[Cuis-dev] Methods that return multiple values

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Jun 23 12:33:38 PDT 2023


Hi all,
please note that the keyword message did eliminate the positional semantics
found in almost every other language.
With multiple return arguments, as well as multiple arguments block
workaround, we are back to a kind of positional semantic.
Of course, there is still some name used as block args [:g :s :t | ...] but
nothing would tell that [:t :g :s | ...] is a mistake.
A hint on order can be given by the keyword used to pass block argument,
like qr: [:quo :rem | ] or whatever, but when there is more than 2, naming
is getting difficult.
Nicolas


Le ven. 23 juin 2023 à 21:00, rabbit via Cuis-dev <cuis-dev at lists.cuis.st>
a écrit :

> I just realized I have been working in squeak. I updated
> PromisesLocal-rabbt.66.mcz and am attaching it. I am getting the error
> below when I 'browse code' or 'install Mionticello package'. I do not know.
> How can I load Monticello packages? Any way to get the Installer available
> in cuis? Install Monticello config maps?
>
> I appreciate you,
> rabbit
>
>
> On 6/22/23 16:21, rabbit via Cuis-dev wrote:
>
> Hey! I got inspired by your proposal, Luciano, and here's my solution in
> eventual promises. Code can be loaded as:
>
> Installer ss project: 'Cryptography'; install: 'ProCrypto.release.3'.
>
> I added a test method
>
> RefsTest>>#testMultiReturns
>
>     | selectCount unionFlag pair |
>     unionFlag := false.
>     selectCount := 0.
>     ((pair := self promiseResolverPair) key xgcd: 9)
>         <<* [:each | selectCount := selectCount + 1. Transcript cr; show:
> 'each = ', each];
>         <<* [:g :s :t | unionFlag := true. Transcript cr; show: 'g = ', g,
> '; s = ', s, '; t = ', t. g + s + t].
>     pair value resolve: 21.
>     (Delay forMilliseconds: 333) wait.
>     self assert: (selectCount == 3).
>     self assert: (unionFlag).
>
> This calls new multireturn #xgcd: method
>
> xgcd: anInteger
>     " 21 xgcd: 9"
>     | g s t |
>     g := self gcd: anInteger.
>     s := self / g.
>     t := anInteger / g.
>     ^ { g. s. t}
>
> And in the test method there are eventual sends (#<<*) to the promise of
> the #xgcd: send once the reciever promise is resolved to 21. This
> implementation detects cardinality of the continuation block and sends
> #whenResolved: appropriately, for future evaluation.
>
> Object>>#<<* continuation
>
>     (continuation numArgs == 1)
>         ifTrue: [^ self whenResolved: [:result | result do: [:each |
> continuation value: each]]].
>     ^ self whenResolved: [:result | continuation valueWithArguments:
> result].
>
> One can see a 1 cardinality schedules the continuation to evaluate with
> each result, while a continuation with cardinality 2 or more will be
> scheduled to receive all results. #valueWithArguments:
>
> Here are 2 return handlers,
>
> promise := ((pair := self promiseResolverPair) key xgcd: 9).
>
> the first for each argument
>
> promise <<* [:each | selectCount := selectCount + 1. Transcript cr; show:
> 'each = ', each];
>
> and the second for all three arguments.
>
> promise <<* [:g :s :t | unionFlag := true. Transcript cr; show: 'g = ', g,
> '; s = ', s, '; t = ', t. g + s + t].
>
> --
> ❤️‍🔥🐰
>
>
>
>
> On 6/21/23 09:44, Luciano Notarfrancesco via Cuis-dev wrote:
>
> Interesting, thanks for sharing!
> Actually I think it’s the same thing I did, my implementation calls
> BlockClosure>>#valueWithPossibleArgs: and takes only as many arguments as
> needed by the block but the array can be bigger than that (it should be
> named #valueWithPossibleArguments: tho, abbreviations are ugly).
>
>
> On Wed, 21 Jun 2023 at 15:37 Christian Haider via Cuis-dev <
> cuis-dev at lists.cuis.st> wrote:
>
>> I added something similar to my Values package (VW and ports).
>>
>> The source is
>>
>> SequenceableCollection>>asArgumentsIn: aBlock
>>
>>      "Evaluate aBlock with the receiver's elements as parameters.
>>
>>      aBlock takes its arguments from the receiver.
>>
>>      'ok'
>>
>>      #(1 2 3) asArgumentsIn: [:a :b :c | a + b + c]
>>
>>      #(1 2 3) asArgumentsIn: [:a :b | a + b]
>>
>>      #(1 2 3) asArgumentsIn: [:a | a]
>>
>>      #(1 2 3) asArgumentsIn: [42]
>>
>>      'not ok'
>>
>>      #(1 2 3) asArgumentsIn: [:a :b :c :d | a + b + c + d]
>>
>>      "
>>
>>
>>
>>      ^aBlock cullWithArguments: self asArray
>>
>>
>>
>> The difference is that it takes a list of any size and picks out the
>> first items and binds them to the variables.
>>
>> I use it often for CSV processing like
>>
>>                 (line tokensBasedOn: $;) asArgumentsIn: [:first :second
>> :y | … ].
>>
>>
>>
>> I am just a bit unhappy with the name – it is too long. It reads ok
>> though.
>>
>> The pipe character is an interesting idea. I have to think about it.
>>
>>
>>
>> I am use it for a while now and I am very happy with it.
>>
>>
>>
>> Happy hacking,
>>
>> Christian
>>
>>
>>
>>
>>
>> *Von:* Cuis-dev <cuis-dev-bounces at lists.cuis.st> *Im Auftrag von *Luciano
>> Notarfrancesco via Cuis-dev
>> *Gesendet:* Mittwoch, 21. Juni 2023 15:13
>> *An:* Discussion of Cuis Smalltalk <cuis-dev at lists.cuis.st>
>> *Cc:* Luciano Notarfrancesco <luchiano at gmail.com>
>> *Betreff:* [Cuis-dev] Methods that return multiple values
>>
>>
>>
>> Smalltalk doesn’t have a convention for methods returning multiple
>> values, and I’m not aware of any implementation.
>>
>> An example of such thing is the extended gcd: ‘a xgcd: b’ returns g, s, t
>> where g is the gcd, and as + bt = g. Writing methods that return multiple
>> values is easy with the curly brackets syntax, Integer>>#xgcd: ends with
>> something like
>>
>>     ^ {g. s. t}
>>
>> But using sending messages that return multiple values is kind of
>> annoying, I end up doing something like:
>>
>>     xgcd := a xgcd: b.
>>
>>     g := xgcd at: 1.
>>
>>     s := xgcd at: 2.
>>
>>     t := xgcd at: 3
>>
>> Some years ago I thought about using blocks for this, but I never tried
>> it. Today I just did a little experiment implementing anArray | aBlock as
>> ‘^ aBlock valueWithPossibleArgs: self’ and I can do:
>>
>>     (a xgcd: b) | [:g :s :t| … ]
>>
>>
>>
>> This is seems quite nice already, I guess I’ll start using it and see how
>> it feels. But the point of this mail is not to show a solution, but to ask
>> if anyone have thought about this or if they know any nicer solutions. Any
>> ideas?
>> --
>> Cuis-dev mailing list
>> Cuis-dev at lists.cuis.st
>> https://lists.cuis.st/mailman/listinfo/cuis-dev
>>
> --
> ❤️‍🔥🐰
>
> --
> Cuis-dev mailing list
> Cuis-dev at lists.cuis.st
> https://lists.cuis.st/mailman/listinfo/cuis-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20230623/a4899593/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: BhpEokqJiowsCL1P.jpeg
Type: image/jpeg
Size: 170169 bytes
Desc: not available
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20230623/a4899593/attachment-0001.jpeg>


More information about the Cuis-dev mailing list