from preamble:
"Change Set: KCP Date: 30 September 2004 Author: stephane ducasse
transform Collection>>ifNotEmpty: aBlock
^ self isEmpty ifFalse: [aBlock valueWithPossibleArgs: {self}]
into
ifNotEmpty: aBlock ^ self isEmpty ifFalse: [aBlock value]
which corresponds to the method comment Evaluate the block unless I'm empty" !
Am 30.09.2004 um 10:04 schrieb ducasse@iam.unibe.ch:
from preamble:
"Change Set: KCP Date: 30 September 2004 Author: stephane ducasse
transform Collection>>ifNotEmpty: aBlock
^ self isEmpty ifFalse: [aBlock valueWithPossibleArgs: {self}]
into
ifNotEmpty: aBlock
^ self isEmpty ifFalse: [aBlock value]
which corresponds to the method comment Evaluate the block unless I'm empty" ! <ifNotEmptyCleans.cs.gz>
No good idea: we need to support *both*
aCollection ifNotEmpty: [:arg | arg doSomething]
and
aCollection ifNotEmpty: [ self doSomething].
This is really important, as VW and RB define ifNotEmpty: to require a block, but squeak's implementation used to not require one. So we need the implementation that allows both, or we need to fix a lot of senders.
I really like the valueWithPossibleArgs: thingy: It does a double-dispatch on the number of arguments of the block, and just does the right thing. We really should keep it.
Marcus
On Sep 30, 2004, at 12:03 PM, Marcus Denker wrote:
I really like the valueWithPossibleArgs: thingy: It does a double-dispatch on the number of arguments of the block, and just does the right thing. We really should keep it.
Yup, though I would like to have a variation that expected only one arg - so,
aBlock valueWithPossibleArgument: self
rather than
aBlock valueWithPossibleArgs: {self}.
Especially since I imagine that's the most common usage.
Avi
transform Collection>>ifNotEmpty: aBlock
^ self isEmpty ifFalse: [aBlock valueWithPossibleArgs: {self}]
into
ifNotEmpty: aBlock
^ self isEmpty ifFalse: [aBlock value]
which corresponds to the method comment Evaluate the block unless I'm empty" ! <ifNotEmptyCleans.cs.gz>
No good idea: we need to support *both*
aCollection ifNotEmpty: [:arg | arg doSomething]
and
aCollection ifNotEmpty: [ self doSomething].
This is really important, as VW and RB define ifNotEmpty: to require a block,
you mean anargument?
but squeak's implementation used to not require one. So we need the implementation that allows both, or we need to fix a lot of senders.
For me I do not understand what it means to require an argument, in this case this is not ifNotEmpty: [do that] but ifNotEmpty: [do that with self] and the message does not tell that at all
and why we have that for ifNotEmpty and not for ifTrue: and isNil:
Really I do not understand and as a user of the interface I do not get that at all.
IF people need that then why don't they write ifNotEmptyDoWithMe: []
I really like the valueWithPossibleArgs: thingy: It does a double-dispatch on the number of arguments of the block, and just does the right thing. We really should keep it.
But not like that. Sorry this is really bad
Marcus
Am 30.09.2004 um 12:41 schrieb stéphane ducasse:
I really like the valueWithPossibleArgs: thingy: It does a double-dispatch on the number of arguments of the block, and just does the right thing. We really should keep it.
But not like that. Sorry this is really bad
Why? It allows ifNotEmpty: to be compatible to both the old Squeak version *and* the VisualWorks version. That is really nice, and should be kept. If we remove that, we get lots of trouble with e.g. RB and a big fight over what the "correct" default behaviour should be.
We could add a ifNotEmptyDo: in addition, but I don't see the point.
For ifNotNil: Yes, this too should allow both a 1-arg block and a 0-arg block. But that needs a compiler change. I looked into that a bit and gave up after realising how simple that will be in the new compiler (it's actually already done there).
We should discuss that on Monday.
Marcus
For me I do not understand what it means to require an argument, in this case this is not ifNotEmpty: [do that] but ifNotEmpty: [do that with self] and the message does not tell that at all
and why we have that for ifNotEmpty and not for ifTrue: and isNil:
Really I do not understand and as a user of the interface I do not get that at all.
But not like that. Sorry this is really bad
Yip - this is bad, Stef's refactoring are good. Better to have clean CONSISTENT interface.
brent
Am 30.09.2004 um 13:03 schrieb Brent Pinkney:
For me I do not understand what it means to require an argument, in this case this is not ifNotEmpty: [do that] but ifNotEmpty: [do that with self] and the message does not tell that at all
and why we have that for ifNotEmpty and not for ifTrue: and isNil:
Really I do not understand and as a user of the interface I do not get that at all.
But not like that. Sorry this is really bad
Yip - this is bad, Stef's refactoring are good. Better to have clean CONSISTENT interface.
So you would argue that having
1 + 1.0
and
1 + 3
is bad, too?
Marcus
On Sep 30, 2004, at 12:41 PM, stéphane ducasse wrote:
For me I do not understand what it means to require an argument, in this case this is not ifNotEmpty: [do that] but ifNotEmpty: [do that with self] and the message does not tell that at all
and why we have that for ifNotEmpty and not for ifTrue: and isNil:
Because in the case of ifTrue: and ifNil: (as well as ifFalse:), if the block is evaluated then you know exactly what the receiver is, so there's no need to pass it in. This is also mostly true for #ifEmpty:, in that you know that you've got an empty collection, and that's probably all you care about. In the case of #ifNotNil: or #ifNotEmpty:, however, there are interesting things about the receiver (for #ifNotNil:, what the instance is, for #ifNotEmpty:, what instances it contains) that you *don't* know, and so passing the receiver into the block is very useful.
I generally agree with you about the message names, in that I'd rather see ifNotEmptyDo: (to match #ifNotNilDo:) as a distinct method from #ifNotEmpty:. However, there's a compatibility issue here - other dialects expect #ifNotNil: and #ifNotEmpty: to take a 1-arg block, and we should probably follow suit. As it is I have to avoid using either message if I want my code to be portable, which is a shame.
Avi
I see the point.
Especially the fact that receiver is a collection make sense but this is not consistent and not transparent. I hate to have to read a method body to understand what is does because we have abstraction but we break it.
Marcus for the 1 + 1.0 I is not at the same level because plus is overloaded and we use that since we are kids.
When I read ifNotEmpty:
I associate it with all the methods such as ifTrue: ok this is a conditional and conditional do not take block arguments. And now I have this particular method that does it.....sure! and without any distinctive signs from its user interface. Even better.
So I understand than for compatibility reasons we want to keep that but at least: - we should update the comment!!!! - then be consistent with the other methods
For me I do not understand what it means to require an argument, in this case this is not ifNotEmpty: [do that] but ifNotEmpty: [do that with self] and the message does not tell that at all
and why we have that for ifNotEmpty and not for ifTrue: and isNil:
Because in the case of ifTrue: and ifNil: (as well as ifFalse:), if the block is evaluated then you know exactly what the receiver is, so there's no need to pass it in. This is also mostly true for #ifEmpty:, in that you know that you've got an empty collection, and that's probably all you care about. In the case of #ifNotNil: or #ifNotEmpty:, however, there are interesting things about the receiver (for #ifNotNil:, what the instance is, for #ifNotEmpty:, what instances it contains) that you *don't* know, and so passing the receiver into the block is very useful.
I generally agree with you about the message names, in that I'd rather see ifNotEmptyDo: (to match #ifNotNilDo:) as a distinct method from #ifNotEmpty:. However, there's a compatibility issue here - other dialects expect #ifNotNil: and #ifNotEmpty: to take a 1-arg block, and we should probably follow suit. As it is I have to avoid using either message if I want my code to be portable, which is a shame.
Avi
Am 30.09.2004 um 13:24 schrieb Avi Bryant:
On Sep 30, 2004, at 12:41 PM, stéphane ducasse wrote:
For me I do not understand what it means to require an argument, in this case this is not ifNotEmpty: [do that] but ifNotEmpty: [do that with self] and the message does not tell that at all
and why we have that for ifNotEmpty and not for ifTrue: and isNil:
Because in the case of ifTrue: and ifNil: (as well as ifFalse:), if the block is evaluated then you know exactly what the receiver is, so there's no need to pass it in. This is also mostly true for #ifEmpty:, in that you know that you've got an empty collection, and that's probably all you care about. In the case of #ifNotNil: or #ifNotEmpty:, however, there are interesting things about the receiver (for #ifNotNil:, what the instance is, for #ifNotEmpty:, what instances it contains) that you *don't* know, and so passing the receiver into the block is very useful.
I generally agree with you about the message names, in that I'd rather see ifNotEmptyDo: (to match #ifNotNilDo:) as a distinct method from #ifNotEmpty:. However, there's a compatibility issue here - other dialects expect #ifNotNil: and #ifNotEmpty: to take a 1-arg block, and we should probably follow suit. As it is I have to avoid using either message if I want my code to be portable, which is a shame.
So I think the following would be a good compromise:
1) allow 0- and 1-arg block for ifNotEmpty: and ifNotNil: for compatibility 2) provide ifNotEmptyDo: to be used. (there is already ifNotNilDo:).
Marcus
"Marcus" == Marcus Denker denker@iam.unibe.ch writes:
Marcus> So I think the following would be a good compromise:
Marcus> 1) allow 0- and 1-arg block for ifNotEmpty: and ifNotNil: for Marcus> compatibility Marcus> 2) provide ifNotEmptyDo: to be used. (there is Marcus> already ifNotNilDo:).
3) Add a new check in SLint for "improper" usage of ifNotEmpty: and ifNotNil:
Sam
So I think the following would be a good compromise:
- allow 0- and 1-arg block for ifNotEmpty: and ifNotNil: for
compatibility
and said that people should not use 1-arg and use 2)
- provide ifNotEmptyDo: to be used. (there is already ifNotNilDo:).
This is my inmpression because I tried to write some code and the code hurts me
#(3 4 5) ifNotEmpty: [:col| col inspect]
Am 30.09.2004 um 15:07 schrieb stéphane ducasse:
So I think the following would be a good compromise:
- allow 0- and 1-arg block for ifNotEmpty: and ifNotNil: for
compatibility
and said that people should not use 1-arg and use 2)
- provide ifNotEmptyDo: to be used. (there is already ifNotNilDo:).
This is my inmpression because I tried to write some code and the code hurts me
#(3 4 5) ifNotEmpty: [:col| col inspect]
Ok, I'l put a changeset together that does this. (minus the ifNotNil: 1-arg code, I'm too dumb to understand the inlining in the current compiler, so this has to wait till we get a new compiler).
Marcus
This is really important, as VW and RB define ifNotEmpty: to require a block,
VW does not define such a message.
What is the semantic we want ifNotEmpty: to have? Before Stef's email I always thought that writing: obj ifNotEmpty: [...] is equivalent to: obj notEmpty ifTrue: [...]
I believe it should be.
In a 5987 image, all the sender of ifNotEmpty: does not expect any passed argument.
Alexandre
but squeak's implementation used to not require one. So we need the implementation that allows both, or we need to fix a lot of senders.
I really like the valueWithPossibleArgs: thingy: It does a double-dispatch on the number of arguments of the block, and just does the right thing. We really should keep it.
Marcus
squeak-dev@lists.squeakfoundation.org