Daniel Ruoso wrote: > > Hi, > > As smop and mildew now support ControlExceptionReturn (see > v6/mildew/t/return_function.t), an important question raised: > > sub plural { return 1,2 } > sub singular { return 1 } > my @a = plural(); > my $b = plural(); > my @c = singular(); > my $d = singular(); > > What should @a, $b, @c and $d contain? > > Note that the spec says explicitly that a Capture should be returned, > delaying the context at which the value will be used, this allows > > sub named { return :x<1> } > my $x := |(named); > > So, this also means that assigning > > my @a = plural(); > my @c = singular(); > > forces list context in the capture, which should return all positional > parameters, as expected. But > > my $b = plural(); > my $d = singular(); > > would force item context in the capture, and here is the problem, as a > capture in item context was supposed to return the invocant.
If item context is supposed to return the invocant, then it would seem to me that returning a single value from a sub would put that value into the capture object's invocant. This would mean that the problem crops up under 'my @c = singular()' instead of 'my $b = plural()'. The idea in the spec is that the capture object can hold an item, a distinct list, and a distinct hash all at once. The problem that we're encountering here is that there are times when the difference between an item and a one-item list is fuzzy. We _could_ kludge it by saying that when a sub returns an item $x, it gets returned as a capture object ($invocant := $x: $param1 := $x) or some such; but this _is_ a kludge, which has the potential for unexpected and unsightly developments later on. Another option would be to change the way that applying item context to a capture object works in general, to allow for the possibility that a single-item list was actually intended to be a single item: if there's no invocant, but there is exactly one positional parameter, return the positional parameter instead: $a = |("title": 1) $b = |("title":) $c = |(1) $x = item $a; # $x == "title" $x = item $b; # $x == "title" $x = item $c; # $x == 1 $x = list $a; # $x == [1] $x = list $b; # $x == [] $x = list $c; # $x == [1] With this approach, return values would return values as positional parameters unless a conscious effort was made to do otherwise. But let's say that you really wanted to get the invocant of a capture object. You can still do so: |($x:) = $a; # $x == "title" |($x:) = $b; # $x == "title" |($x:) = $c; # $x == undef Likewise, you could specify that you want the first positional parameter of the capture object by saying: |($x) = $a; # $x == 1 |($x) = $b; # $x == undef |($x) = $c; # $x == 1 This isn't as clean as a straight mapping of invocant to item, positional to list, and named to hash; but I think that it's got better dwimmery. -- Jonathan "Dataweaver" Lang