[Cuis-dev] Methods that return multiple values

rabbit rabbit at callistohouse.org
Sat Jun 24 07:03:56 PDT 2023


Hi.

An interesting facet of eventual sending with promises is the bonus of sending multiple result handlers to a single eventual send result promise. So multiple result handlers, or whatever best describes, for whatever that is worth.

Here are 3 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 last 2 for all three arguments.

> promise <<* [:g :s :t | firstUnionFlag := true. Transcript cr; show: 'gcd = 'g'].
>
> promise <<* [:g :s :t | secondUnionFlag := true. Transcript cr; show: 'g = ', g, '; s = ', s, '; t = ', t.].

--
❤️‍🔥🐰

On 6/23/23 16:15, Luciano Notarfrancesco wrote:

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


More information about the Cuis-dev mailing list