I was browsing some of the Magritte source code, when I saw a message that confused me: selectors := anObject class allSelectors select: #isDescriptionSelector.
I couldn't understand how you could pass a Symbol to #select: instead of a block -- certainly the definition of Collection>>select: implies it should only take a block. But trying it for myself, I see it works -- eg { 1. 2. 3. 4. } select: #even.
can be used in place of:
{ 1. 2. 3. 4. } select: [ :each | each even ]
Given how much simpler this looks, I was surprised I'd not seen this usage before, and searching for senders of #select: shows that the wordier version seems to be generally preferred.
So my question is: is this a usage I should adopt or avoid?
Cheers, Michael
Hi Michael,
It's a trick. It only works because #value: is implemented on symbol as:
Symbol>>value: anObject ^anObject perform: self.
So the following works too.
#asUppercase value: 'I am a trick'
My suggestion is that you shouldn't follow such tricks. Although I do it too sometimes with things like.
aDictionary at: #foo ifAbsent: nil.
Since nil responds self to #value it seems redundant to me to put the nil in a block so that it can return nil when the block is evaluated with #value. Even though in this case the execution is faster but in the case of sending a symbol to select it is slower.
In both cases it is harder to read so in my opinion it is best to stick with arguments that are expected.
Ron Teitelbaum
From: Michael Davies Sent: Wednesday, February 07, 2007 1:07 PM
I was browsing some of the Magritte source code, when I saw a message that confused me: selectors := anObject class allSelectors select: #isDescriptionSelector.
I couldn't understand how you could pass a Symbol to #select: instead of a block -- certainly the definition of Collection>>select: implies it should only take a block. But trying it for myself, I see it works -- eg { 1. 2. 3. 4. } select: #even.
can be used in place of:
{ 1. 2. 3. 4. } select: [ :each | each even ]
Given how much simpler this looks, I was surprised I'd not seen this usage before, and searching for senders of #select: shows that the wordier version seems to be generally preferred.
So my question is: is this a usage I should adopt or avoid?
Cheers, Michael _______________________________________________ Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
In both cases it is harder to read so in my opinion it is best to stick with arguments that are expected.
It is usually sorter and therefor any unnecessary characters, but I completely agree with Run. The latest versions of Magritte do not use this trick anymore.
Cheers, Lukas
Ron, Thanks for the clear explanation. I ran the debugger on the example I gave, and followed the code through until I saw the 'trick' in action for myself -- it was one of those 'aha' moments. It's a very tempting shortcut, but I'll heed your advice and steer clear.
Lukas, Thanks for clarifying this wrt Magritte - and thanks also for your work on Magritte; I'm having lots of fun experimenting with it at the moment!
Cheers, Michael
Il giorno mer, 07/02/2007 alle 13.42 -0500, Ron Teitelbaum ha scritto:
Hi Michael,
It's a trick. It only works because #value: is implemented on symbol as:
Symbol>>value: anObject ^anObject perform: self.
So the following works too.
#asUppercase value: 'I am a trick'
My suggestion is that you shouldn't follow such tricks. Although I do it too sometimes with things like.
aDictionary at: #foo ifAbsent: nil.
Since nil responds self to #value it seems redundant to me to put the nil in a block so that it can return nil when the block is evaluated with #value. Even though in this case the execution is faster but in the case of sending a symbol to select it is slower.
In both cases it is harder to read so in my opinion it is best to stick with arguments that are expected.
Not to mention the fact that if you use a Symbol instead of a block, that use won't be listed in the Senders browser.
Giovanni
On 07/02/07, Giovanni Corriga giovanni@corriga.net wrote:
Not to mention the fact that if you use a Symbol instead of a block, that use won't be listed in the Senders browser.
Giovanni
That was one of the things that I originally thought would weigh against this idiom, but found to my surprise that "Senders of" identified these references correctly-- I'd previously found symbols being included in my results and wondered why, but it looks as though someone was aware of this gotcha.
Cheers, Michael
That was one of the things that I originally thought would weigh against this idiom, but found to my surprise that "Senders of" identified these references correctly-- I'd previously found symbols being included in my results and wondered why, but it looks as though someone was aware of this gotcha.
Yes, browsing senders also works. Squeak puts all the data needed by a compiled method into a special place called literal array. So all selectors you send (expect special ones like #ifTrue:, #ifFalse:, #and:, #or, #whileTrue, ...) are in there, all symbols you use, all classes you reference, all strings and numbers. If you browse for senders, the system just looks at this literal array and doesn't make the difference if this is just a symbol or an actual selector of a message send.
Cheers, Lukas
Il giorno gio, 08/02/2007 alle 07.53 +0100, Lukas Renggli ha scritto:
That was one of the things that I originally thought would weigh against this idiom, but found to my surprise that "Senders of" identified these references correctly-- I'd previously found symbols being included in my results and wondered why, but it looks as though someone was aware of this gotcha.
Yes, browsing senders also works. Squeak puts all the data needed by a compiled method into a special place called literal array. So all selectors you send (expect special ones like #ifTrue:, #ifFalse:, #and:, #or, #whileTrue, ...) are in there, all symbols you use, all classes you reference, all strings and numbers. If you browse for senders, the system just looks at this literal array and doesn't make the difference if this is just a symbol or an actual selector of a message send.
Does it? I tried browsing for senders on a 3.9 image before sending my message, and it didn't work.
Giovanni
On Thu, 08 Feb 2007 10:21:53 +0100, Giovanni Corriga wrote:
Il giorno gio, 08/02/2007 alle 07.53 +0100, Lukas Renggli ha scritto:
That was one of the things that I originally thought would weigh against this idiom, but found to my surprise that "Senders of" identified these references correctly-- I'd previously found symbols being included in my results and wondered why, but it looks as though someone was aware of this gotcha.
Yes, browsing senders also works. Squeak puts all the data needed by a compiled method into a special place called literal array. So all selectors you send (expect special ones like #ifTrue:, #ifFalse:, #and:, #or, #whileTrue, ...) are in there, all symbols you use, all classes you reference, all strings and numbers. If you browse for senders, the system just looks at this literal array and doesn't make the difference if this is just a symbol or an actual selector of a message send.
Does it? I tried browsing for senders on a 3.9 image before sending my message, and it didn't work.
What was that symbol (for reproduction)?
FWIW in #thoroughWhichSelectorsReferTo:special:byte: it is sought for #allButLast of the method's literals. This can be a problem if the method wasn't (re-)created after the image was traitified.
Also, SystemNavigation>>#allCallsOn: is influenced by (Preferences thoroughSenders).
/Klaus
Giovanni
Il giorno gio, 08/02/2007 alle 11.37 +0100, Klaus D. Witzel ha scritto:
On Thu, 08 Feb 2007 10:21:53 +0100, Giovanni Corriga wrote:
Does it? I tried browsing for senders on a 3.9 image before sending my message, and it didn't work.
What was that symbol (for reproduction)?
FWIW in #thoroughWhichSelectorsReferTo:special:byte: it is sought for #allButLast of the method's literals. This can be a problem if the method wasn't (re-)created after the image was traitified.
Also, SystemNavigation>>#allCallsOn: is influenced by (Preferences thoroughSenders).
Ok, looking for senders from the Method Finder and/or the Message Finder works. But clicking on the Senders button on the browser doesn't show the symbol with the other selectors.
I tested this by creating a bogus class and adding a method with this:
#(1 2 3) select: #even.
thoroughSenders is set.
Giovanni
On Thu, 08 Feb 2007 12:15:34 +0100, Giovanni Corriga wrote:
Il giorno gio, 08/02/2007 alle 11.37 +0100, Klaus D. Witzel ha scritto:
On Thu, 08 Feb 2007 10:21:53 +0100, Giovanni Corriga wrote:
Does it? I tried browsing for senders on a 3.9 image before sending my message, and it didn't work.
What was that symbol (for reproduction)?
FWIW in #thoroughWhichSelectorsReferTo:special:byte: it is sought for #allButLast of the method's literals. This can be a problem if the method wasn't (re-)created after the image was traitified.
Also, SystemNavigation>>#allCallsOn: is influenced by (Preferences thoroughSenders).
Ok, looking for senders from the Method Finder and/or the Message Finder works. But clicking on the Senders button on the browser doesn't show the symbol with the other selectors.
I tested this by creating a bogus class and adding a method with this:
#(1 2 3) select: #even.
thoroughSenders is set.
I tested: in IntegerTest>>#testEven I added a line at the end . self assert: (1 perform: #odd)
Now senders of #odd, when selecting 'odd' and doing alt-n, includes the changed method.
But the browser's "senders" button apparently is not in sync with the much better capabilities of #allCallsOn: and #thoroughSenders. I must say that this was the first time ever that I used this particular button ;-)
/Klaus
Giovanni
On Thu, 08 Feb 2007 01:02:50 +0100, Michael Davies wrote:
On 07/02/07, Giovanni Corriga wrote:
Not to mention the fact that if you use a Symbol instead of a block, that use won't be listed in the Senders browser.
Giovanni
That was one of the things that I originally thought would weigh against this idiom, but found to my surprise that "Senders of" identified these references correctly-- I'd previously found symbols being included in my results and wondered why, but it looks as though someone was aware of this gotcha.
Yes, and it is even more general: have a look at method #badSelectors for example, and check the senders of one of the symbols in this list. If a method refers (anyhow) to a symbol, the latter is considered a (potential) sender.
So you can find the #mySymbol sender when you use it in (myObject perform: #mySymbol), but the same goes for (myCollection select: #mySymbol).
BTW I whish that Marcus would read this thread, he invented Symbol>>#value: :)
/Klaus
Cheers, Michael
beginners@lists.squeakfoundation.org