Fact: Captures seem to be turning into a first-class data structure
that can represent:
argument lists
match results
XML nodes
anything that requires all of $, @, and % bits.
Fact: We're currently going through contortions to try to get these to behave
when they're stored in a scalar variable: [,] =$capture
Fact: This contrasts with the ease with which we can request arrayness
and hashness using the @ and % sigils.
Conjecture: We need a corresponding sigil to request captureness.
As with @ and %, you can store a capture in a $ to hide it, but we
don't have the ability to have capture variables that know how to
behave like captures without fakey syntactic help.
Bikeshed: What should that sigil be? And if it's in Latin-1, what's the
ASCII workaround?
Latin-1 candiates:
¡ 00A1 INVERTED EXCLAMATION MARK
¢ 00A2 CENT SIGN
£ 00A3 POUND SIGN
¤ 00A4 CURRENCY SIGN
¥ 00A5 YEN SIGN
¦ 00A6 BROKEN BAR
§ 00A7 SECTION SIGN
¨ 00A8 DIAERESIS
© 00A9 COPYRIGHT SIGN
ª 00AA FEMININE ORDINAL INDICATOR
« 00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
¬ 00AC NOT SIGN
00AD SOFT HYPHEN
® 00AE REGISTERED SIGN
¯ 00AF MACRON
° 00B0 DEGREE SIGN
± 00B1 PLUS-MINUS SIGN
² 00B2 SUPERSCRIPT TWO
³ 00B3 SUPERSCRIPT THREE
´ 00B4 ACUTE ACCENT
µ 00B5 MICRO SIGN
¶ 00B6 PILCROW SIGN
The obvious ASCII for ¢ would be c/ or C/ or c| or c| or maybe just |.
The obvious ASCII for © would be (c), I suppose.
Or instead of going for visual lookalikes, we could go for semantic
likenesses. If @@ is multiple arrays, then @% or %@ could be an array
mixed with a hash (and a scalar, but let's not go that far). Which
leads me to wonder if there's a Latin-1 synonym for @@, like § maybe
for "sectional", or µ for "multidimensional", or ® for, er, repetitious
or something.
Hmm, then ®©foo could take the multidimensional feeds out of capture
"foo". Maybe µ¢foo looks better though. Or maybe we could work
the € in there somewhere for "extra" dimensional... ☺
On the other hand, we could just make |foo a capture because it
inclusive-ORs several other structures. Main downside is that it looks
too much like an "ell". That's probably not a showstopper in practice.
Much of the time we'd be using it to qualify other variables anyway, so
instead of scattering [,] all over the place we would have things like
foo(|$foo)
foo(|@foo)
foo(|%foo)
foo(|foo)
Visually it kinda works as an "insert this here" marker too. And most
of the places you'd use it wouldn't be using | operators. Another factor
is that it kind of resonates visually with the \ that makes captures.
Larry
I like ¢,but:
c/$foo # ASCII of ¢$foo
d/$foo # d() divided by $foo
is rather confusing. (Same goes for |).
So the Term Term exclusion makes me rather lean towards |. Whether it's
the canonical sigil or the ASCII of ¢ doesn't much matter to me.
Trey
In a message dated Wed, 20 Sep 2006, Trey Harris writes:
> In a message dated Wed, 20 Sep 2006, Larry Wall writes:
>> The obvious ASCII for ¢ would be c/ or C/ or c| or c| or maybe just |.
>
> I like ¢,but:
>
> c/$foo # ASCII of ¢$foo
> d/$foo # d() divided by $foo
>
> is rather confusing. (Same goes for |).
Oops, I meant "same goes for c|". I like |:
This is quite true, and worth thinking about. Captures are useful beasts.
> Fact: We're currently going through contortions to try to get these to behave
> when they're stored in a scalar variable: [,] =$capture
> Fact: This contrasts with the ease with which we can request arrayness
> and hashness using the @ and % sigils.
Consider this the first test of the first-classness of objects in Perl
6. You have an object that's something not entirely unlike:
class Capture { has $.scalar; has @.array; hash %.hash }
I think the addition of a sigil is the wrong way to go for several
reasons, but most important among them is that there are going to be a
lot of scalars that contain objects that are awfully capture-like, and
they'll need whatever semantics we deem appropriate for captures too.
For this reason, I'd suggest putting away the Latin-1 glyphset and
instead focusing on developing operators to act on containers with
multiple access methods and their expanded forms.
First of all, I need a word. I'm going to call an expanded capture a
"signature" even though that's a bit too metaish. I don't encourage
others to use this term, but it helps me to get my head around this. A
signature is a bit like a list. It has no data type that you can point
to directly. Signatures are also probably lazy like lists.
When we want to turn a capture that is stored in a scalar into a
signature, we need an operator that performs that action, and
unambiguously does NOT perform the action of turning it into a list. I
suggested some in my previous message (such as <-- and $\).
Subroutines just so happen to take signatures, so you can invoke them
with one:
foo(<-- $capture);
foo($\ $capture);
Now, you need to be able to go in the other direction. You need to be
able to assemble a signature and convert it into a capture. This, we
already have:
$cap = \(<-- $othercap, $a, :$b)
$cap = \($\ $othercap, $a, :$b)
This would transform $othercap from a capture to a signature, add in a
positional and a named value and then re-integrate the resulting
signature as a new capture.
Calling subroutines with such a thing looks nice and clean:
$values = \(=@a, =@b, $c, :mean<1>);
$avg1 = avg(<-- $values, :undef<ignore>);
$avg2 = avg(<-- $values, :undef<iszero>);
That's as simple as you can get, and we didn't have to promote captures
to a new kind of sigil type to do it.
Once upon a time I had an unproposed proposal that the thing that
distinguished @ from $ is that @ auto-flattens. So perhaps captures
as well as arrays can be stored in @-variables, if you define
flattening as the [,] operator.
The reason I didn't propose it is because I couldn't figure out what
to do with %.
Luke
The one that springs out to me is:
> ¤ 00A4 CURRENCY SIGN
Probably because it looks like a container with something captured
inside it, or trying to break out, and because we use currency to
pass value(s) between individuals.
I don't have an ASCII suggestion.
-kolibrie
I don't see how that follows. There will be lots of objects containing
lots of things that don't give a rip about having a capture interface.
: For this reason, I'd suggest putting away the Latin-1 glyphset and
: instead focusing on developing operators to act on containers with
: multiple access methods and their expanded forms.
There's already going to be such an operator, and it probably won't be
Latin-1. The only question in my mind is whether it's also a sigil.
: First of all, I need a word. I'm going to call an expanded capture a
: "signature" even though that's a bit too metaish. I don't encourage
: others to use this term, but it helps me to get my head around this.
That's not a good choice of term, since signatures already mean something
else entirely in Perl 6.
: A signature is a bit like a list. It has no data type that you can point
: to directly. Signatures are also probably lazy like lists.
What you're calling a signature is in fact just another capture in our
terminology.
: When we want to turn a capture that is stored in a scalar into a
: signature, we need an operator that performs that action, and
: unambiguously does NOT perform the action of turning it into a list. I
: suggested some in my previous message (such as <-- and $\).
The Style Police have rated those as slightly less ugly than [,]=.
: Subroutines just so happen to take signatures, so you can invoke them
: with one:
:
: foo(<-- $capture);
: foo($\ $capture);
That's foo(|$capture) now.
: Now, you need to be able to go in the other direction. You need to be
: able to assemble a signature and convert it into a capture. This, we
: already have:
:
: $cap = \(<-- $othercap, $a, :$b)
: $cap = \($\ $othercap, $a, :$b)
:
: This would transform $othercap from a capture to a signature, add in a
: positional and a named value and then re-integrate the resulting
: signature as a new capture.
In my current thinking that's just \( |$othercap, $a, :$b ).
: Calling subroutines with such a thing looks nice and clean:
:
: $values = \(=@a, =@b, $c, :mean<1>);
: $avg1 = avg(<-- $values, :undef<ignore>);
: $avg2 = avg(<-- $values, :undef<iszero>);
:
: That's as simple as you can get, and we didn't have to promote captures
: to a new kind of sigil type to do it.
I think | is a lot nice-and-cleaner and simpler than <--. And it
can also work as a sigil.
Larry
> Conjecture: We need a corresponding sigil to request captureness. As
> Bikeshed: What should that sigil be?
What's * doing these days?
Smylers
Thought a lot about that one, but I think it's more useful in 0..*
and such. Unfortunately the "whatever" use of * can't take unary
argument or we fail to parse things like 0..*:by(2) correctly.
Besides, people would accuse us of reintroducing typeglobs. :-)
Which they aren't quite, but they're similar enough that a P5 person
would think of *foo as a typeglob and be thoroughly confused.
Oh, and we'd also have to rethink our use of * as a shorthand for GLOBAL::.
Larry
Well, that sounds reasonable enough. Let me take the last point, then,
which I'm only slightly convinced I have a good answer for: They just
don't seem important enough to pump out another sigil for. Filehandles
are FAR more valuable and potentially semantically rich, so I would
expect them to get their own sigil long before captures. If captures
have an expand-o-op, then I think they have everything they need to be
on-par with features like filehandles.
> : When we want to turn a capture that is stored in a scalar into a
> : signature, we need an operator that performs that action, and
> : unambiguously does NOT perform the action of turning it into a list. I
> : suggested some in my previous message (such as <-- and $\).
>
> The Style Police have rated those as slightly less ugly than [,]=.
>
My problem with [,]= is not that it's ugly (it is, a bit), but that it's
two operations which are both being slightly bent out of shape for their
use here. I do agree that capture expansion is something which demands
its own op.
> : Subroutines just so happen to take signatures, so you can invoke them
> : with one:
> :
> : foo(<-- $capture);
> : foo($\ $capture);
>
> That's foo(|$capture) now.
>
>
Hrm... ugly is one thing, but visual ambiguity is another. With an
operator like <-- one can use or discard the parens at will. However,
with | there is no alternative, since:
x |$y
could be a programmer trying to say:
x() | $y
I cry for a Q/A group every time I see that kind of thing go into Perl
6. It's especially unfortunate because there might be a fair amount of
value to coercing simple types into captures, but we don't want to in
this case, so that we can catch such errors.
...
> In my current thinking that's just \( |$othercap, $a, :$b ).
>
Yep, if |$ is the capture sigil (making | the sigil prefix op) then this
is a fairly obvious extrapolation from your previous messages.
> : Calling subroutines with such a thing looks nice and clean:
> :
> : $values = \(=@a, =@b, $c, :mean<1>);
> : $avg1 = avg(<-- $values, :undef<ignore>);
> : $avg2 = avg(<-- $values, :undef<iszero>);
> :
> : That's as simple as you can get, and we didn't have to promote captures
> : to a new kind of sigil type to do it.
>
> I think | is a lot nice-and-cleaner and simpler than <--. And it
> can also work as a sigil.
>
Keep in mind that, while <-- is my strongest current idea, I'm more
advocating the "non-ambiguous, non-sigil" idea, and not championing any
particular implementation of that idea.
One reason that I liked <-- was for the fact that it looks like -->
which defines return type inside of a signature. Though it's not clear
to me if knowlege of expected return type is wrapped up in a capture. If
so, then perhaps this is how you re-dispatch with a forced/overridden
context:
callargs(<-- $args -->Int);
Though I admit that's going to catch HTML/XML programmers off-guard ;)
Also;
role type parameters
Sam.
1. How would the capture sigil affect the use of capture objects as
replacements for perl5's references?
2. With the introduction of the capture sigil, would it be worthwhile
to allow someone to specify a signature as a capture object's 'type'?
That is:
my :(Dog: Str $name, Num :legs) |x = /($spot: "Spot"):legs<4>;
in analogy to 'my Dog $spot'?
--
Jonathan "Dataweaver" Lang
I don't see how it would have any effect at all, unless the P5 ref happened
to be to a typeglob, or had both array and hash semantics tied to it.
The regular $$x, @$x, and %$x look much like they do in P5.
: 2. With the introduction of the capture sigil, would it be worthwhile
: to allow someone to specify a signature as a capture object's 'type'?
: That is:
:
: my :(Dog: Str $name, Num :legs) |x = \($spot: "Spot"):legs<4>;
:
: in analogy to 'my Dog $spot'?
There are a several syntax errors in there, and we currently don't
allow assignment to a capture, only binding. Semantically, I don't
know what such a construct would buy you over the already defined:
my (|x Dog: Str $name, Num :$legs) := \($spot: "Spot", :legs(4));
Larry
But $x is a scalar; wouldn't you need to use '|x' to denote a capture
object, thus making the above '$|x', '@|x', and '%|x', respectively?
> we currently don't allow assignment to a capture, only binding.
IOW, if you want someone to be able to say '$|x' and get '$a' as a
result, you'd have to say '|x := \$a' (or perhaps '$|x := $a') instead
of '|x = \$a'. Right?
--
Jonathan "Dataweaver" Lang
You don't need to use | to store a capture any more than you need @ to
store an array. Just as
$x = @b;
@$x;
gives you the original array, likewise
$x = \@a;
@$a;
gives you the original array as well.
: >we currently don't allow assignment to a capture, only binding.
:
: IOW, if you want someone to be able to say '$|x' and get '$a' as a
: result, you'd have to say '|x := \$a' (or perhaps '$|x := $a') instead
: of '|x = \$a'. Right?
Yes. That's how it's currently specced, anyway. (The \ is probably
required, or it'll try to bind to the contents of $a instead.)
Larry
Huh. I'm not used to this happening. So what would the following
code do, and why?
my @b = ('foo', 'bar');
my $x = @b;
say $x;
> likewise
>
> $x = \@a;
> @$a;
>
> gives you the original array as well.
Err... don't you mean '@$x' instead of '@$a'?
> : >we currently don't allow assignment to a capture, only binding.
> :
> : IOW, if you want someone to be able to say '$|x' and get '$a' as a
> : result, you'd have to say '|x := \$a' (or perhaps '$|x := $a') instead
> : of '|x = \$a'. Right?
>
> Yes. That's how it's currently specced, anyway. (The \ is probably
> required, or it'll try to bind to the contents of $a instead.)
???
There's some potential non-dwimmery here - either that, or there's a
steep learning curve (that I haven't mastered) before dwimmery can be
applied[1]. I would expect $|x to refer to the scalar slot of the
capture object |x; as such, '$|x := ...' would mean 'bind the scalar
slot of |x to ...'. Likewise, I would expect '... := $a' to mean
'bind ... to the scalar variable $a'.
Or is the distinction between '$a' and 'the contents of $a' similar to
the distinction between a Unix filename and a Unix file ID? That is,
are we talking about the difference between hard links and symbolic
links in Unix?
--
Jonathan "Dataweaver" Lang
[1] I'm not sure that there's much of a difference between the two statements.
@b gets a list shoved into it
$x gets the array @b shoved into it
The array @b gets printed.
Arrays in a scalar context in Perl6 auto-capture themselves and the
scalar becomes a reference to the array (or hash, or even capture, for
that matter).
At a higher level, think of it this way: all data types are objects.
Assigning an array into a scalar is just a change in notation.
>> likewise
>>
>> $x = \@a;
>> @$a;
>>
>> gives you the original array as well.
>
> Err... don't you mean '@$x' instead of '@$a'?
Yes, he does.
>> : >we currently don't allow assignment to a capture, only binding.
>> :
>> : IOW, if you want someone to be able to say '$|x' and get '$a' as a
>> : result, you'd have to say '|x := \$a' (or perhaps '$|x := $a') instead
>> : of '|x = \$a'. Right?
>>
>> Yes. That's how it's currently specced, anyway. (The \ is probably
>> required, or it'll try to bind to the contents of $a instead.)
>
> ???
IMHO most of the confusion here goes away if capture variables ONLY
store parameter-list-like captures, and any other kind of capture
should, IMHO, permute itself into such a structure if you try to store
it into one. That way, their use is carefully constrained to the places
where Perl 6 can't already do the job.
My understanding is that perl6 treats references as subsets of the
capture object - something along the lines of the following (WARNING -
this is going to border on 'internals' territory):
When you bind a variable to an object, that variable becomes a synonym
of that object for all purposes. However, barring auto-capturing, the
variable's sigil must match the object's type: bind a scalar variable
to an object, and the object better know how to behave like a scalar,
else you have trouble. I understood that list-like objects generally
don't know how to behave like scalars, and vice versa.
A capture object is an object that's intended to allow for
indirection: it's a perl6opaque object with (at least) three
attributes inside, all of which are to be used exclusively for binding
purposes: in effect, it's something like:
role Capture {
has $invocant, @positional, %named, ::returnType;
}
Note that you don't need any & or | attributes in order to capture a
parameter list.
The '\' prefix operator constructs a Capture object and binds the
various parts of its parameter list to the appropriate attributes.
The '$' prefix operator returns the Capture object's $invocant
attribute; the '@' prefix operator returns the Capture object's
@positional attribute; the Capture object's '%' prefix operator
returns the Capture object's %named attribute; and the Capture
object's '::' prefix operator returns the Capture object's
::returnType attribute.
Such a Capture object would be unable to capture codeblocks or other
Capture objects without extending its capabilities. That is, '\&code'
wouldn't have an attribute to bind to &code. There _might_ be a way
around this without introducing a new attribute, but only if code
objects know how to behave like scalars.
I may be off in terms of some of the details; but am I on the right
course in general?
--
Jonathan "Dataweaver" Lang