Declaration and definition of state() vars

2005-05-05 Thread Ingo Blechschmidt
Hi,

  sub gen() {
state $svar = 42;
# Only initialized once, as it is (per S04) equivalent to
#   state $svar will first{ 42 };
return { $svar++ };
  }

  my $a = gen();# $svar == 42
  $a(); $a();   # $svar == 44
  my $b = gen();# $svar == 44
  say $b(); # 44
# $svar == 45

I presume that's correct. Is the following correct, too?

  sub gen() {
(state $svar) = 42;
# Initialized on each invocation of gen, as it is equivalent to
#   (state $svar will first{ undef }) = 42;
# I.e. $svar is only set to undef once (as $svar is a state
# variable), but it is set to 42 each time gen is called. Correct?
return { $svar++ };
  }

  my $a = gen();# $svar == 42
  $a(); $a();   # $svar == 44
  my $b = gen();# $svar == 42
  say $b(); # 42
# $svar == 43


--Ingo

-- 
Linux, the choice of a GNU | Mathematicians practice absolute freedom.
generation on a dual AMD   | -- Henry Adams  
Athlon!|



Re: Declaration and definition of state() vars

2005-05-05 Thread Larry Wall
On Thu, May 05, 2005 at 07:50:31PM +0200, Ingo Blechschmidt wrote:
: Hi,
: 
:   sub gen() {
: state $svar = 42;
: # Only initialized once, as it is (per S04) equivalent to
: #   state $svar will first{ 42 };
: return { $svar++ };
:   }
: 
:   my $a = gen();# $svar == 42
:   $a(); $a();   # $svar == 44
:   my $b = gen();# $svar == 44
:   say $b(); # 44
: # $svar == 45
: 
: I presume that's correct.

Yes.  Though I'm not quite sure if we've nailed down whether the will
form will auto-assign or would instead have to be written

state $svar will first { $_ = 42 }

I think the latter is probably correct.  However, you should be able
to write the non-closure form to auto-assign in any event:

state $svar is first(42)

: Is the following correct, too?
: 
:   sub gen() {
: (state $svar) = 42;
: # Initialized on each invocation of gen, as it is equivalent to
: #   (state $svar will first{ undef }) = 42;
: # I.e. $svar is only set to undef once (as $svar is a state
: # variable), but it is set to 42 each time gen is called. Correct?
: return { $svar++ };
:   }
: 
:   my $a = gen();# $svar == 42
:   $a(); $a();   # $svar == 44
:   my $b = gen();# $svar == 42
:   say $b(); # 42
: # $svar == 43

Depends on whether assignment to a state variable is recognized in
syntactic analysis (where parens count) or semantic analysis (where they
don't).  You're taking the syntactic approach.  It can be argued that
the semantic approach is more robust, insofar as it makes all of
these equivalent:

state $a = 1; state $b = 2;
state ($a,$b) = (1,2);
(state $a, state $b) = (1,2);

just as

my $a = 1; my $b = 2;
my ($a,$b) = (1,2);
(my $a, my $b) = (1,2);

should all be equivalent.  On the other hand, don't ask me when

(my $a, state $b) = (1,2);

should evaluate its RHS.  The semantic analyzer should probably throw
up its hands in disgust if it sees conflicting requirements for =.

Or we could make assignment policy depend on the outside of the parens
as you're doing.  In that case

my ($a, state $b) = (1,2);

might initialize $b every time, while

state ($a, my $b) = (1,2);

would only initialize $b the first time.  Hmm, then you could write

state (my $first) = 1;

and $first would be true only the first time though.  Not sure if that's
terribly useful.  On the other hand,

state (our $x) = 1;

would have the same effect as

our $x is first(1);

That isn't terribly useful, but I think, for simplicity of analysis,
let's go ahead with your approach and just make the assignment timing
depend only on the declarator outside the parens.

So, yes.

Larry