[Cuis-dev] curried blocks
Boris Shingarov
shingarov at labware.com
Thu Aug 15 11:49:23 PDT 2024
> I attached my solution as a fileOut. I'd love to get some feedback in
> terms of style and better ways to implement it. What would you do
> differently?
I really really like what you did, for fundamental reasons.
Finally someone is looking at Smalltalk with an open mind!
I guess an enabling factor, which helps a lot, is not having
spent too many years in a particular Smalltalk-80 implementation.
As Andrés says in "DPBS Revisited":
> Reading DPBS with Smalltalk familiarity tends to reinforce
> a narrow point of view.
In this particular case — currying — if I am confined in a Smalltalk-80
implementation with broken #value: for 30 years, I lose the ability to
imagine anything else.
As a side note, even among Smalltalk-80 implementations not every one
lacks currying. Smalltalk/X has had currying for decades (albeit it
doesn't invoke it by default). And yeah, I would sure-as-hell love to
see it fixed in Cuis as well.
> Perhaps this has already been done and I just didn't find it.
Apart from the timid way how it's done in Smalltalk/X, Jan and I have been
using the fix in PreSmalltalks [1] for many years. It enables some
seriously cool stuff; in fact we rely on it in all parts of our work
(MachineArithmetic, Tinyrossa etc.) At the same time it doesn't break
anything in Pharo (i.e. nothing in Pharo demands bug-for-bug compatibility
with the old behavior — or at least we haven't come across anything that
does). I guess I would compare the situation with how Squeak got closures
progressively fixed (although currying is much simpler).
Regarding your implementation, I do have criticisms of some details:
> cb := CurriedBlock block: [:a :b | a + b]
This is just straightforward wrong. There is no need to distinguish between
Block and CurryingBlock. If
[ :a :b | body ]
is not congruent to
[ :a | [ :b | body ] ],
which is the same as saying that
C raisedTo: A*B
is not congruent to
(C raisedTo: B) raisedTo: A,
then it's an obvious bug, needing a (hopefully-)obvious fix.
> The goal is to be able to pass fewer arguments than a block requires
You meant "fewer or more arguments", right? Because it's perfectly
valid to uncurry a nested block:
[ :a | [ :b | a+b ] ] value: 2 value: 3 ">>> 5".
Now.
This is very nice but in Smalltalk we also have the "named" counterpart
to it, #perform:. If we fix currying #value:, why not fix it in #perform:
too? This allows stuff like [2]
Integer>>factorial
^self unfold inject: 1 into: #*
and other "banana programming" [3,4]; in fact this is how the supercompiler
in MachineArithmetic [5] is able to reduce Gauss:
0 + … + n
which is
n unfold inject: 0 into: #+
to
n * (n+1) / 2.
---
Are you on the BsAs Smalltalk slack? There are some very interesting
discussions around these topics, especially in the #mathematics channel.
Best,
Boris
[1] https://github.com/shingarov/MachineArithmetic/blob/pure-z3/src/PreSmalltalks-Pharo/BlockClosure.extension.st#L98
[2] https://github.com/shingarov/MachineArithmetic/blob/pure-z3/src/MathNotation-Tests/Integer.extension.st#L7
[3] https://maartenfokkinga.github.io/utwente/mmf91m.pdf
[4] Gibbons, de Moor. The fun of programming. (Palgrave, 2003)
[5] https://doi.org/10.1016/j.cola.2024.101275
On Fri, Aug 02, 2024 at 06:53:52PM -0500, Mark Volkmann via Cuis-dev wrote:
> I wanted to see if it was possible to define a class that supports partial
> application with blocks. The goal is to be able to pass fewer arguments
> than a block requires and get back a new "block" that requires
> the remaining arguments. Perhaps this has already been done and I just
> didn't find it.
>
> Here are examples of using my solution:
>
> cb := CurriedBlock block: [:a :b | a + b].
> cb valueWithArguments: #(2 3). "5"
>
> cb2 := cb valueWithArguments: #(5). "a new CurriedBlock"
> cb2 valueWithArguments: #(7). "12"
>
> I attached my solution as a fileOut. I'd love to get some feedback in terms
> of style and better ways to implement it. What would you do differently?
>
> --
> R. Mark Volkmann
> Object Computing, Inc.
> --
> Cuis-dev mailing list
> Cuis-dev at lists.cuis.st
> https://lists.cuis.st/mailman/listinfo/cuis-dev
More information about the Cuis-dev
mailing list