develooper Front page | perl.perl5.porters | Postings from September 2013

Re: [perl #114932] state(@a) =

Thread Previous
Aristotle Pagaltzis
September 24, 2013 09:25
Re: [perl #114932] state(@a) =
Message ID:
* Father Chrysostomos <> [2012-10-17 03:00]:
> * Aristotle Pagaltzis <> [2012-10-17 02:35]:
> >     $ perl -E'my (our $foo) = 1; say $::foo ? 1 : 0'
> >     1
> >     $ perl -E'our (my $foo) = 1; say $::foo ? 1 : 0'
> >     0
> >
> > To my mind that is a “no”. So far `state` is basically just another
> > declarator, which in Perl can be strewn throughout an expression,
> > and the closest declarator wins. But it’s already not quite just
> > another declarator, but one with some special behaviour. That’s fine
> > but I don’t think I want its semantics complicated further so that
> > it becomes kind of a declarator with some special behaviour that
> > also modifies some other declarators within the expression. (Maybe
> > it is a missed opportunity that isn’t spelled `state my`.
> But then would return \state my $x give the same variable each time?
> (I.e., I don’t consider it a lost opportunity, as state is yet another
> scope, different from my and our.)

My impulse was to contradict this until I finally realised I’m wrong.

I felt that `my` and `our` are about visibility, while `state` is the
exact same in terms of visibility as `my` is, except it also concerns
temporal scoping. But then I couldn’t really explain away `our`. In the
end I realised they *all* provide lexical visibility, and the difference
is just in the object that the variable they are giving visibility to is
attached to – with the consequential lifetime of that variable and thus
its temporal scoping.

So I withdraw that argument, and thanks for helping me clear my thoughts
on this.

Though on the converse, this only strengthens my argument that `state`
is just another declarator and therefore shouldn’t go around imposing
its rules onto variables already declared by other declarators.

> > I care not to tug that ship back into the port now by the anchor
> > line though.)
> >
> > For those times where you really need this functionality you might
> > be able to just abuse lexical `state`:
> >
> >     { state $init = do { our $foo = 1 } }
> >
> > Not as obvious as I would like, but at least not ugly either.
> My question is more ‘Where do we draw the line?’ than ‘Isn’t this
> useful?’
> Where do *you* think we should draw the line between state controlling
> the rhs of assignment and state not controlling the rhs of assignment?
> And will it involve more than one special case?
> What I like about my explanation above between the difference between
> (state @a) and state(@a) is that it can be said simply with no
> qualifications: = is special if the left-hand operand is state(...).

That *is* attractive, but I don’t know if it’s really a good idea.

Consider the status quo here:

    $ perl -E 'sub x { state(my $x) = "a"; $x++ // "(undef)" }; say x; x; say x'
    $ perl -E 'sub x { state(   $x) = "a"; $x++ // "(undef)" }; say x; x; say x'

How (else?) should that work? And why? If `state` is just another kind
of scope like `my`, and in this case `my` has already won, then `$x` is
a lexical variable. What would you intend to do differently here?

If I take your proposal at face value, it would become this:

    $ perl -E 'sub x { state(my $x) = "a"; $x++ // "(undef)" }; say x; x; say x'

I.e. the upshot of your proposal would be that assignment to a `state`
operation has *its own* tied-to-the-function execution scope separate
from that of the variable being declared within the `state` expression,
if any.

I don’t think I like having `state` be two different things.

Also, currently this is an error:

    $ perl -E 'sub x { my(state $x) = "a"; $x++ // "(undef)" }; say x; x; say x'
    Initialization of state variables in list context currently forbidden at -e line 1, near ""a";"
    Execution of -e aborted due to compilation errors.

What would you want this to do?

What would you want *this* to do if list assignment were no longer

    $ perl -E 'sub x { state($x, my $y) = ("a", "b"); $x++ // "(undef)" }; say x; x; say x'

Does this assign "a" to $x only once but "b" to $y every time? If not,
do you give $y the state variable treatment or $x the non-state variable

The way I understand it you’d give $y the state variable treatment here,
but is it a good idea for a `state(...)=...;` statement to have special
scope, overloading what `state` as an expression does?

Note that if we decide that you will never be able to mention more than
one variable to `state` (even if that is a container), and it’s not just
something we left out “for now”, then we *can* come up with consistent
semantics – and we can go with very nearly your formulation of the rule:
“assignment is special if the left-hand operand is `state` declaring
a new state variable”. Not entirely free of qualifications as you’d’ve
liked it, but seems close enough to me. Since only a single variable can
be given to `state` at a time, we avoid having to deal with the case of
assigning a list to a mixed-scopes list of variables, and therefore
avoid potentially having to think of `state` in an assignment as being
scoped as-an-operation separately from the variables involved on the LHS
of that assignment.

That would then imply the following:

    $ perl -E 'sub x { my(state $x) = "a"; $x++ // "(undef)" }; say x; x; say x'

This is not terrible. It would also imply that the state($x, my $y)
example will never work, with any semantics, which I’m fine with.

I’m not happy.

Any which way I turn it, this is messy, with no apparent way to handle
it gracefully. The only solution appears to be to outlaw the messy cases
rather than admit them.

Aristotle Pagaltzis // <>

Thread Previous Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About