Re: the $! too global
Following the discussions from 2 weeks ago, are there any plans to update the synopsis soon regarding the $! variable? Synopsis 2 still says that it is conjectural to whether $! is always environmental. Thanks. -- Darren Duncan
Re: the $! too global
On Wed, Dec 07, 2005 at 09:43:31AM +0100, TSa wrote: : HaloO, : : Larry Wall wrote: : My gut-level feeling on this is that $! is going to end up being an : env variable like $_. : : I just re-read about exceptions. Well, I undestand now that $! is : intented as a variable with a spectrum of meanings ranging from : : 1) the return value of a sub, through : 2) an error return value, up to : 3) a non-return value. : : Of these only the last is what I know as exceptions. I'm for now : undecided to regard these three purposes of $! as very clever or : as big potential for subtle problems. From the viewpoint of the : execution model this environment approach is very clear, though. : It nicely unifies return values with in-band errors and out-band : exceptions. Which leaves just one wish from my side: make CATCH : blocks dispatched. That is they get a signature what kind of : exception they handle. The optimizer will make good use of this : information. I think that's basically the direction that Parrot is headed. : Then the problem reduces : to what you do with an unhandled $! at the end of a lexical scope, : : I don't understand this. The end of scope is either the closing : brace or an explicit statement like next, leave, return, yield, : fail or die. In the above spectrum of $! these are resultizer : just as given, for and friends are topicalizer for $_. But I think : simple assignment to $! is not foreseen, or is it? I don't entirely understand it all yet myself. It's possible that we're trying to unify too many ideas into $! all at once. It may be impossible to simultaneously do all of: * emulate Perl 5's $!, $@, $? and $^E * represent only the last exception status * never lose exception information Indeed, the faults with Perl 5's $! mechanism are the major reason for CATCH blocks. So maybe we should just make $! as close to Perl 5 semantics as possible and then steer people away from it if they want to write robust code. Even the first of those items above is something we really haven't thought through. In Perl 5 $! has errno semantics that mean you shouldn't rely on its value unless something went bang and you know it some other way. Whereas $@ and $? rely respectively on evalish and systemish calls to clear the variables on success. Does unifying $! with those mean that $! has to be cleared on every function call? That seems rather ill-defined. I think the solution is more along the lines of $! clears its boolean/defined status on every function call but remembers the last actual exception. Or maybe we just say that $! stays true if it contains any exception, and rely on eval or system-like calls to clear $! if they want test-after semantics? I can argue it both ways, which probably means that neither solution is the right one. : For an example let's assume that / returns 'undef but division by zero' : in $! if its rhs is zero. Well, NaN probably, but go on. : { # begin of scope : : my $x = 3; : my $y = 4; : : say $x/$y; : : $x = foo; # foo could return 0 : : my $z = $y/$x; # $! == 'undef but division by zero' if $x == 0 : # Is that assignable to $z? : : $z++; # This is now a statement in a potential CATCH block? : } Yes, the return value is assignable whether it is NaN or undef (assuming the type of $z doesn't prevent assignment), but the return value is not quite the same thing as $!, I suspect. It's more like $! contains a pointer to the latest error return value. Another way to look at it is that the returned exception value is immutable (more or less) but $! is mutably bound to some error value. Larry
Re: the $! too global
HaloO, Larry Wall wrote: My gut-level feeling on this is that $! is going to end up being an env variable like $_. I just re-read about exceptions. Well, I undestand now that $! is intented as a variable with a spectrum of meanings ranging from 1) the return value of a sub, through 2) an error return value, up to 3) a non-return value. Of these only the last is what I know as exceptions. I'm for now undecided to regard these three purposes of $! as very clever or as big potential for subtle problems. From the viewpoint of the execution model this environment approach is very clear, though. It nicely unifies return values with in-band errors and out-band exceptions. Which leaves just one wish from my side: make CATCH blocks dispatched. That is they get a signature what kind of exception they handle. The optimizer will make good use of this information. Then the problem reduces to what you do with an unhandled $! at the end of a lexical scope, I don't understand this. The end of scope is either the closing brace or an explicit statement like next, leave, return, yield, fail or die. In the above spectrum of $! these are resultizer just as given, for and friends are topicalizer for $_. But I think simple assignment to $! is not foreseen, or is it? For an example let's assume that / returns 'undef but division by zero' in $! if its rhs is zero. { # begin of scope my $x = 3; my $y = 4; say $x/$y; $x = foo; # foo could return 0 my $z = $y/$x; # $! == 'undef but division by zero' if $x == 0 # Is that assignable to $z? $z++; # This is now a statement in a potential CATCH block? } -- $TSa.greeting := HaloO; # mind the echo!
Re: the $! too global
On 12/5/05, Darren Duncan [EMAIL PROTECTED] wrote: Under the current system, a subroutine argument is an alias for the container passed to it; The most immediate offender here is the referential passing semantics. Here is a code case: sub foo ($x, code) { code(); say $x; } my $bar = 41; foo($bar, { $bar++ }); As far as I recall, the spec says that this should output 42. My intuition tells me that it should output 41. In fact, most modern languages (python, java, ...) would consider it to be 41. They have assignment semantics, rather than binding semantics. What was the reason for choosing binding semantics? Luke
Re: the $! too global
TSa skribis 2005-12-05 12:32 (+0100): IIRC, the default is to be a read-only ref. Not even local modifications s/ref/alias/, which you can see as an implicit or automatic reference, but which we usually don't call that. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: the $! too global
HaloO, Darren Duncan wrote: The problem is that $! is being treated too much like a global variable and not enough like a lexical variable. Consider the following example: Wasn't the idea to have $! only bound in CATCH blocks? sub foo () { try { die MyMessage.new( 'key' = 'dang', 'vars' = {'from'='foo()'} ); }; CATCH { if ($!) { display_message( $! ); } else { display_message( MyMessage.new( 'key' = 'nuthin_wrong', 'vars' = {'from'='foo()'} ) ); } } # end of CATCH } Note that, while my examples don't use a CATCH block (which isn't yet implemented in Pugs), you get the exception from $! or an alias thereof anyway, so whether or not I used CATCH is factored out of the discussion at hand here. Well, I think it brings us back to the discussion about the exception semantics ;) A CATCH block is not supposed to be executed under normal circumstances and $! is undef outside of CATCH blocks. Your code mixes these two things. The big problem here is that almost any argument for any subroutine could potentially come from $!, and it would be rediculous for them all to be 'is copy' just to handle the possibility. Oh, you are advocating exception handling while an exception is handled! Thus after handling the exception exception the one-level-down exception handler procedes normally exceptional again. Finally the normal, non-exceptional layer is re-instated, or some such. Nor is it reasonable for a caller to have to copy $! to another variable before passing it to a subroutine just because that sub *may* have its own try block ... a caller shouldn't have to know about the implementation of what it called. I welcome feedback on this issue and a positive, elegant resolution. I'm still advocating a semantic for exceptions that drop out of the normal flow of events and call code explicitly dedicated to that task. Returning to the normal flow as if nothing exceptional happened is particularly *not* guarenteed! Thus the context of $! is *not* the runtime context, just like the compile context isn't runtime either. Actually, many of the exceptions might be compiled-in assertions that where silenced warnings of the compiler: didn't I say we'll meet again :). -- $TSa.greeting := HaloO; # mind the echo!
Re: the $! too global
On Mon, Dec 05, 2005 at 12:32:03PM +0100, TSa wrote: HaloO, Luke Palmer wrote: The most immediate offender here is the referential passing semantics. IIRC, the default is to be a read-only ref. Not even local modifications are permitted if the 'is copy' property is missing. Here is a code case: sub foo ($x, code) { code(); say $x; } my $bar = 41; foo($bar, { $bar++ }); As far as I recall, the spec says that this should output 42. My intuition tells me that it should output 41. My intuition also opts for 41. Evaluating code() inside foo either violates the constance of its own $x if the changes propagate back into the already bound/passed argument or violates the callers excapsulation. The latter depends on what exactly the second argument of the call of foo closes over. Theoretically the binding of CALLER$bar to foo$x could spill over to the closure which then would mean foo(x = $bar, { $x++ }) and require $x beeing declared either 'is copy' or 'is rw'. In other words it could be marked as error. No, I think not, because the closure on the last line closes over a read/write variable. It happens that read only reference to the same variable is passed into the subroutine, but that's fine, because the subroutine never writes to *its* reference. Thinking about it in C terms, where pointers and values are explicit, it's as if function arguments are always passed as const pointers to a value in a outer scope. This seems fine and consistent to me, but you can never be sure whether anyone else has another pointer to that same value, which they can modify at any time. If nearly all function parameters are PMCs (internally) I don't think that this is an efficiency problem, as PMCs are always reference semantics, even when loaded into Parrot's registers. Nicholas Clark
Re: the $! too global
HaloO, Nicholas Clark wrote: No, I think not, because the closure on the last line closes over a read/write variable. It happens that read only reference to the same variable is passed into the subroutine, but that's fine, because the subroutine never writes to *its* reference. So, you argue that Luke's example should print 42? Thinking about it in C terms, where pointers and values are explicit, it's as if function arguments are always passed as const pointers to a value in a outer scope. This seems fine and consistent to me, but you can never be sure whether anyone else has another pointer to that same value, which they can modify at any time. Sure. But I consider this a semantic nightmare. And the optimizer thinks the same. Basically every variable then becomes volatile in C terms :( Note that lazy evaluation does *not* imply permanent refetching. Actually the opposite is true, lazy evaluation implies some capturing of former state as far as the lazied part needs it to produce its content. And item parameters aren't even lazy by default! If nearly all function parameters are PMCs (internally) I don't think that this is an efficiency problem, as PMCs are always reference semantics, even when loaded into Parrot's registers. The point I'm argueing about is how exposed subs like Luke's foo should be to this. Essentially I want the invocation of foo to create a COW branchpoint in the outer $bar such that when, from where ever, this value is changed, the former $bar that foo's $x was bound to remains unharmed. And is garbage collected when foo is done with it. -- $TSa.greeting := HaloO; # mind the echo!
Re: the $! too global
My gut-level feeling on this is that $! is going to end up being an env variable like $_. (If you don't know what env is then you've not read the conjectural parts of S2 lately.) Then the problem reduces to what you do with an unhandled $! at the end of a lexical scope, which is probably just to fail, insofar as this style of processing is treating the rest of the block as an implicit catch block. We'd also have to determine what handled means. Probably just evaluating $! for boolean is sufficient to mark it as handled. With the env solution, if an inner sub wants to refer to its caller's $!, it'd use $+! or ENV::$! instead of $!. And $! passed to a sub as an argument would simply be a different variable, just as everyone gets their own $_ right now. Larry