Hi all,

I’ve been lurking so far, but I must add my voice here and agree with Richard.

The malleability of Smalltalk tempts people into implementing #asString, #name, 
and similar semantically ambiguous method names. Like Richard, I regretted 
every single time I (or someone else on my team before me) decided to use 
these. It goes back to ’Smalltalk with Style’ (probably the best little red 
book you could ever own): write intention revealing code whenever you can, and 
comment liberally when you can’t.

Jerry Kott
This message has been digitally signed.
PGP Fingerprint:
A9181736DD2F1B6CC7CF9E51AC8514F48C0979A5



> On 11-05-2020, at 2:48 PM, Richard Sargent <rsarg...@5x5.on.ca> wrote:
> 
> 
> 
> On May 11, 2020 2:19:49 PM PDT, Richard O'Keefe <rao...@gmail.com> wrote:
>> I was saying that I expected #($a $b $c) asString ==> 'abc'.
> 
> Over the years, I found myself being opposed to the idea that all objects can 
> sensibly have an #asString implementation. When it's been done, it ultimately 
> caused more problems than it solved.
> 
> Consider $(48 49 50) asString. Do you expect it to give you a string with all 
> the digits? Or perhaps it's meant to interpret the elements as byte-like 
> things, as you would need for "String withAll: aCollection". So, the numbers 
> could be interpreted as codepoints, as they are in a ByteArray.
> 
> But, what does "(Array with: Object new with: ProcessScheduler) asString" 
> mean?
> 
> It seems to me that having all objects understand #asString leads to 
> confusion.
> 
> If you want an array to print as its literal representation, implement 
> #printAsLiteral, so that your intention is clear.
> 
> 
>> If you want something that can be read back, that's what #storeString
>> is for,
>> 
>> On Tue, 12 May 2020 at 01:28, Stéphane Ducasse
>> <stephane.duca...@inria.fr> wrote:
>>> 
>>> 
>>> 
>>> On 5 May 2020, at 16:16, Richard O'Keefe <rao...@gmail.com> wrote:
>>> 
>>> By the way, while playing with this problem, I ran into a moderately
>>> painful issue.
>>> 
>>> There is a reason that Smalltalk has both #printString (to get a
>>> printable representation of an object) and #asString (to convert a
>>> sequence to another kind of sequence with the same elements.)  If I
>>> *want* #printString, I know where to find it.  The definition in my
>>> Smalltalk no reads
>>> 
>>>   asString
>>>     "What should #($a $b $c) do?
>>>     - Blue Book, Inside Smalltalk, Apple Smalltalk-80:
>>>       there is no #asString.
>>>     - ANSI, VW, Dolphin, CSOM:
>>>       #asString is defined on characters and strings
>>>       (and things like file names and URIs that are sort of
>> strings),
>>>       so expect an error report.
>>>     - VisualAge Smalltalk:
>>>       '($a $b $c)'
>>>     - Squeak and Pharo:
>>>       '#($a $b $c)'
>>>     - GNU Smalltalk, Smalltalk/X, and astc:
>>>       'abc'
>>>      I don't intend any gratuitous incompatibility, but when there
>>>      is no consensus to be compatible with, one must pick something,
>>>      and this seems most useful.
>>>     "
>>>     ^String withAll: self
>>> 
>>> Does anyone here know WHY Squeak and Pharo do what they do here?
>>> 
>>> 
>>> Oops I did not see the quotes on my screen..
>>> 
>>> #( a b c) asString
>>>>>> '#(#a #b #c)’
>>> 
>>> this is unclear to me why this is not good but I have no strong
>> opinion
>>> that this is good.
>>> 
>>> I worked on printString for literals because I wanted to have
>>> self evaluating properties for basic literal like in Scheme and
>> others.
>>> where
>>> #t
>>>>>> 
>>> #t
>>> 
>>> And I payed attention that we get the same for literal arrays.
>>> Now the conversion is open to me.
>>> 
>>> #($a $b $c) asString
>>>>>> 
>>> '#($a $b $c)’
>>> 
>>> In fact I do not really understand why a string
>>> 
>>> #($a $b $c) asString would be '(a b c)’
>>> and its use
>>> if this is to nicely display in the ui I would have
>>> displayString doing it.
>>> 
>>> S.
>>> 
>>> 
>>> 
>>> On Wed, 6 May 2020 at 01:20, Richard O'Keefe <rao...@gmail.com>
>> wrote:
>>> 
>>> 
>>> The irony is that the code I was responding to ISN'T obviously
>> correct.
>>> Indeed, I found it rather puzzling.
>>> The problem specification says that the input string may contain
>> digits
>>> AND SPACES.  The original message includes this:
>>> 
>>> Strings of length 1 or less are not valid. Spaces are allowed in the
>>> input, but they should be stripped before checking. All other
>>> non-digit characters are disallowed.
>>> 
>>> Now it isn't clear what "disallowed" means.  I took it to mean "may
>> occur and
>>> should simply mean the input is rejected as invalid."  Perhaps "may
>> not occur"
>>> was the intention.  So we shall not quibble about such characters.
>>> 
>>> But I can't for the life of me figure out how Trygve's code checks
>> for spaces.
>>> One reason this is an issue is that the behaviour of #digitValue is
>> not
>>> consistent between systems.
>>> Character space digitValue
>>>   does not exist in the ANSI standard
>>>   answers -1 in many Smalltalks (which is a pain)
>>>   answers a positive integer that can't be mistake for a digit in my
>> Smalltalk
>>>   raises an exception in some Smalltalks.
>>> 
>>> This is a comment I now have in my Smalltalk library for #digitValue
>>>     "This is in the Blue Book, but unspecified on non-digits.
>>>      Squeak, Pharo, Dolphin, VW, VAST, and Apple Smalltalk-80
>>>      answer -1 for characters that are not digits (or ASCII
>> letters),
>>>      which is unfortunate but consistent with Inside Smalltalk
>>>      which specifies this result for non-digits.
>>>      ST/X and GST raise an exception which is worse.
>>>      Digitalk ST/V documentation doesn't specify the result.
>>>      This selector is *much* easier to use safely if it
>>>      returns a 'large' (>= 36) value for non-digits."
>>> 
>>> Let's compare three versions, the two I compared last time,
>>> and the "version A" code I discussed before, which to my mind
>>> is fairly readable.
>>> 
>>> "Don't add slowness": 1 (normalised time)
>>> "Trygve's code":  6.5
>>> "High level code": 30.6 (or 4.7 times slower than Trygve's)
>>> 
>>> Here's the "High level code".
>>>     ^(aString allSatisfy: [:each | each isSpace or: [each isDigit]])
>> and: [
>>>       |digitsReverse|
>>>       digitsReverse := (aString select: [:each | each isDigit])
>> reverse.
>>>       digitsReverse size > 1 and: [
>>>         |evens odds evenSum oddSum|
>>>         odds  := digitsReverse withIndexSelect: [:y :i | i odd].
>>>         evens := digitsReverse withIndexSelect: [:x :i | i even].
>>>         oddSum  := odds  detectSum: [:y | y digitValue].
>>>         evenSum := evens detectSum: [:x |
>>>                      #(0 2 4 6 8 1 3 5 7 9) at: x digitValue + 1].
>>>         (oddSum + evenSum) \\ 10 = 0]]
>>> 
>>> This is the kind of code I was recommending that Roelof write.
>>> 
>>> As a rough guide, by counting traversals (including ones inside
>> existing
>>> methods), I'd expect the "high level" code to be at least 10 times
>> slower
>>> than the "no added slowness" code.
>>> 
>>> We are in vehement agreement that there is a time to write high level
>>> really obvious easily testable and debuggable code, and that's most
>>> of the time, especially with programming exercises.
>>> 
>>> I hope that we are also in agreement that factors of 30 (or even 6)
>>> *can* be a serious problem.  I mean, if I wanted something that slow,
>>> I'd use Ruby.
>>> 
>>> I hope we are also agreed that (with the exception of investigations
>>> like this one) the time to hack on something to make it faster is
>> AFTER
>>> you have profiled it and determined that you have a problem.
>>> 
>>> But I respectfully suggest that there is a difference taking slowness
>> OUT
>>> and simply not going out of your way to add slowness in the first
>> place.
>>> 
>>> I'd also like to remark that my preference for methods that traverse
>> a
>>> sequence exactly once has more to do with Smalltalk protocols than
>>> with efficiency.  If the only method I perform on an object is #do:
>>> the method will work just as well for readable streams as for
>>> collections.  If the only method I perform on an object is
>> #reverseDo:
>>> the method will work just as well for Read[Write]Streams as for
>>> SequenceReadableCollections, at least in my library.   It's just like
>>> trying to write #mean so that it works for Durations as well as
>> Numbers.
>>> 
>>> Oh heck, I suppose I should point out that much of the overheads in
>>> this case could be eliminated by a Self-style compiler doing dynamic
>>> inlining + loop fusion.    There's no reason *in principle*, given
>> enough
>>> people, money, and time, that the differences couldn't be greatly
>>> reduced in Pharo.
>>> 
>>> On Tue, 5 May 2020 at 21:50, Trygve Reenskaug <tryg...@ifi.uio.no>
>> wrote:
>>> 
>>> 
>>> Richard,
>>> 
>>> Thank you for looking at the code. It is comforting to learn that the
>> code has been executed for a large number of examples without breaking.
>> The code is not primarily written for execution but for being read and
>> checked by the human end user. It would be nice if we could also check
>> that it gave the right answers, but I don't know how to do that.
>>> 
>>> The first question is: Can a human domain expert read the code and
>> sign their name for its correctness?
>>> 
>>> 
>>> When this is achieved, a programming expert will transcribe the first
>> code to a professional quality program. This time, the second code
>> should be reviewed by an independent programmer who signs their name
>> for its correct transcription from the first version.
>>> 
>>> --Trygve
>>> 
>>> PS: In his 1991 Turing Award Lecture, Tony Hoare said: "There are two
>> ways of constructing a software design: One way is to make it so simple
>> that there are obviously no deficiencies and the other is to make it so
>> complicated that there are no obvious deficiencies. The first method is
>> far more difficult."
>>> 
>>> --Trygve
>>> 
>>> On tirsdag.05.05.2020 04:41, Richard O'Keefe wrote:
>>> 
>>> As a coding experiment, I adapted Trygve  Reenskoug's code to my
>>> Smalltalk compiler, put in my code slightly tweaked, and benchmarked
>>> them on randomly generated data.
>>> 
>>> Result: a factor of 6.3.
>>> 
>>> In Squeak it was a factor of ten.
>>> 
>>> I had not, in all honesty, expected it to to be so high.
>>> 
>>> On Tue, 5 May 2020 at 02:00, Trygve Reenskaug <tryg...@ifi.uio.no>
>> wrote:
>>> 
>>> A coding experiment.
>>> Consider a Scrum development environment. Every programming team has
>> an end user as a member.
>>> The team's task is to code a credit card validity check.
>>> A first goal is that the user representative shall read the code and
>> agree that it is a correct rendering of their code checker:
>>> 
>>>   luhnTest: trialNumber
>>>       | s1 odd s2 even charValue reverse |
>>> -----------------------------------------------
>>> " Luhn test according to Rosetta"
>>> "Reverse the order of the digits in the number."
>>>   reverse := trialNumber reversed.
>>> "Take the first, third, ... and every other odd digit in the reversed
>> digits and sum them to form the partial sum s1"
>>>   s1 := 0.
>>>   odd := true.
>>>   reverse do:
>>>       [:char |
>>>           odd
>>>               ifTrue: [
>>>                   s1 := s1 + char digitValue.
>>>               ].
>>>               odd := odd not
>>>       ].
>>> "Taking the second, fourth ... and every other even digit in the
>> reversed digits:
>>> Multiply each digit by two and sum the digits if the answer is
>> greater than nine to form partial sums for the even digits"
>>>   "The subtracting 9 gives the same answer. "
>>> "Sum the partial sums of the even digits to form s2"
>>>   s2 := 0.
>>>   even := false.
>>>   reverse do:
>>>       [:char |
>>>           even
>>>               ifTrue: [
>>>                   charValue := char digitValue * 2.
>>>                   charValue > 9 ifTrue: [charValue := charValue -
>> 9].
>>>                   s2 := s2 + charValue
>>>               ].
>>>               even := even not
>>>       ].
>>> "If s1 + s2 ends in zero then the original number is in the form of a
>> valid credit card number as verified by the Luhn test."
>>>   ^(s1 + s2) asString last = $0
>>> ---------------------------------
>>> Once this step is completed, the next step will be to make the code
>> right without altering the algorithm (refactoring). The result should
>> be readable and follow the team's conventions.
>>> 
>>> 
>>> P.S. code attached.
>>> 
>>> 
>>> --
>>> 
>>> The essence of object orientation is that objects collaborate  to
>> achieve a goal.
>>> Trygve Reenskaug      mailto: tryg...@ifi.uio.no
>>> Morgedalsvn. 5A       http://folk.uio.no/trygver/
>>> N-0378 Oslo             http://fullOO.info
>>> Norway                     Tel: (+47) 468 58 625
>>> 
>>> 
>>> 
>>> --------------------------------------------
>>> Stéphane Ducasse
>>> http://stephane.ducasse.free.fr / http://www.pharo.org
>>> 03 59 35 87 52
>>> Assistant: Julie Jonas
>>> FAX 03 59 57 78 50
>>> TEL 03 59 35 86 16
>>> S. Ducasse - Inria
>>> 40, avenue Halley,
>>> Parc Scientifique de la Haute Borne, Bât.A, Park Plaza
>>> Villeneuve d'Ascq 59650
>>> France
>>> 
> 
> 

Attachment: signature.asc
Description: Message signed with OpenPGP

Reply via email to