Entirely against my will, I once worked in a perl shop, and I noticed that perlites liked joining things.
Whenever I find myself wanting to join a bunch of items together (e.g. to make a path) I am never satisfied with the result and so I took a look at the Collections/String classes to see whether anything fitted nicely.
I came up with
SequencableCollection>>join: aCollection
^ self class streamContents: [ :stream | aCollection do: [ :each | stream nextPut: each ] separatedBy: [ stream nextPutAll: self ] ]
and
Character>>join: aCollectionOfStrings
^ self class streamContents: [ :stream | aCollectionOfStrings do: [ :each | stream nextPutAll: each ] separatedBy: [ stream nextPut: self ] ]
and
Collection>>joinWith: aCollection
aCollection join: self
---- This now allows
(Array with: 1 with: 2) join: (Array with: 3 with: 4 with: 5) $/ join: (Array with: 'Hello' with: 'my' with: 'World').
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
Keith
___________________________________________________________ The all-new Yahoo! Mail goes wherever you go - free your email address from your Internet provider. http://uk.docs.yahoo.com/nowyoucan.html
On 14-Sep-06, at 4:57 PM, Keith Hodges wrote:
Entirely against my will, I once worked in a perl shop, and I noticed that perlites liked joining things.
Whenever I find myself wanting to join a bunch of items together (e.g. to make a path) I am never satisfied with the result and so I took a look at the Collections/String classes to see whether anything fitted nicely.
Well, first point is that you shouldn't make paths like that. Filenames are *not* strings. If you use constructs like FileDirectory default directoryNamed:'foo' you'd get a properly (well, as properly as we can manage right now) made file directory object with a properly formed pathname. It would handle platform path separator issues, for example.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim The generation of random numbers is too important to be left to chance.
In answer to your first point, I was not intending to use join for that, it was 'only' an example.
To be honest I dont think much of Squeak's directory/path classes I contributed to a nice ruby 'Path' module about 5 years ago which was quite elegant.
Keith
___________________________________________________________ To help you stay safe and secure online, we've developed the all new Yahoo! Security Centre. http://uk.security.yahoo.com
Hi Keith,
on Fri, 15 Sep 2006 01:57:52 +0200, wrote: ...
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
There are several reasons for the absence of #join:
- the most important one is, that nobody needs it (or else you would have found it). Imagine Pearl with the full Squeak Stream hierarchy, why use join?
- streaming is more flexible when you keep control, it allows better maintainable and adaptable code.
- #join: must be implemented in *base* classes in order to work. String streamContents: [:...] must not be implemented anywhere, it's always where want need it.
Just my CHF 0.05
/Klaus
Keith
On Sep 14, 2006, at 6:25 PM, Klaus D. Witzel wrote:
Hi Keith,
on Fri, 15 Sep 2006 01:57:52 +0200, wrote: ...
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
There are several reasons for the absence of #join:
- the most important one is, that nobody needs it (or else you
would have found it). Imagine Pearl with the full Squeak Stream hierarchy, why use join?
Sure we need it. At Smallthought, we have a package of utility methods that includes:
SequencableCollection>>joinTokens: aString ^ String streamContents: [:s | self do: [:ea | s nextPutAll: ea asString] separatedBy: [s nextPutAll: aString]]
Looking through my sends to it, the argument is always either ' ' or ', ', so #joinedWithSpaces and #joinedWithCommas would probably be sensible methods to have too.
Avi
Hi Avi,
on Fri, 15 Sep 2006 03:31:02 +0200, wrote:
On Sep 14, 2006, at 6:25 PM, Klaus D. Witzel wrote:
Hi Keith, on Fri, 15 Sep 2006 01:57:52 +0200, wrote: ...
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
There are several reasons for the absence of #join:
- the most important one is, that nobody needs it (or else you would
have found it). Imagine Pearl with the full Squeak Stream hierarchy, why use join?
Sure we need it. At Smallthought, we have a package of utility methods that includes:
SequencableCollection>>joinTokens: aString ^ String streamContents: [:s | self do: [:ea | s nextPutAll: ea asString] separatedBy: [s nextPutAll: aString]]
Looking through my sends to it, the argument is always either ' ' or ', ', so #joinedWithSpaces and #joinedWithCommas would probably be sensible methods to have too.
No nitpicking intended, the question and the answer was from the perspective why Squeak doesn't have it.
But you're right, one counterexample brings my nobody case to fall :)
/Klaus
Avi
Thanks Avi,
thats just the method that I was looking for! So please let's get it added to the base image ;-)
This request is somewhat academic since I am stuck in 3.8 for a while until Magma supports 3.9.
Keith
- the most important one is, that nobody needs it (or else you would
have found it). Imagine Pearl with the full Squeak Stream hierarchy, why use join?
Sure we need it. At Smallthought, we have a package of utility methods that includes:
SequencableCollection>>joinTokens: aString ^ String streamContents: [:s | self do: [:ea | s nextPutAll: ea asString] separatedBy: [s nextPutAll: aString]]
Looking through my sends to it, the argument is always either ' ' or ', ', so #joinedWithSpaces and #joinedWithCommas would probably be sensible methods to have too.
Avi
___________________________________________________________ All new Yahoo! Mail "The new Interface is stunning in its simplicity and ease of use." - PC Magazine http://uk.docs.yahoo.com/nowyoucan.html
Sure we need it. At Smallthought, we have a package of utility methods that includes:
SequencableCollection>>joinTokens: aString ^ String streamContents: [:s | self do: [:ea | s nextPutAll: ea asString] separatedBy: [s nextPutAll: aString]]
Looking through my sends to it, the argument is always either ' ' or ', ', so #joinedWithSpaces and #joinedWithCommas would probably be sensible methods to have too.
Avi
Funny, one of the first extension methods I added when I learned Smalltalk, was join as well, I'm still amazed it isn't already there. I got tired of typing out the stream version, and in all but one case, I was also joining on either ' ' or ', '.
Collection>>join: aString ^String streamContents: [:stream | self do: [:each | stream nextPutAll: each] separatedBy: [stream nextPutAll: aString]]
Avi, is there a reason you chose SequencableColleciton over just Collection, I'm curious if I've put mine in the wrong place, and the implications of doing so?
On Sep 14, 2006, at 8:44 PM, Ramon Leon wrote:
Avi, is there a reason you chose SequencableColleciton over just Collection, I'm curious if I've put mine in the wrong place, and the implications of doing so?
Only that the output is deterministic for a SequenceableCollection and not for, say, a Set.
Avi
Poking around a frequently used image I find:
String>>splitOn: aString and SequenceableCollection>>joinOn: aString
And I use them quite a bit when processing input.
On Sep 14, 2006, at 6:31 PM, Avi Bryant wrote:
On Sep 14, 2006, at 6:25 PM, Klaus D. Witzel wrote:
Hi Keith,
on Fri, 15 Sep 2006 01:57:52 +0200, wrote: ...
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
There are several reasons for the absence of #join:
- the most important one is, that nobody needs it (or else you
would have found it). Imagine Pearl with the full Squeak Stream hierarchy, why use join?
Sure we need it. At Smallthought, we have a package of utility methods that includes:
SequencableCollection>>joinTokens: aString ^ String streamContents: [:s | self do: [:ea | s nextPutAll: ea asString] separatedBy: [s nextPutAll: aString]]
Looking through my sends to it, the argument is always either ' ' or ', ', so #joinedWithSpaces and #joinedWithCommas would probably be sensible methods to have too.
Avi
Poking around a frequently used image I find:
String>>splitOn: aString and SequenceableCollection>>joinOn: aString
And I use them quite a bit when processing input.
Care to share your #splitOn:, my #split: was just a synonym for #findTokens: which I recently realized didn't do what I thought it did.
OK
splitOn: aString
| idx lastIdx | idx := lastIdx := 1.
^Array streamContents: [:s | [idx <= self size] whileTrue: [ idx := self findString: aString startingAt: lastIdx. idx = 0 ifTrue: [idx := self size + 1]. s nextPut: (self copyFrom: lastIdx to: idx-1). lastIdx := idx + aString size. ] ]
On Sep 14, 2006, at 8:48 PM, Ramon Leon wrote:
Poking around a frequently used image I find: String>>splitOn: aString and SequenceableCollection>>joinOn: aString And I use them quite a bit when processing input.
Care to share your #splitOn:, my #split: was just a synonym for #findTokens: which I recently realized didn't do what I thought it did.
splitOn: aString
| idx lastIdx | idx := lastIdx := 1. ^Array streamContents: [:s | [idx <= self size] whileTrue: [ idx := self findString: aString startingAt: lastIdx. idx = 0 ifTrue: [idx := self size + 1]. s nextPut: (self copyFrom: lastIdx to: idx-1). lastIdx := idx + aString size. ] ]
Cool, thanks.
Avi Bryant avi.bryant@gmail.com writes:
Sure we need it. At Smallthought, we have a package of utility methods that includes:
SequencableCollection>>joinTokens: aString
Scala's library has a similar method. I thought it was the silliest, overly specific method I've seen, but then I keep finding myself using it!
Looking through my sends to it, the argument is always either ' ' or ', ', so #joinedWithSpaces and #joinedWithCommas would probably be sensible methods to have too.
This is my experience, too.
It seems people just cannot resist the urge to generalize this method more than is useful. We've all taken too *many* programming classes, and are overlooking some pragmatics!
Scala's method is actually more general than the join: methods being passed around -- it takes in an initial string and a final string as arguments -- but I find myself always setting those to the empty string...
-Lex
Oscar and Damien did an implementation of join and split and I would really like to ease perl people and include such protocols in the next release (with tests) Now if would be nice to have a discussion on the implementations
http://bugs.impara.de/view.php?id=4874
I came up with
SequencableCollection>>join: aCollection
^ self class streamContents: [ :stream | aCollection do: [ :each | stream nextPut: each ] separatedBy: [ stream nextPutAll: self ] ]
and
Character>>join: aCollectionOfStrings
^ self class streamContents: [ :stream | aCollectionOfStrings do: [ :each | stream nextPutAll: each ] separatedBy: [ stream nextPut: self ] ]
and
Collection>>joinWith: aCollection
aCollection join: self
This now allows (Array with: 1 with: 2) join: (Array with: 3 with: 4 with: 5) $/ join: (Array with: 'Hello' with: 'my' with: 'World').
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
Keith
___________________________________________________________ The all- new Yahoo! Mail goes wherever you go - free your email address from your Internet provider. http://uk.docs.yahoo.com/nowyoucan.html
I'll just mention that mine are modeled on the NextStep routines
NSString>>componentsSeparatedByString: NSArray>>componentsJoinedByString:
they behave exactly the same way.
On Sep 15, 2006, at 8:37 AM, stephane ducasse wrote:
Oscar and Damien did an implementation of join and split and I would really like to ease perl people and include such protocols in the next release (with tests) Now if would be nice to have a discussion on the implementations
http://bugs.impara.de/view.php?id=4874
I came up with
SequencableCollection>>join: aCollection
^ self class streamContents: [ :stream | aCollection do: [ :each | stream nextPut: each ] separatedBy: [ stream nextPutAll: self ] ]
and
Character>>join: aCollectionOfStrings
^ self class streamContents: [ :stream | aCollectionOfStrings do: [ :each | stream nextPutAll: each ] separatedBy: [ stream nextPut: self ] ]
and
Collection>>joinWith: aCollection
aCollection join: self
This now allows (Array with: 1 with: 2) join: (Array with: 3 with: 4 with: 5) $/ join: (Array with: 'Hello' with: 'my' with: 'World').
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
Keith
___________________________________________________________ The all-new Yahoo! Mail goes wherever you go - free your email address from your Internet provider. http://uk.docs.yahoo.com/nowyoucan.html
On 9/15/06, Todd Blanchard tblanchard@mac.com wrote:
I'll just mention that mine are modeled on the NextStep routines
NSString>>componentsSeparatedByString: NSArray>>componentsJoinedByString:
Are you using an Objective-C bridge here ?
No, I just reproduced their behavior in Squeak.
On Sep 15, 2006, at 9:29 AM, Damien Pollet wrote:
On 9/15/06, Todd Blanchard tblanchard@mac.com wrote:
I'll just mention that mine are modeled on the NextStep routines
NSString>>componentsSeparatedByString: NSArray>>componentsJoinedByString:
Are you using an Objective-C bridge here ?
-- Damien Pollet type less, do more
stephane ducasse wrote:
Oscar and Damien did an implementation of join and split and I would really like to ease perl people and include such protocols in the next release (with tests) Now if would be nice to have a discussion on the implementations
I've also had a brush with Perl, so was looking for join/split too. Here's what I have. Notice that split: expects a charater argument. IIRC, the reason I did that was to make it easier to implement the equivalent method on VAST. Also, the joinWith: doesn't use nextPutAll:separatedBy: so I could easily implement an equivalent method in VAST and VW.
SequenceableCollection joinWith: separator "Answer a string with elements converted to strings and separated by separator."
| ws | ws := WriteStream on: (String new: 100). self withIndexDo: [:each :i | ws nextPutAll: each asString. i < self size ifTrue: [ ws nextPutAll: separator ]. ]. ^ws contents
String>>split: ch | pieces i prev | pieces := OrderedCollection new. i := 0. [(i := self indexOf: ch startingAt: (prev := i + 1)) == 0] whileFalse: [prev < i ifTrue: [pieces add: (self copyFrom: prev to: i - 1)]. prev == i ifTrue: [pieces add: String new]]. prev <= self size ifTrue: [pieces add: (self copyFrom: prev to: self size)]. (self isEmpty not and: [self last = ch]) ifTrue: [pieces add: String new]. ^pieces
I think that join: should be more than a simple string generator. Using the power of Smalltalk collections you will find all sorts of wierd and wonderful operators that work on all manner of collections, and I think that join: should demonstrate some of this power.
avi's joinTokens: aStringToken does just what it say it does, it just creates a string. Simple and unambiguous.
My proposed join: implementation is able to do much more, but there are some ambiguities as to what behaviour is desired/obtained. I have no idea what other Smalltalks do but here are my ideas so far:
Character-useTojoin: result will be a string. String-useToJoin: result will be a string. $/ useToJoin: #('hello' 'my' 'world') -> 'hello/my/world' ', ' useToJoin: #('hello' my' 'world') -> 'hello, my, world'
SequencableCollection-useToJoin result will be a SequencableCollection. #(1 2) useToJoin: #(3 4 5) -> #(3 1 2 4 1 2 5)
The double dispatch approach can be used.
#('hello' 'my' world') joinUsing: $/
SequenceableCollestion>>joinUsing: joiner ^ joiner useToJoin: self
---- ideas:
useToJoin: <-> joinUsing: join: <-> joinWith:
Keith
___________________________________________________________ NEW Yahoo! Cars - sell your car and browse thousands of new and used cars online! http://uk.cars.yahoo.com/
The question as to whether split: should work with Strings or Regex's is something that should be handled with a double dispatch. If you feed it a String it should use a string if you feed it a Regex then it will use a Regex.
eg := 'Now is the time for all good men to come to the aid of the party'.
eg splitOnEvery: 'the' eg splitOnEvery: ( '+[\s]' asRegex ). eg splitOnEvery: $e. #(1 2 3 4 5 6 7 8 9) splitOnEvery: #(4). #(1 2 3 4 5 6 7 8 9) splitOnEvery: #(4 5 6). #(1 2 3 4 5 6 7 8 9) splitOnEvery: [ :n | n isPrimeNumber ]
SequencableCollection>>splitOnEvery: aSpliter ^aSpliter splitUp: self
aRegex>>splitUp: aString. ...regex implementation aString>>splitUp: aString. ...string implementation aCharacter>>splitUp: aString. ...character implementation aSequencableCollection>>splitUp: aSequencableCollection ... generic collection implementation. aMonadicBlock>>splitOnEvery: thing ^ thing splitUsing: aBlock.
more ideas
Keith
In my viewer I saw two spaces at "the party". So what should happen for #split: on a single space. Should there be an extra item with value nil or an empty string? Or should there be no extra item?
I think that the convention is to return an empty string. -> #('the' '' 'party')
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
keep trying to find a fix point with a nice solution and tests ;)
Stef
On 16 sept. 06, at 03:20, Keith Hodges wrote:
The question as to whether split: should work with Strings or Regex's is something that should be handled with a double dispatch. If you feed it a String it should use a string if you feed it a Regex then it will use a Regex.
eg := 'Now is the time for all good men to come to the aid of the party'.
eg splitOnEvery: 'the' eg splitOnEvery: ( '+[\s]' asRegex ). eg splitOnEvery: $e. #(1 2 3 4 5 6 7 8 9) splitOnEvery: #(4). #(1 2 3 4 5 6 7 8 9) splitOnEvery: #(4 5 6). #(1 2 3 4 5 6 7 8 9) splitOnEvery: [ :n | n isPrimeNumber ]
SequencableCollection>>splitOnEvery: aSpliter ^aSpliter splitUp: self aRegex>>splitUp: aString. ...regex implementation aString>>splitUp: aString. ...string implementation aCharacter>>splitUp: aString. ...character implementation aSequencableCollection>>splitUp: aSequencableCollection ... generic collection implementation. aMonadicBlock>>splitOnEvery: thing ^ thing splitUsing: aBlock.
more ideas
Keith
In my viewer I saw two spaces at "the party". So what should happen for #split: on a single space. Should there be an extra item with value nil or an empty string? Or should there be no extra item?
I think that the convention is to return an empty string. -> # ('the' '' 'party')
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
And here is my vote for split.
From: Keith Hodges keith_hodges@yahoo.co.uk Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org Subject: Re: split: Date: Sat, 16 Sep 2006 02:20:17 +0100
The question as to whether split: should work with Strings or Regex's is something that should be handled with a double dispatch. If you feed it a String it should use a string if you feed it a Regex then it will use a Regex.
eg := 'Now is the time for all good men to come to the aid of the party'.
eg splitOnEvery: 'the' eg splitOnEvery: ( '+[\s]' asRegex ). eg splitOnEvery: $e. #(1 2 3 4 5 6 7 8 9) splitOnEvery: #(4). #(1 2 3 4 5 6 7 8 9) splitOnEvery: #(4 5 6). #(1 2 3 4 5 6 7 8 9) splitOnEvery: [ :n | n isPrimeNumber ]
SequencableCollection>>splitOnEvery: aSpliter ^aSpliter splitUp: self
aRegex>>splitUp: aString. ...regex implementation aString>>splitUp: aString. ...string implementation aCharacter>>splitUp: aString. ...character implementation aSequencableCollection>>splitUp: aSequencableCollection ... generic collection implementation. aMonadicBlock>>splitOnEvery: thing ^ thing splitUsing: aBlock.
more ideas
Keith
In my viewer I saw two spaces at "the party". So what should happen for #split: on a single space. Should there be an extra item with value nil or an empty string? Or should there be no extra item?
I think that the convention is to return an empty string. -> #('the' '' 'party')
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
Keith Hodges wrote:
I think that join: should be more than a simple string generator. Using the power of Smalltalk collections you will find all sorts of wierd and wonderful operators that work on all manner of collections, and I think that join: should demonstrate some of this power.
A potential problem is that *if* the results depend on particular quirks of Squeak, then trying to do the equivalent in another Smalltalk becomes difficult. Seaside runs in VW (and Dolphin) too, so portability is important. We don't want to diverge in a way that makes frameworks & components built for Seaside in one Smalltalk, difficult to port to other Smalltalks.
Having said that, I'll be happy with whatever covers my use case, and isn't so general or complicated that we can't agree on what the correct result ought to be. Otherwise, I can always rename my methods.
Ok, I went and dug it up. I think this was the best proposal for adding "join" to Squeak 3.10.
From: Keith Hodges keith_hodges@yahoo.co.uk Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org Subject: Re: join Date: Sat, 16 Sep 2006 01:54:50 +0100
I think that join: should be more than a simple string generator. Using the power of Smalltalk collections you will find all sorts of wierd and wonderful operators that work on all manner of collections, and I think that join: should demonstrate some of this power.
avi's joinTokens: aStringToken does just what it say it does, it just creates a string. Simple and unambiguous.
My proposed join: implementation is able to do much more, but there are some ambiguities as to what behaviour is desired/obtained. I have no idea what other Smalltalks do but here are my ideas so far:
Character-useTojoin: result will be a string. String-useToJoin: result will be a string. $/ useToJoin: #('hello' 'my' 'world') -> 'hello/my/world' ', ' useToJoin: #('hello' my' 'world') -> 'hello, my, world'
SequencableCollection-useToJoin result will be a SequencableCollection. #(1 2) useToJoin: #(3 4 5) -> #(3 1 2 4 1 2 5)
The double dispatch approach can be used.
#('hello' 'my' world') joinUsing: $/
SequenceableCollestion>>joinUsing: joiner ^ joiner useToJoin: self
ideas:
useToJoin: <-> joinUsing: join: <-> joinWith:
Keith
___________________________________________________________ NEW Yahoo! Cars
- sell your car and browse thousands of new and used cars online!
Thanks JJ, I think I prefer this option overall. Sorry I just havent had any time to do anything about writing tests etc as requested.
Keith
J J wrote:
Ok, I went and dug it up. I think this was the best proposal for adding "join" to Squeak 3.10.
From: Keith Hodges keith_hodges@yahoo.co.uk Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org Subject: Re: join Date: Sat, 16 Sep 2006 01:54:50 +0100
I think that join: should be more than a simple string generator. Using the power of Smalltalk collections you will find all sorts of wierd and wonderful operators that work on all manner of collections, and I think that join: should demonstrate some of this power.
avi's joinTokens: aStringToken does just what it say it does, it just creates a string. Simple and unambiguous.
My proposed join: implementation is able to do much more, but there are some ambiguities as to what behaviour is desired/obtained. I have no idea what other Smalltalks do but here are my ideas so far:
Character-useTojoin: result will be a string. String-useToJoin: result will be a string. $/ useToJoin: #('hello' 'my' 'world') -> 'hello/my/world' ', ' useToJoin: #('hello' my' 'world') -> 'hello, my, world'
SequencableCollection-useToJoin result will be a SequencableCollection. #(1 2) useToJoin: #(3 4 5) -> #(3 1 2 4 1 2 5)
The double dispatch approach can be used.
#('hello' 'my' world') joinUsing: $/
SequenceableCollestion>>joinUsing: joiner ^ joiner useToJoin: self
ideas:
useToJoin: <-> joinUsing: join: <-> joinWith:
Keith
___________________________________________________________ Try the all-new Yahoo! Mail. "The New Version is radically easier to use" The Wall Street Journal http://uk.docs.yahoo.com/nowyoucan.html
hi guys
could you sit down and propose a cool set of names and implementation and we include it in 3.10
Hi Folks,
Let me summarize my thoughts on the topic of split and join.
General: - As far as I can tell, neither split: nor join: can be easily simulated by existing methods
On split: - split: is fairly specific to strings, though it could be generalized to other kinds of Sequenceables - split: should take a String, not a Character, as its argument (as in Ruby & friends) - generally speaking, the argument to split: should be a Regex, so it makes sense to make String>>split: an extension to String from the regex package (i.e., VB-Regex) - string-matching is a well-known problem, so we should avoid ad hoc solutions. See for example http://doi.acm.org/10.1145/360825.360855 For this reason I think that split: should depend on VB-Regex, unless someone want's to implement one of the modern algoirthms
I propose that: String>>split: ^ regexString asRegex split: self As follows
Regex>>split: aString | result lastPosition | result := OrderedCollection new. stream := aString readStream. lastPosition := stream position. [ self searchStream: stream ] whileTrue: [ result add: (aString copyFrom: lastPosition+1 to: (self subBeginning: 1)). self assert: lastPosition < stream position description: 'Regex cannot match null string'. lastPosition := stream position ]. result add: (aString copyFrom: lastPosition+1 to: aString size). ^ result
NB: - Assertion is needed to avoid infinite loops in case of null Regex.
On join: - join: is the conceptual inverse of split: (see the tests in http:// squeaksource.com/RubyShards/) - join: obviously works for Sequenceables as well as Strings
I propose adding the following method to either SequenceableCollection or OrderedCollection [the tradeoff is not clear to me].
join: anOrderedCollection "Implicit precondition: my elements are all OrderedCollections" | result index | result := (self at: 1) writeStream. result nextPutAll: (self at: 1). index := 2. [index <= self size] whileTrue: [ result nextPutAll: anOrderedCollection. result nextPutAll: (self at: index). index := index + 1. ]. ^ result contents
This will clearly work not only for Strings but for other kinds of collections too.
SplitJoinTest>>setUp eg := 'Now is the time for all good men to come to the aid of the party'.
SplitJoinTest>>testJoin self assert: ((eg split: 'the') join: 'the') = eg. self assert: ({ {1. 2}. {4. 5} } asOrderedCollection join: {3}) = {1. 2. 3. 4. 5}.
Is anyone convinced?
Oscar
On Sep 15, 2006, at 17:40, stephane ducasse wrote:
hi guys
could you sit down and propose a cool set of names and implementation and we include it in 3.10
Is anyone convinced?
I'm sure someone is convinced but probably not everyone ;-) Couple of notes:
For this reason I think that split: should depend on VB-Regex, unless someone want's to implement one of the modern algoirthms
I propose that: String>>split: ^ regexString asRegex split: self
I don't like this too much as it means there is special meaning to the search pattern (wildcards and the like) and it requires a non-optional dependency on a regex package. Perhaps the simple string split should remain the simple string split and the regex string split should remain in regex?
On join:
- join: is the conceptual inverse of split: (see the tests in
http://squeaksource.com/RubyShards/)
- join: obviously works for Sequenceables as well as Strings
I propose adding the following method to either SequenceableCollection or OrderedCollection [the tradeoff is not clear to me].
OrderedCollection makes little sense since you couldn't join: arrays or strings in that case so it should go into SequenceableCollection.
join: anOrderedCollection
It would be good to give this a role instead of a type name. From the type name it's not immediately obvious whether: 'abc' join: 'xyz' results in 'axyzbxyzc' or 'xabcyabcz'.
"Implicit precondition: my elements are all OrderedCollections"
The precondition should probably be that "receiver species = argument species" and consequently determine the result species.
Cheers, - Andreas
Andreas Raab andreas.raab@gmx.de writes:
join: anOrderedCollection
It would be good to give this a role instead of a type name. From the type name it's not immediately obvious whether: 'abc' join: 'xyz' results in 'axyzbxyzc' or 'xabcyabcz'.
Yeah, you can only learn the behavior by experience. It would be better if the name just gave away the behavior.
"Implicit precondition: my elements are all OrderedCollections"
The precondition should probably be that "receiver species = argument species" and consequently determine the result species.
Actually, it might be nice to make this produce *strings*. That's what most people seem to want the method for. It's hard to think of a good name that is shorter than the implementation, but maybe:
joinStringsWith: printStrings: makeString:
Join is popular for people who use Perl, but it seems weird if there's a print involved in the method. printStrings: can be misread in several ways, e.g. does it return the print strings? Does it print the argument's elmeents, which are expected to be strings?
I lean towards makeString:, though I admit I have different and warped experience that makes this one look familiar to me. That said, makeString: does tell you the most important thing about the method-- it flattens the receiver into a string. It is vague about how it does it, but in most use cases the reader can guess (foo makeString: ', ').
-Lex
Join is popular for people who use Perl, but it seems weird
And Python, Ruby, JavaScript, CSharp, and Visual Basic.Net. Split and join are the common names in most languages that use them.
if there's a print involved in the method. printStrings: can be misread in several ways, e.g. does it return the print strings? Does it print the argument's elmeents, which are expected to be strings?
I lean towards makeString:, though I admit I have different and warped experience that makes this one look familiar to me. That said, makeString: does tell you the most important thing about the method-- it flattens the receiver into a string. It is vague about how it does it, but in most use cases the reader can guess (foo makeString: ', '). -Lex
They should be called #split: and #join:, no need to hide them under other names when all newcomers are going to be looking for #split: and #join:. Let's not be different, just to be different.
+ 1
Stef
On 18 sept. 06, at 17:38, Ramon Leon wrote:
Join is popular for people who use Perl, but it seems weird
And Python, Ruby, JavaScript, CSharp, and Visual Basic.Net. Split and join are the common names in most languages that use them.
if there's a print involved in the method. printStrings: can be misread in several ways, e.g. does it return the print strings? Does it print the argument's elmeents, which are expected to be strings?
I lean towards makeString:, though I admit I have different and warped experience that makes this one look familiar to me. That said, makeString: does tell you the most important thing about the method-- it flattens the receiver into a string. It is vague about how it does it, but in most use cases the reader can guess (foo makeString: ', '). -Lex
They should be called #split: and #join:, no need to hide them under other names when all newcomers are going to be looking for #split: and #join:. Let's not be different, just to be different.
"Ramon Leon" ramon.leon@allresnet.com writes:
Join is popular for people who use Perl, but it seems weird
And Python, Ruby, JavaScript, CSharp, and Visual Basic.Net. Split and join are the common names in most languages that use them.
OK, that's a good reason to call it "join".
Just to be sure, though, which "join" do these languages have? "join" sounds right for the method posted initially in this thread, but sounds wrong for the method that creates a string regardless of the initial collection types.
-Lex
Lex Spoon wrote:
"Ramon Leon" ramon.leon@allresnet.com writes:
Join is popular for people who use Perl, but it seems weird
And Python, Ruby, JavaScript, CSharp, and Visual Basic.Net. Split and join are the common names in most languages that use them.
OK, that's a good reason to call it "join".
Just to be sure, though, which "join" do these languages have? "join" sounds right for the method posted initially in this thread, but sounds wrong for the method that creates a string regardless of the initial collection types.
-Lex
As far as I know, join creates a string in each of these languages.
It appears to be to be a discrepancy between the smalltalk way and these 'other' languages.
in ruby
[ 'a', 'b', 'c' ].join(', ')
in smalltalk to achieve the same thing, including the specification that the result should be a String, arguably could be
' ,' join: #('a' 'b' 'c')
but I can bet that if you are trying to satisfy the aesthetic requirements of users of 'other' languages (those languages with supposedly less brackets), they will take one look at this smalltalk version and say that it is the wrong way around.
so... if you do want the wrong way around for them, we need a right way around for us. how about #joining:
aCollection>>join:bCollection ^bCollection joining: aCollection
#('a' 'b' 'c') join: ', '.
', ' joining: #('a' 'b' 'c')
Keith
___________________________________________________________ Copy addresses and emails from any email account to Yahoo! Mail - quick, easy and free. http://uk.docs.yahoo.com/trueswitch2.html
in ruby
[ 'a', 'b', 'c' ].join(', ')
in smalltalk to achieve the same thing, including the specification that the result should be a String, arguably could be
' ,' join: #('a' 'b' 'c')
What? Why would you do this, join isn't a method on string, it produces a string, that doesn't mean it belongs there. Join belongs on Collection or SequencedCollection. Split and Join are partners, join makes a list into a string and split does the opposite, join belongs to lists, split belongs to String.
but I can bet that if you are trying to satisfy the aesthetic requirements of users of 'other' languages (those languages with supposedly less brackets), they will take one look at this smalltalk version and say that it is the wrong way around.
so... if you do want the wrong way around for them, we need a right way around for us. how about #joining:
Why do you consider their way the wrong way around?
Ramon Leon wrote:
Split and Join are partners, join makes a list into a string and split does the opposite, join belongs to lists, split belongs to String.
You could see it as primarily oriented on the collection being split or joined, or on the separator interleaving the collection. Python's join is separator-as-receiver. Python isn't symmetric though: it expects the string /to be split/ as the receiver of the split() message.
Tony
Ramon Leon wrote:
' ,' join: #('a' 'b' 'c')
What? Why would you do this,
that seems obvious to me:
it's ' ,' that joins the items in #('a' 'b' 'c'), acting as a glue, while the expression
#('a' 'b' 'c') join: ' ,'
does not make any sense when you read it. we do "small talk" after all... not "reverse talk"
just my 2 cents
Stef
that seems obvious to me:
it's ' ,' that joins the items in #('a' 'b' 'c'), acting as a glue, while the expression
#('a' 'b' 'c') join: ' ,'
does not make any sense when you read it. we do "small talk" after all... not "reverse talk"
just my 2 cents
Stef
I see it the other way, I have an array, I want a string, I ask the array to join: itself on some delimiter, it's the array's data, therefore the array needs to do the work.
I see it the other way, I have an array, I want a string, I ask the array to join: itself on some delimiter, it's the array's data, therefore the array needs to do the work.
Ramon,
indeed I can see your point but have a look at the rest of the smalltalk system and look at how many things are implemented backwards to your way of thinking and how much more power and flexibility is available by doing things this way.
For example, using your logic, you would never come up with this idea.
1 to: 10 do: [:b ].
I think your version might look like something from another thread on squeak-dev at the moment. ACollection>>from:to:apply:
In this case Number>>to:do: is implemented on Number as syntactic sugar onto Interval>>do: which actually does the work.
I think that it is relatively common to have classes that are not the actual data holder doing the work. This is primarily because of the power of the Smalltalk collections and their iterators.
best regards
Keith
___________________________________________________________ All new Yahoo! Mail "The new Interface is stunning in its simplicity and ease of use." - PC Magazine http://uk.docs.yahoo.com/nowyoucan.html
1 to: 10 do: [:b ]. I think your version might look like something from another thread on squeak-dev at the moment. ACollection>>from:to:apply:
Nope, my version would be implemented just like it already is, to: on number and do: on interval.
In this case Number>>to:do: is implemented on Number as syntactic sugar onto Interval>>do: which actually does the work.
Which is how I'd think of it, to: belongs on number, do: belongs on interval, to:do: is just a shortcut to the common case so you don't have to put parens to disambiguate the statement.
I think that it is relatively common to have classes that are not the actual data holder doing the work. This is primarily because of the power of the Smalltalk collections and their iterators.
best regards
Keith
I think it's common to have shortcuts that make it appear so, but having classes that hold the data do the work, is a fundamental concept of object orientation, this case is no different.
On Wed, 20 Sep 2006 01:21:57 +0200, Keith Hodges wrote: ...
For example, using your logic, you would never come up with this idea.
1 to: 10 do: [:b ].
I think your version might look like something from another thread on squeak-dev at the moment. ACollection>>from:to:apply:
And I thought that would slip through unnoticed ;-)
The original suggestion was, aBlock>>apply: aCollection from: start to: stop.
Since only collections can know how to do that, aBlock and aCollection had to be swapped. Of course your suggestion #from:to:apply: is also a good one.
-----------
Wrt #join, my favorites are your joinUsing: and useToJoin: this is Smalltalk land and people (incl. newbies) use method finder, if not for finding #substring.
I use #substring as an exmple for the utility of method finder because in other languages is takes one or two arguments and so in Smalltalk *must* have another name.
/Klaus
Klaus D. Witzel wrote:
On Wed, 20 Sep 2006 01:21:57 +0200, Keith Hodges wrote: ...
For example, using your logic, you would never come up with this idea.
1 to: 10 do: [:b ].
I think your version might look like something from another thread on squeak-dev at the moment. ACollection>>from:to:apply:
And I thought that would slip through unnoticed ;-)
The original suggestion was, aBlock>>apply: aCollection from: start to: stop.
Since only collections can know how to do that, aBlock and aCollection had to be swapped. Of course your suggestion #from:to:apply: is also a good one.
I was wondering why it is called "apply" anyway - the traditional term would be "do". The only reason to call it "apply" is if it's a Block method.
I'd suggest that the proper selector for that method would be
from:to:do:
which indeed exists already, and which would just get a speed enhancement by the new primitive.
- Bert -
On Wed, 20 Sep 2006 15:40:29 +0200, Bert Freudenberg wrote:
Klaus D. Witzel wrote:
On Wed, 20 Sep 2006 01:21:57 +0200, Keith Hodges wrote: ...
For example, using your logic, you would never come up with this idea.
1 to: 10 do: [:b ].
I think your version might look like something from another thread on squeak-dev at the moment. ACollection>>from:to:apply:
And I thought that would slip through unnoticed ;-) The original suggestion was, aBlock>>apply: aCollection from: start to: stop. Since only collections can know how to do that, aBlock and aCollection had to be swapped. Of course your suggestion #from:to:apply: is also a good one.
I was wondering why it is called "apply" anyway - the traditional term would be "do". The only reason to call it "apply" is if it's a Block method.
:)
I'd suggest that the proper selector for that method would be
from:to:do:
Done.
which indeed exists already, and which would just get a speed enhancement by the new primitive.
Oh no! that's too easy! Only the one-liner <primitive: ...> has to be added to an existing method. Will this count as an enhancement, a change, a VM extension, or what ;-)
Thank you Bert.
/Klaus
- Bert -
I like your previous example the best. I think smalltalk is different enough from the other languages that it needs a "Smalltalk for <language> programmers" for the different languages (which it has for some). Then you can just put their join and smalltalks.
From: Keith Hodges keith_hodges@yahoo.co.uk Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org Subject: Re: join Date: Tue, 19 Sep 2006 15:40:11 +0100
It appears to be to be a discrepancy between the smalltalk way and these 'other' languages.
in ruby
[ 'a', 'b', 'c' ].join(', ')
in smalltalk to achieve the same thing, including the specification that the result should be a String, arguably could be
' ,' join: #('a' 'b' 'c')
but I can bet that if you are trying to satisfy the aesthetic requirements of users of 'other' languages (those languages with supposedly less brackets), they will take one look at this smalltalk version and say that it is the wrong way around.
so... if you do want the wrong way around for them, we need a right way around for us. how about #joining:
aCollection>>join:bCollection ^bCollection joining: aCollection
#('a' 'b' 'c') join: ', '.
', ' joining: #('a' 'b' 'c')
Keith
___________________________________________________________ Copy addresses and emails from any email account to Yahoo! Mail - quick, easy and free. http://uk.docs.yahoo.com/trueswitch2.html
I think the best version of all these things was recomended by Kieth, and his version just joined collections. If they happen to be string then it makes a string.
My vote is for his submission and I will go back through my mail and find it again if you don't know the one I'm talking about.
From: Lex Spoon lex@cc.gatech.edu Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: squeak-dev@lists.squeakfoundation.org Subject: Re: join Date: 19 Sep 2006 13:49:50 +0200
"Ramon Leon" ramon.leon@allresnet.com writes:
Join is popular for people who use Perl, but it seems weird
And Python, Ruby, JavaScript, CSharp, and Visual Basic.Net. Split and
join
are the common names in most languages that use them.
OK, that's a good reason to call it "join".
Just to be sure, though, which "join" do these languages have? "join" sounds right for the method posted initially in this thread, but sounds wrong for the method that creates a string regardless of the initial collection types.
-Lex
"J J" azreal1977@hotmail.com writes:
I think the best version of all these things was recomended by Kieth, and his version just joined collections. If they happen to be string then it makes a string.
Isn't returning a string practically the only use case?
$('red' 'green' 'blue') join: ', ' "gives: red, green, blue"
$(1 2 3) join: ', ' "gives: 1, 2, 3"
If "join" is not to be the above method, the above method would still be nice to have.
-Lex
What about:
#( 241 243 248 ) joinWith: #(255 253).
Now you could make the argument that what I'm going for is a string (the numbers are almost certainly wrong, but I was trying to encode some telnet options), but I'm sure with some sleep I can come up with some examples where you would want to join a collection with collections or anything else.
Duplicating what others have when you don't have it is important. But if you can improve on it at no extra cost then why not?
From: Lex Spoon lex@cc.gatech.edu Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: squeak-dev@lists.squeakfoundation.org Subject: Re: join Date: 25 Sep 2006 14:25:58 +0200
"J J" azreal1977@hotmail.com writes:
I think the best version of all these things was recomended by Kieth, and his version just joined collections. If they happen to be string then it makes a string.
Isn't returning a string practically the only use case?
$('red' 'green' 'blue') join: ', ' "gives: red, green, blue"
$(1 2 3) join: ', ' "gives: 1, 2, 3"
If "join" is not to be the above method, the above method would still be nice to have.
-Lex
"J J" azreal1977@hotmail.com writes:
Duplicating what others have when you don't have it is important. But if you can improve on it at no extra cost then why not?
You did not address the example I gave:
$(1 2 3) join: ', ' "gives: 1, 2, 3"
For this kind of use case, it would be nice if the join called asString on the elements of the receiver.
I expect that this kind of use case, where you are turning a collection into a space- or comma-delimited string for output, is the most common use case.
-Lex
Actually, the implimentation that Keith had did a double dispatch as I recall (I guess I will dig that up and resend it if I ever get more then 5 minutes online at a time) and in this case, i.e. the argument to join: is a string, would result in a string.
From: Lex Spoon lex@cc.gatech.edu Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: squeak-dev@lists.squeakfoundation.org Subject: Re: join Date: 26 Sep 2006 23:02:09 +0200
"J J" azreal1977@hotmail.com writes:
Duplicating what others have when you don't have it is important. But if you can improve on it at no extra cost then why not?
You did not address the example I gave:
$(1 2 3) join: ', ' "gives: 1, 2, 3"
For this kind of use case, it would be nice if the join called asString on the elements of the receiver.
I expect that this kind of use case, where you are turning a collection into a space- or comma-delimited string for output, is the most common use case.
-Lex
"J J" azreal1977@hotmail.com writes:
Actually, the implimentation that Keith had did a double dispatch as I recall (I guess I will dig that up and resend it if I ever get more then 5 minutes online at a time) and in this case, i.e. the argument to join: is a string, would result in a string.
That would sound fine to me, and it sounds so fine to you that apparently you assumed this is what the original code did! However, I just looked it up and it is not the case. Here's is the top of Keith's message again:
Whenever I find myself wanting to join a bunch of items together (e.g. to make a path) I am never satisfied with the result and so I took a look at the Collections/String classes to see whether anything fitted nicely.
I came up with
SequencableCollection>>join: aCollection
^ self class streamContents: [ :stream | aCollection do: [ :each | stream nextPut: each ] separatedBy: [ stream nextPutAll: self ] ]
It is great but for two things: it creates an instance of the *receiver's* class, and it never calls asString.
When I read the idea, I thought of the following method:
join: separatorString "Create a string composed of the elements of the receiver separated by the specified separator. For example: ['/', (#('usr' 'bin' 'squeak') join: '/')] or [#(1 2 3) join: ', ']" ^String streamContents: [ :result | self do: [ :each | result nextPutAll: each asString ] separatedBy: [ result nextPutAll: separatorString ] ]
By the way, I still find "join" to be a funny name here, but everyone in the thread insists it is common....
-Lex
By the way, I still find "join" to be a funny name here, but everyone in the thread insists it is common....
-Lex
Really? Seems to make sense to me, telling a collection to join all of it's elements together with a string. Here's a list of words, join them all with ', '. Here's a list of conditions, join them all with ' and ', or ' or '. It's used so much, I can't think of a shorter more precise name. It's certainly a common name in many other languages, maybe we're all just acclimated to that name.
Of course, I thought #ifTrue:ifFalse: looked pretty funny at first as well, even stubbed out #if:else: just to see if I could make it look more normal, but only at first. ;)
Ramon Leon http://onsmalltalk.com
Hi fellas!
Lex Spoon lex@cc.gatech.edu wrote:
"J J" azreal1977@hotmail.com writes:
Duplicating what others have when you don't have it is important. But if you can improve on it at no extra cost then why not?
You did not address the example I gave:
$(1 2 3) join: ', ' "gives: 1, 2, 3"
For this kind of use case, it would be nice if the join called asString on the elements of the receiver.
I fainlty remember implementing a method that does the above, but with this added twist:
#('1' '2' '3') join: ', ' last: ' and ' ==> '1, 2 and 3'
So if anyone is hoing to add something like this, then include this extra feature too somehow. :)
And since you are then rumming about in Collection and friends - add #removeAll while you are at it with efficient implementations in suitable subclasses. I tried a few years back but got my head bitten off and retreated. ;)
Soo... who is the steward for Collections? :)
regards, Göran
goran@krampe.se writes:
And since you are then rumming about in Collection and friends - add #removeAll while you are at it with efficient implementations in suitable subclasses. I tried a few years back but got my head bitten off and retreated. ;)
Curiously, there is no removeAll method in Collection, in 3.7, 3.8, or 3.9. There are very few removeAll methods at all, most are not in the Collection hierarchy, and one of them is deprecated. Maybe you are thinking of a *proposed* removeAll method or methods?
Speaking of which, why is SharedQueue2>>removeAll marked "Deprecated3.9". It seems like a useful method, and there is no replacement. Especially odd is that SharedQueue2>>flush is marked as "deprecated: 'use removeAll'".
-Lex
Hi!
Lex Spoon lex@cc.gatech.edu wrote:
goran@krampe.se writes:
And since you are then rumming about in Collection and friends - add #removeAll while you are at it with efficient implementations in suitable subclasses. I tried a few years back but got my head bitten off and retreated. ;)
Curiously, there is no removeAll method in Collection, in 3.7, 3.8, or 3.9. There are very few removeAll methods at all, most are not in the Collection hierarchy, and one of them is deprecated. Maybe you are thinking of a *proposed* removeAll method or methods?
Yes, I am proposing to add it. I wrote *add* :). I argumented for such a method a few years back but as I said - I did not have the energy to argue with other prominent Smalltalkers saying that it was a bad idea. I still think it is an obviously good idea - especially since it can be concretely efficiently implemented in selected subclasses.
Speaking of which, why is SharedQueue2>>removeAll marked "Deprecated3.9". It seems like a useful method, and there is no replacement. Especially odd is that SharedQueue2>>flush is marked as "deprecated: 'use removeAll'".
-Lex
No idea. I also think SharedBufferStreams on SM is better than SharedQueue. ;)
regards, Göran
Oscar Nierstrasz wrote:
eg := 'Now is the time for all good men to come to the aid of the
party'.
self assert: ((eg split: 'the') join: 'the') = eg.
In my viewer I saw two spaces at "the party". So what should happen for #split: on a single space. Should there be an extra item with value nil or an empty string? Or should there be no extra item?
Forgive my newbieness, but doesn't smalltalk already have a join called "," (e.g. #(1 2 3) , #(4 5 6) ----> #(1 2 3 4 5 6) )?
From: Keith Hodges keith_hodges@yahoo.co.uk Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org Subject: join Date: Fri, 15 Sep 2006 00:57:52 +0100
Entirely against my will, I once worked in a perl shop, and I noticed that perlites liked joining things.
Whenever I find myself wanting to join a bunch of items together (e.g. to make a path) I am never satisfied with the result and so I took a look at the Collections/String classes to see whether anything fitted nicely.
I came up with
SequencableCollection>>join: aCollection
^ self class streamContents: [ :stream | aCollection do: [ :each | stream nextPut: each ] separatedBy: [ stream nextPutAll: self ] ]
and
Character>>join: aCollectionOfStrings
^ self class streamContents: [ :stream | aCollectionOfStrings do: [ :each | stream nextPutAll: each ] separatedBy: [ stream nextPut: self ] ]
and
Collection>>joinWith: aCollection
aCollection join: self
This now allows
(Array with: 1 with: 2) join: (Array with: 3 with: 4 with: 5) $/ join: (Array with: 'Hello' with: 'my' with: 'World').
any thoughts? I am curious as to why #join: hasn't made it into the core image, and if it were to how would it happen?
Keith
___________________________________________________________ The all-new Yahoo! Mail goes wherever you go - free your email address from your Internet provider. http://uk.docs.yahoo.com/nowyoucan.html
Hi J J, you wrote:
Forgive my newbieness, but doesn't smalltalk already have a join called "," (e.g. #(1 2 3) , #(4 5 6) ----> #(1 2 3 4 5 6) )?
No, #, is concatenation of collections.
#(1 2 3) useToJoin: #(4 5 6) is not same as #, see Keith' postings.
BTW Keith you get my +1 for the predictable species of the result, very non-confusing!
/Klaus
*bonk self*
From: "Klaus D. Witzel" klaus.witzel@cobss.com Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: squeak-dev@lists.squeakfoundation.org Subject: Re: join Date: Sat, 16 Sep 2006 15:34:00 +0200
Hi J J, you wrote:
Forgive my newbieness, but doesn't smalltalk already have a join called "," (e.g. #(1 2 3) , #(4 5 6) ----> #(1 2 3 4 5 6) )?
No, #, is concatenation of collections.
#(1 2 3) useToJoin: #(4 5 6) is not same as #, see Keith' postings.
BTW Keith you get my +1 for the predictable species of the result, very non-confusing!
/Klaus
My running image is displaying a cursor like a pair of spectacles and it appears to be stuck/busy. How can I interrupt it and get control back?
many thanks
Keith
___________________________________________________________ Inbox full of spam? Get leading spam protection and 1GB storage with All New Yahoo! Mail. http://uk.docs.yahoo.com/nowyoucan.html
squeak-dev@lists.squeakfoundation.org