David Christensen writes:
> Greetings,
> 
> In trying to hack closure trait support into pugs, I have some 
> questions about closure traits, variable with "will" traits and 
> introspection.  (Apologies if some of this has been discussed on the 
> list before -- I'm just going off of the synopses, which if definite 
> clarification on some of these issues has been made, should probably be 
> updated to reflect the decisions made.)
> 
> Firstly, it is suggested in S04 that variables indicated with a "will"
> predicate contribute to the corresponding block-level trait. 
Not really.  `will` is just defined as:

    $a will foo {...}

Is the same as:

    $a is foo({...})

So it's up to foo to associate itself with the block.

> I.e., if we have the following bit of code:
> 
> if $dbh {
>       my $sth will undo {$dbh.rollback} will keep {$dbh.commit} = FIRST 
> {$dbh.prepare($query)};
>       UNDO {
>               say "DB error!";
>       }
>       KEEP {
>               say "We're good!";
>       }
> }
> 
> Then the block has in effect 5 total traits, 2 UNDO block, 2 KEEP 
> blocks and 1 FIRST blocks.  From what I understand, the blocks for each 
> trait are executed in FIFO order, thus we would rollback before we 
> report the error in this contrived example.

Nope.  Entry-time blocks are executed in declaration order.  Exit-time
blocks are executed in reverse declaration order.  Just like CHECK and
END in Perl 5.

> Questions:
> 
> 1) What type of introspection, if any, are we providing to the language 
> level?  I.e., are we providing something along the lines of
> 
>     %traits = &?BLOCK.traits
> 
> where %traits is keyed on trait name (FIRST, LAST, whatever) and in 
> turn is an array of closures?  This would mean, for instance that we 
> could say
> 
>     &?BLOCK.traits<FIRST>
> 
> to get the current block's FIRST closures, if any.  When parsing the 
> block for traits, coming across a new FIRST block would be akin to 
> saying:
> 
>     push &?BLOCK.traits<FIRST>, {...block contents...}
> 
> Specifically, I'm looking for definition of the syntax, which is only 
> alluded to in the Synopsis.

What you are saying here seems reasonable.  However, we have to remember
that the closures are different for each run.  So the traits are not
associated with the block, but with the particular runtime instance of
the block.  Maybe that's what &?BLOCK refers to anyway.

I wonder how you could talk about the traits of a sub that isn't
currently executing.

> 2) If we accept the introspection at the block-level above, it seems 
> clear that we should also accept the same .traits method on variables.  
> I.e., in the above DBI example, we should get back the closure(s) for 
> undoing by referring to $sth.traits<UNDO>.  Is a variable-level trait a 
> single entry, or can we have multiple "will undo {...}" predicates on a 
> single variable?  (The utility of such is left as an exercise to the 
> reader.)

The question is, are you asking about the variable or the value?  For
instance:

    my $block = &?BLOCK;  # _not_ calling
    $block.traits;        # variable traits or &?BLOCK traits?

We probably just use whatever the equivalent of `tied` is these days.
Let's call it, er, `tied`.

    $block.traits;         # &?BLOCK traits
    (tied $block).traits;  # variable traits

> 3) User-definable traits.  Now, this may be a closed domain of sorts,
> but do we need to allow for the possibility of user-defined traits?  

No.  By which I mean OF COURSE!

> (I'm thinking here of variable-level "will" predicates.)  If so, do 
> user-defined traits get normalized to UPPER?  

No.  Block level traits are different from variable traits, and they
should be declared separately.  The variable trait `undo` for instance
probably just pushes an UNDO handler on its caller.  Likewise, the UNDO
macro (?) does precisely the same thing.

But people are allowed to declare traits that are all caps, and block
handlers which are lowercase, and any combination of the above.  Perl
culture will try to enforce against that, however.

> It would seem like we would want consistency here, because if "will
> undo {...}" and "UNDO {...}" get stored in the same trait slot, we're
> obviously transforming one of the identifiers -- should this behavior
> be specific to our "built-in" ones, or to all traits?
> 
> 4) Which of the closure traits are supported as "will" predicates on 
> variables?  Not all of the closure traits make sense on the 
> variable-level -- this information will be useful when trying to parse 
> the "will" predicates.

Hmm, not quite sure.  Traits are a pretty big thing, and I'm not sure
what it buys you to hack them in.  I'd start by implementing the block
handlers without variable traits.

Luke

Reply via email to