On 10/2/2014 16:03, Elizabeth Mattijsen wrote:
On 01 Oct 2014, at 07:48, Father Chrysostomos wrote:
Does ‘state’ govern ‘:=’ the way it governs ‘=’? In other words, just as this:
state $x = 1;
only assigns to $x once (per closure), does the same apply to this?
state $x := $y;
I can’t find anything in the specs that implies that it does.
The reason I ask is that I am currently implementing binding for Perl 5, but
the syntax is different—
\$x = \$y;
(The reason for the different syntax is that, when we tried to use :=, we could
not find a coherent way to handle edge cases [e.g., flattening vs not
flattening]. Reusing existing Perl 5 syntax seemed the most straightforward
and intuitive approach.)
—and I am debating whether \state $x = \$y should bind only once or every time
the surrounding code is executed. I could argue it either way (though I am
leaning toward the latter), so I thought to find out what Perl 6 does.
It would seem that binding state variables will be something that will be
prohibited in Perl 6, until such time we find a good use case for it.
[15:55:36] well, all of this was because of a question of
Father Chrysostomos (a very productive p5p contributor) on p6l
[15:57:01] OK. Well, I'll leave it at, I'm happy enough with
the current semantics, so unless TimToady++ feels they have to chnage, then I'm not
inclined to do much about the status quo.
[15:57:44] (Where by "the current semantics" I mean, what Moar
does, and I'm about certain what we do on JVM. I don't actually know how things are on Parrot.)
[15:57:59] eh, but the current semantics silently do the wrong
thing, no ?
[15:59:11] lizmat: Depends how you define the semantics of
state.
[15:59:44] lizmat: Note that if you go binding a temp or let
var you are in equal trouble.
[16:00:03] moritzwouldn't mind compile-time disallowing rebinding
temp/let/state vars
[16:00:05] 'cus those are certainly about value, not container
[16:00:14]moritz +1
[16:00:18] I took state to be wanting the same semantics
[16:00:31] Yeah, I could go with a conservative approach of "just
disallow it"
[16:00:53] I'll answer FC
To expand a little, all of state/temp/let are implemented under the
assumption that you'll be doing assignment to the container you applied
them to. That is, when I:
temp $x;
Then I'm really saying "stash away a pair (the-cont = $x, current-value
= the value in $x), and at block LEAVE time then do the-cont =
old-value". It's the same container throughout, and if you re-bind $x
then temp has no clue about it. For state, containers are created at
first entry to a given closure clone, stashed away in the closure's code
object, and those same containers are used in the frames (specifically,
lexical storage) of future invocations of the same closure.
Generally in Perl 6, binding is a quite low-level operation. An operation:
$x := $y;
Might be JITted to just a couple of instructions (perhaps even if $x has
a static type constraint that needs checking, since type specialization
might prove the check isn't needed). Binding can be understood as
directly replacing the contents of a slot (that is, just setting a
pointer), and has no effect on any container that used to be there.
Since state is implemented by keeping another reference to the container
in the closure's code object, re-binding a state variable in a call
frame will have no effect beyond the lifetime of that frame:
> sub foo() { state $x = 42; say $x++; $x := 99; say $x; }; foo()
for ^5
42
99
43
99
44
99
45
99
46
99
It's also worth noting that:
state $x = 42;
And a later:
$x = 42;
Are parsed rather differently. The same goes for := and ::=. The former
kind of construct is parsed as a declarator with an initializer; the
latter is parsed as the familiar infix operators. Curiously, since we
figure out what to do by declarator scope (so a different code-path for
state than my), it turns out that := and ::= initializers on a state var
are completely ignored at present.
I suspect instead of ignoring them, we'll go down to line of giving an
error on:
state $x := something;
...because it's hard to imagine it being anything except programmer
error. That is, unless Larry comes along and declares that state should
have got "save what's in the lexpad back to the per-closure storage at
scope exit" semantics, in which case it would do something arguably
useful...and increase the cost of state vars, frustrate inlining (in a
perhaps fixable way), and make something once immutable become
mutable...you might imagine I'm hoping we don't go this way. :-)
But to answer the original question, if we *do* end up doing something
that runs code in a "state $x := ..." rather than complain about it,
then it will surely be once per closure clone, not every time,