[Cuis-dev] Methods that return multiple values
rabbit
rabbit at callistohouse.org
Sat Jun 24 07:18:59 PDT 2023
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/726ec5ee/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/726ec5ee/attachment-0001.jpeg>
More information about the Cuis-dev
mailing list