[Pharo-project] cull: protocol
Refactoring the AXAnnouncements abit so there's no separate classes for 0-, 1-, and 2-arg blocks, and really missing these methods from VisualWorks... cull: is equivalent to value: protocol except they accept block with N or less blockArgs Yes, I know valueWithEnoughArguments:/valueWithPossibleArgs: provide the same functionality, but the code looks much less nice using them, you end up constructing arrays needlessly etc. Look at the senders of valueWithPossibleArgs: for examples, very few of those actually need the ability to accept blocks with more arguments than they provide, and would also look nicer with cull:. Would anyone object strongly to adding the cull:, cull:cull: methods in core instead of putting them as extension methods? Cheers, Henry
http://code.google.com/p/pharo/issues/detail?id=1991 Purpose of code changes on this branch: Provide a cull: protocol on BlockClosure, equivalent to value: protocol, but taking N or more args, where N is numArgs. This is already provided by valueWithPossibleArgs:, but this only takes an array, and fills out missing arguments if block numArgs is higher than array size, as well as leading to extra syntax when your number of variable args is low and constant compared to cull: f.ex. ifNotNil: ifNotNilBlock ^ifNotNilBlock valueWithPossibleArgs: {self} turns into: ifNotNil: ifNotNilBlock ^ifNotNilBlock cull: self and: ifError: errorHandlerBlock ^ self on: Error do: [:ex | errorHandlerBlock valueWithPossibleArgs: {ex description. ex receiver}] turns into: ifError: errorHandlerBlock ^ self on: Error do: [:ex | errorHandlerBlock cull: ex description cull: ex receiver] When reviewing my code changes, please focus on: - Code clarity (there are speedier but uglier implementations) - Unnecessary array creation - Usefulness On Feb 18, 2010, at 2:23 PM, Henrik Johansen wrote:
Refactoring the AXAnnouncements abit so there's no separate classes for 0-, 1-, and 2-arg blocks, and really missing these methods from VisualWorks... cull: is equivalent to value: protocol except they accept block with N or less blockArgs Yes, I know valueWithEnoughArguments:/valueWithPossibleArgs: provide the same functionality, but the code looks much less nice using them, you end up constructing arrays needlessly etc. Look at the senders of valueWithPossibleArgs: for examples, very few of those actually need the ability to accept blocks with more arguments than they provide, and would also look nicer with cull:.
Would anyone object strongly to adding the cull:, cull:cull: methods in core instead of putting them as extension methods?
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
henrik I'm trying to get the pros and cons of cull: So am'I correct that this is useful only for situation where we have a block and we do not know upfront its number of argument: = places where valueWithPossibleArgs: Now what cull: offers is that the client does not have to create the array. I did not check your implementation. Stef On Feb 18, 2010, at 2:23 PM, Henrik Johansen wrote:
Refactoring the AXAnnouncements abit so there's no separate classes for 0-, 1-, and 2-arg blocks, and really missing these methods from VisualWorks... cull: is equivalent to value: protocol except they accept block with N or less blockArgs Yes, I know valueWithEnoughArguments:/valueWithPossibleArgs: provide the same functionality, but the code looks much less nice using them, you end up constructing arrays needlessly etc. Look at the senders of valueWithPossibleArgs: for examples, very few of those actually need the ability to accept blocks with more arguments than they provide, and would also look nicer with cull:.
Would anyone object strongly to adding the cull:, cull:cull: methods in core instead of putting them as extension methods?
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Den 18.02.2010 21:55, skrev Stéphane Ducasse:
henrik
I'm trying to get the pros and cons of cull: So am'I correct that this is useful only for situation where we have a block and we do not know upfront its number of argument: = places where valueWithPossibleArgs: Now what cull: offers is that the client does not have to create the array.
I did not check your implementation.
Stef
It's useful where you may or may not be interested in all the arguments passed to a block. Announcement and Exception handling are good examples. It covers the same bases as valueWithPossibleArgs:, with the exception it does not expand with nil args if block has more args than the corresponding message sent. Pros: - Maps well with to the value:, value:value, etc. protocol - Your code looks cleaner (imo), since you don't have to put the args in an array, and it's clear in a heart beat how many args you can choose to use in your block. - It's faster than valueWithPossibleArgs, since you don't have to put your args in an array (Also you avoid a max of 2 extra array creations as part of the method) Cons: - Functionality is already provided by valueWithPossibleArgs: (That's a superset though, if you need the exact functionality of cull, your code will end up even hairier since you need an arg size check before calling valueWithPossibleArgs:) - Portability. VW and GNU ST has them, Squeak does not, not sure about other implementations. Cheers, Henry
Your arguments are convincing to me ;) Stef On Feb 19, 2010, at 10:22 AM, Henrik Johansen wrote:
Den 18.02.2010 21:55, skrev Stéphane Ducasse:
henrik
I'm trying to get the pros and cons of cull: So am'I correct that this is useful only for situation where we have a block and we do not know upfront its number of argument: = places where valueWithPossibleArgs: Now what cull: offers is that the client does not have to create the array.
I did not check your implementation.
Stef
It's useful where you may or may not be interested in all the arguments passed to a block. Announcement and Exception handling are good examples. It covers the same bases as valueWithPossibleArgs:, with the exception it does not expand with nil args if block has more args than the corresponding message sent.
Pros: - Maps well with to the value:, value:value, etc. protocol - Your code looks cleaner (imo), since you don't have to put the args in an array, and it's clear in a heart beat how many args you can choose to use in your block. - It's faster than valueWithPossibleArgs, since you don't have to put your args in an array (Also you avoid a max of 2 extra array creations as part of the method)
Cons: - Functionality is already provided by valueWithPossibleArgs: (That's a superset though, if you need the exact functionality of cull, your code will end up even hairier since you need an arg size check before calling valueWithPossibleArgs:) - Portability. VW and GNU ST has them, Squeak does not, not sure about other implementations.
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Den 18.02.2010 21:55, skrev Stéphane Ducasse:
henrik
I'm trying to get the pros and cons of cull: So am'I correct that this is useful only for situation where we have a block and we do not know upfront its number of argument: = places where valueWithPossibleArgs: Now what cull: offers is that the client does not have to create the array.
I did not check your implementation.
Stef
It's useful where you may or may not be interested in all the arguments passed to a block. Announcement and Exception handling are good examples. It covers the same bases as valueWithPossibleArgs:, with the exception it does not expand with nil args if block has more args than the corresponding message sent.
Pros: - Maps well with to the value:, value:value, etc. protocol - Your code looks cleaner (imo), since you don't have to put the args in an array, and it's clear in a heart beat how many args you can choose to use in your block. - It's faster than valueWithPossibleArgs, since you don't have to put your args in an array (Also you avoid a max of 2 extra array creations as part of the method)
Cons: - Functionality is already provided by valueWithPossibleArgs: (That's a superset though, if you need the exact functionality of cull, your code will end up even hairier since you need an arg size check before calling valueWithPossibleArgs:) - Portability. VW and GNU ST has them, Squeak does not, not sure about other implementations.
Even though I'm just a lurker here, I think you should add this feature to Pharo. Of course I'd add the "uglier" implementation (as we discussed it with Henry in January), since I think it's not "uglier" and gives better performance (~1.3x faster for #cull:cull: if the block has less than 2 arguments while same performance if the block has 2 arguments). Levente
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Den 19.02.2010 12:40, skrev Levente Uzonyi:
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Den 18.02.2010 21:55, skrev Stéphane Ducasse:
henrik
I'm trying to get the pros and cons of cull: So am'I correct that this is useful only for situation where we have a block and we do not know upfront its number of argument: = places where valueWithPossibleArgs: Now what cull: offers is that the client does not have to create the array.
I did not check your implementation.
Stef
It's useful where you may or may not be interested in all the arguments passed to a block. Announcement and Exception handling are good examples. It covers the same bases as valueWithPossibleArgs:, with the exception it does not expand with nil args if block has more args than the corresponding message sent.
Pros: - Maps well with to the value:, value:value, etc. protocol - Your code looks cleaner (imo), since you don't have to put the args in an array, and it's clear in a heart beat how many args you can choose to use in your block. - It's faster than valueWithPossibleArgs, since you don't have to put your args in an array (Also you avoid a max of 2 extra array creations as part of the method)
Cons: - Functionality is already provided by valueWithPossibleArgs: (That's a superset though, if you need the exact functionality of cull, your code will end up even hairier since you need an arg size check before calling valueWithPossibleArgs:) - Portability. VW and GNU ST has them, Squeak does not, not sure about other implementations.
Even though I'm just a lurker here, I think you should add this feature to Pharo. Of course I'd add the "uglier" implementation (as we discussed it with Henry in January), since I think it's not "uglier" and gives better performance (~1.3x faster for #cull:cull: if the block has less than 2 arguments while same performance if the block has 2 arguments).
Levente Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
Cheers, Henry PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :) PPS. For those interested, the alternative, faster version Levente made can be found at http://paste.lisp.org/display/93130
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
I think the difference is 3 lines for the 4 methods.
Cheers, Henry
PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :)
There's no inlining VM available ATM (besides SqueakJ, but that can't run current images) and noone knows when one will be. And even though I didn't try it, I expect that "inlining by hand" saves time and memory.
PPS. For those interested, the alternative, faster version Levente made can be found at http://paste.lisp.org/display/93130
Here is a working example (the linked version has a bug): BlockClosure >> cull: argument1 cull: argument2 numArgs = 2 ifTrue: [ ^self value: argument1 value: argument2 ]. numArgs = 1 ifTrue: [ ^self value: argument1 ]. ^self value (For #cull:cull:cull: the difference is ~1.7x if the block has 0 or 1 argument, and ~1.3x if it has 2 arguments) Levente
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
"Levente" == Levente Uzonyi <leves@elte.hu> writes:
Levente> Here is a working example (the linked version has a bug): Levente> BlockClosure >> cull: argument1 cull: argument2 Levente> numArgs = 2 ifTrue: [ ^self value: argument1 value: argument2 ]. Levente> numArgs = 1 ifTrue: [ ^self value: argument1 ]. Levente> ^self value The error message here will be misleading if it's a 3 arg block, saying that it wants 3 args, but was given 0, when in fact you *offered* two args. Perhaps the tests could be done in the reverse order: numargs = 0 ifTrue: [^self value]. numargs = 1 ifTrue: [^self value: argument1]. ^self value: argument1 value: argument2. Then, you'll get a sensible message... "offered 2, wanted 3" -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
Den 19.02.2010 14:03, skrev Levente Uzonyi:
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
I think the difference is 3 lines for the 4 methods.
Cheers, Henry
PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :)
There's no inlining VM available ATM (besides SqueakJ, but that can't run current images) and noone knows when one will be. And even though I didn't try it, I expect that "inlining by hand" saves time and memory.
No objections here, it's definately faster.
PPS. For those interested, the alternative, faster version Levente made can be found at http://paste.lisp.org/display/93130
Here is a working example (the linked version has a bug): BlockClosure >> cull: argument1 cull: argument2
numArgs = 2 ifTrue: [ ^self value: argument1 value: argument2 ]. numArgs = 1 ifTrue: [ ^self value: argument1 ]. ^self value
Ah yes, had forgotten about that. How about: numArgs > 1 ifTrue: [ ^self value: argument1 value: argument2 ]. numArgs = 1 ifTrue: [ ^self value: argument1 ]. ^self value That way, you get "This block accepts 3 arguments, but was called with 2 arguments" instead of "... was called with 0 arguments" error messages if the block has too many args.
(For #cull:cull:cull: the difference is ~1.7x if the block has 0 or 1 argument, and ~1.3x if it has 2 arguments)
Then also consider the scale "overhead of 120 ms rather than 320ms for 1 million cull:cull:cull: sends where the block has one arg, compared to a raw value: send (130ms)". ;) Cheers, Henry
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Den 19.02.2010 14:03, skrev Levente Uzonyi:
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
I think the difference is 3 lines for the 4 methods.
Cheers, Henry
PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :)
There's no inlining VM available ATM (besides SqueakJ, but that can't run current images) and noone knows when one will be. And even though I didn't try it, I expect that "inlining by hand" saves time and memory.
No objections here, it's definately faster.
PPS. For those interested, the alternative, faster version Levente made can be found at http://paste.lisp.org/display/93130
Here is a working example (the linked version has a bug): BlockClosure >> cull: argument1 cull: argument2
numArgs = 2 ifTrue: [ ^self value: argument1 value: argument2 ]. numArgs = 1 ifTrue: [ ^self value: argument1 ]. ^self value
Ah yes, had forgotten about that. How about:
numArgs > 1 ifTrue: [ ^self value: argument1 value: argument2 ]. numArgs = 1 ifTrue: [ ^self value: argument1 ]. ^self value
That way, you get "This block accepts 3 arguments, but was called with 2 arguments" instead of "... was called with 0 arguments" error messages if the block has too many args.
Nice.
(For #cull:cull:cull: the difference is ~1.7x if the block has 0 or 1 argument, and ~1.3x if it has 2 arguments)
Then also consider the scale "overhead of 120 ms rather than 320ms for 1 million cull:cull:cull: sends where the block has one arg, compared to a raw value: send (130ms)". ;)
Now imagine that you have a lot slower machine. ;) Levente
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
So henry the fast or the slow :) Stef On Feb 19, 2010, at 2:26 PM, Henrik Johansen wrote:
Den 19.02.2010 14:03, skrev Levente Uzonyi:
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
I think the difference is 3 lines for the 4 methods.
Cheers, Henry
PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :)
There's no inlining VM available ATM (besides SqueakJ, but that can't run current images) and noone knows when one will be. And even though I didn't try it, I expect that "inlining by hand" saves time and memory.
No objections here, it's definately faster.
PPS. For those interested, the alternative, faster version Levente made can be found at http://paste.lisp.org/display/93130
Here is a working example (the linked version has a bug): BlockClosure >> cull: argument1 cull: argument2
numArgs = 2 ifTrue: [ ^self value: argument1 value: argument2 ]. numArgs = 1 ifTrue: [ ^self value: argument1 ]. ^self value
Ah yes, had forgotten about that. How about:
numArgs > 1 ifTrue: [ ^self value: argument1 value: argument2 ]. numArgs = 1 ifTrue: [ ^self value: argument1 ]. ^self value
That way, you get "This block accepts 3 arguments, but was called with 2 arguments" instead of "... was called with 0 arguments" error messages if the block has too many args.
(For #cull:cull:cull: the difference is ~1.7x if the block has 0 or 1 argument, and ~1.3x if it has 2 arguments)
Then also consider the scale "overhead of 120 ms rather than 320ms for 1 million cull:cull:cull: sends where the block has one arg, compared to a raw value: send (130ms)". ;)
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On Fri, 2010-02-19 at 14:03 +0100, Levente Uzonyi wrote:
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
I think the difference is 3 lines for the 4 methods.
Cheers, Henry
PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :)
There's no inlining VM available ATM (besides SqueakJ, but that can't run current images) and noone knows when one will be. And even though I didn't try it, I expect that "inlining by hand" saves time and memory.
I'm working on inlining in Exupery at the moment though progress is still slow. (Time I've two young boys)... Bryce
Den 21.02.2010 23:11, skrev Bryce Kampjes:
On Fri, 2010-02-19 at 14:03 +0100, Levente Uzonyi wrote:
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
I think the difference is 3 lines for the 4 methods.
Cheers, Henry
PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :)
There's no inlining VM available ATM (besides SqueakJ, but that can't run current images) and noone knows when one will be. And even though I didn't try it, I expect that "inlining by hand" saves time and memory.
I'm working on inlining in Exupery at the moment though progress is still slow. (Time I've two young boys)...
Bryce
Will Exupery work on the 0.15 VM now? IIRC, when making it available, you mentioned there was primitive collision between Exupery/Closures. Cheers, Henry
On Mon, 2010-02-22 at 11:14 +0100, Henrik Johansen wrote:
Den 21.02.2010 23:11, skrev Bryce Kampjes:
On Fri, 2010-02-19 at 14:03 +0100, Levente Uzonyi wrote:
On Fri, 19 Feb 2010, Henrik Johansen wrote:
Well, ugly was a strong word. Reusing less, aka. shorter is a better choice, I guess.
I think the difference is 3 lines for the 4 methods.
Cheers, Henry
PS. In VisualWorks, the two perform equally. *Wishing for a Cog VM to test on* :)
There's no inlining VM available ATM (besides SqueakJ, but that can't run current images) and noone knows when one will be. And even though I didn't try it, I expect that "inlining by hand" saves time and memory.
I'm working on inlining in Exupery at the moment though progress is still slow. (Time I've two young boys)...
Bryce
Will Exupery work on the 0.15 VM now? IIRC, when making it available, you mentioned there was primitive collision between Exupery/Closures.
You mean the 0.15 Exupery VM? ;-) Yes, but there's still that problem with closures. I moved the interpreter closure code into the Exupery VMs to allow people to work on closures in the image. I haven't yet implemented the closure bytecodes in Exupery. Closure support will be added to the Exupery JIT after inlining methods without blocks. Then after adding closure bytecode support I'll add inlining of closures. Bryce
participants (5)
-
Bryce Kampjes -
Henrik Johansen -
Levente Uzonyi -
merlyn@stonehenge.com -
Stéphane Ducasse