|
03:48
runesicle joined
03:57
runesicle left
07:06
sibl joined
07:48
sibl left,
sibl joined
08:03
dakkar joined
08:04
sibl left,
sibl joined
13:05
sibl left,
sibl joined
14:21
sibl left
16:31
dakkar left
17:14
runesicle joined
18:24
david7832 joined
18:27
sibl joined
19:48
sibl left
|
|||
| david7832 | I have two multis. One multi accepts a Scalar parameter, the other a Positional. When the argument is a Positional in Scalar context (e.g. $[1,2,3]), it is still the "positional" multi that gets called, even though I would like the scalar multi to be called instead. How can I achieve this? In other words: The "positional" sub should only be called | 20:21 | |
| for a listy argument in listy context. | |||
| multi sub e($a) { # scalar }; | |||
| multi sub e(@a) { # positional } | |||
| m: multi sub e($a) { say "scalar" }; multi sub e(@a) { say "positional" }; say e($[1,2,3]) | 20:23 | ||
| camelia | positional True |
||
| librasteve_ | david7832: please can you offer a code example of what you are trying to do? | 20:46 | |
| david7832 | I'm building some routines for to escape strings/add quotes. For lists, I want the option to either have each element wrapped in its own pair of quotes, or have the entire list stringified as one thing and wrapped in a single pair of quotes. The container type (Array vs Scalar) might be one way to decide between these options. | 20:54 | |
| multi sub esc($a) { '"' ~ $a ~ '"' } | |||
| multi sub esc(@a) { do '"' ~ $_ ~ '"' for @a} | |||
| esc([1,2,3]) # should return ("1", "2", "3") and does so | |||
| esc($[1,2,3]) # should return "(1, 2, 3)" but also returns ("1", "2", "3") | |||
| librasteve_ | tx | 21:01 | |
| david7832 | Seems that making the second signature `@a is raw` could be a solution. It doesn't change the multi that's called, that's still the @a-multi for either argument, but it makes this multi treat $[1,2,3] as a single element: | 21:16 | |
| m: multi sub esc(@a is raw) { say "got @"; return do '"' ~ $_ ~ '"' for @a}; say esc([1,2,3]); say esc($[1,2,3]) | |||
| camelia | got @ ("1" "2" "3") got @ ("1 2 3") |
||
| disbot2 | <librasteve> hmm - I admit to being stumped - I guess is raw sidesteps some of the confusion between containers and var binding in a capture | 21:29 | |
| <librasteve> best I can do is #multi sub esc($a is raw where $a.VAR.^name eq 'Scalar') { 'scalar' } | 21:30 | ||
| <librasteve> not very impressive (although I think you are swimming against the stream of containers being invisible in general code) | 21:31 | ||
| <librasteve> I suspect someone will come along shortly and tell me what I missed | |||
| david7832 | Thank you very much for your efforts, though. I'll ask folks in the main channel to also look at this | 22:01 | |
|
22:05
[Coke] joined
|
|||
| [Coke] | m: $[1,2,3].WHAT.say | 22:06 | |
| camelia | (Array) | ||
| disbot2 | <librasteve> =b | 22:10 | |
| david7832 | As for why things work as they do, with the multis above, I guess the description goes like: | ||
| A multi with signature (@a) has higher priority than that with ($a), and it will match any thing doing Positional role; if it's in a scalar container, it will just be forced into @a and thereby made positional. For example, $[1,2,3] becomes [1,2,3]. | |||
| In contrast, the signature (@a is raw) keeps the original container, so that within the function body, the argument $[1,2,3] will still be $[1,2,3] (i.e. [1,2,3] in a scalar context), while the argument [1,2,3] will still be [1,2,3] (i.e. [1,2,3] in an array context). | |||
| For convenience when reading the logs: timo suggested in #raku to use a slurpy with signature (*@a), which works out very well – irclogs.raku.org/raku/2026-04-02.html#22:02 | 23:40 | ||
|
23:40
david7832 left
23:53
runesicle left
|
|||