[Cuis-dev] Methods that return multiple values

Luciano Notarfrancesco luchiano at gmail.com
Fri Jun 23 13:15:07 PDT 2023


Right, good point! Fortunately, messages with multiple return values are
not very common in my system, I just have a few examples, and I’ll rewrite
them with Juan’s suggestion, and I’ll keep your point in mind.

On Fri, 23 Jun 2023 at 21:33 Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com> wrote:

> 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/da2d54d9/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/da2d54d9/attachment-0001.jpeg>


More information about the Cuis-dev mailing list