For what it's worth, here's a moderately thorough examination of several
different Smalltalk systems.
Let A = astc, D = Dolphin, G = GNU Smalltalk, Q = Squeak,
    S = ANSI standard, T = Strongtalk, V = VisualWorks, X = ST/X

#asString

ADGPQST!X  Character => String with: self
ADGPQSTVX  String => self
ADGPQSTVX  Symbol => String withAll: self
.........  Text/Paragraph, where provided, => underlying string.
A-G-----X  Collection => String withAll: self
---PQ----  Collection => self printString
A........  ByteArray => "decoded as Unicode"
.DGPQ-TVX  ByteArray => "decoded as Latin1"
ADG.Q..VX  Filename => "unparse (Filename, FilePath, whatever)
AdgpQ.TVX  URI => "unparse (ZnUrl in P)
Ad.PQ...X  UUID => "unparse (d, GUID equivalent)"
.DGpq...X  Number => self displayString "or self printString, maybe via
Object"
...PQ...X  Object => self printString

There's a rough consensus here:
 - if something *is* textual (Character, String, Symbol, Text,
   Paragraph) #asString returns it as a normal string
 - if something is a parsed form of structured text (file name,
   URI, UUID) its unparsed form is returned, converting it back
   should yield an equal parsed form
 - if something is a byte array, it may be converted to a string
   (the rule is to preserve the bytes, my library presumes byte
   arrays are UTF8-encoded)
 - if numbers are accepted at all, their #printString is returned
 - if is none of the above, but has a #name or #title, that is
   commonly the result.

The open question is what converting an array of characters using
#asString will do.  There is at least one Smalltalk out there
where #(65 66 67) asString => 'ABC', but that's a step further
than I personally want, though it is consistent with ByteArray.




On Tue, 12 May 2020 at 11:16, Jerry Kott <jk...@image-ware.com> wrote:

> 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
>
>
>
>
>

Reply via email to