[Cuis-dev] Methods that return multiple values

rabbit rabbit at callistohouse.org
Sat Jun 24 07:30:02 PDT 2023


My apologies for the undue traffic. I feel the need to clarify what is happening. The promise local is set to the result of the eventual send of #xgcd: to the promise of the initial pair. So we have 2 promises. When the resolver of the initial pair is resolved, it resolves the initial pair promise, which sends the #xgcd: message and thus resolves the 2nd promise to cause the multiResponseHanldlers to be sent in turn. Each send of #<<* also returns a promise, so we actually have 3 momentarily, 3 times, each before the 3rd gets GCed. Before the 4th & 5th? I dunno. Perhaps we have 5 Promises momentarily.

rabbit

On 6/24/23 10:18, rabbit via Cuis-dev wrote:

> I forgot to mention, to resolve the promise <pair value resolve: 21>.
>
> But I'm getting this #becomeForward: error on promise resolution, in Cuis. It's a temporary issue.
>
>> promise := ((pair := self promiseResolverPair) key xgcd: 9).
>>
>> promise <<* [:each | selectCount := selectCount + 1. Transcript cr; show: 'each = ', each];
>> 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.].
>>
>> pair value resolve: 21.
>
> On 6/24/23 10:03, rabbit via Cuis-dev wrote:
>
>> 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/788f9507/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/788f9507/attachment-0001.jpeg>


More information about the Cuis-dev mailing list