Re: Exceptuations
Yuval Kogman wrote: On Thu, Oct 06, 2005 at 14:27:30 -0600, Luke Palmer wrote: On 10/6/05, Yuval Kogman [EMAIL PROTECTED] wrote: when i can't open a file and $! tells me why i couldn't open, i can resume with an alternative handle that is supposed to be the same when I can't reach a host I ask a user if they want to wait any longer when disk is full I ask the user if they want to write somewhere else when a file is unreadable i give the user the option to skip I'm not bashing your idea, because I think it has uses. But I'll point out that all of these can be easily accompilshed by writing a wrapper for open(). That would be the usual way to abstract this kind of thing. Writing a wrapper may be the implementation mechanics: sub safe_open() { call; CATCH { when E::AccessDenied { return show_user_setuid_dialog(); }} } open.wrap(safe_open); But this is just one way to do it, and it fails to provide for helping other people's code: Yuval's GUI environment would offer to fix the problem for ALL file related calls (open, dup, popen, ad nauseum), and would not have to worry about the order in which calls are wrapped. But see below. Stylistically I would tend to disagree, actually. I think it's cleaner to use exception handling for this. Also, this implies that you know that the errors are generated by open. This is OK for open(), but if the errors are generated from a number of variants (MyApp::Timeout could come from anywhere in a moderately sized MyApp), then wrapping is not really an option. I think that what your proposal *really* requires is uniformity. There are other ways to get the same behavior, including an abstract factory interface for exception construction (would provide virtual constructor for exceptions, so permitting userspace to insert a 'retry' behavior), but it has the same vulnerability: the p6core must cooperate in uniformly using the same mechanism to report errors: throw, fail, die, error, abend, whatever it's eventually called. sub *::throw(...) { return recover_from_error([EMAIL PROTECTED]) or P6CORE::throw([EMAIL PROTECTED]); } =Austin
Re: Exceptuations
On Fri, Oct 07, 2005 at 02:31:12 -0400, Austin Hastings wrote: Yuval Kogman wrote: On Thu, Oct 06, 2005 at 14:27:30 -0600, Luke Palmer wrote: On 10/6/05, Yuval Kogman [EMAIL PROTECTED] wrote: when i can't open a file and $! tells me why i couldn't open, i can resume with an alternative handle that is supposed to be the same when I can't reach a host I ask a user if they want to wait any longer when disk is full I ask the user if they want to write somewhere else when a file is unreadable i give the user the option to skip I'm not bashing your idea, because I think it has uses. But I'll point out that all of these can be easily accompilshed by writing a wrapper for open(). That would be the usual way to abstract this kind of thing. Writing a wrapper may be the implementation mechanics: sub safe_open() { call; CATCH { when E::AccessDenied { return show_user_setuid_dialog(); }} } open.wrap(safe_open); But this is just one way to do it, and it fails to provide for helping other people's code: Yuval's GUI environment would offer to fix the problem for ALL file related calls (open, dup, popen, ad nauseum), and would not have to worry about the order in which calls are wrapped. But see below. Stylistically I would tend to disagree, actually. I think it's cleaner to use exception handling for this. Also, this implies that you know that the errors are generated by open. This is OK for open(), but if the errors are generated from a number of variants (MyApp::Timeout could come from anywhere in a moderately sized MyApp), then wrapping is not really an option. I think that what your proposal *really* requires is uniformity. There are other ways to get the same behavior, including an abstract factory interface for exception construction (would provide virtual constructor for exceptions, so permitting userspace to insert a 'retry' behavior), but it has the same vulnerability: the p6core must cooperate in uniformly using the same mechanism to report errors: throw, fail, die, error, abend, whatever it's eventually called. We have: die: throw immediately fail: return an unthrown exception, which will be thrown depending on whether our caller, and their caller - every scope into which this value propagates - is using fatal. This is enough for normal exception handling. As for recovery - the way it's done can be specialized on top of continuations, but a continuation for the code that would run had the exception not been raised is the bare metal support we need to do this. Where this gets taken further by (IMHO overly abstract) exception handling libraries and standardization is a question that application development kits (e.g. Catalyst, GTK, Cocoa) must develop a policy for. return recover_from_error([EMAIL PROTECTED]) what does this do? -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: /me beats up some cheese: neeyah! pgp3FUsw93RD9.pgp Description: PGP signature
Re: Exceptuations
On Fri, Oct 07, 2005 at 05:23:55 +0100, Piers Cawley wrote: Peter Haworth [EMAIL PROTECTED] writes: On Wed, 5 Oct 2005 19:24:47 +0200, Yuval Kogman wrote: On Wed, Oct 05, 2005 at 16:57:51 +0100, Peter Haworth wrote: On Mon, 26 Sep 2005 20:17:05 +0200, TSa wrote: Piers Cawley wrote: Exactly which exception is continued? The bottommost one. If you want to return to somewhere up its call chain, do: $!.caller(n).continue(42) Whow, how does a higher level exception catcher *in general* know what type it should return and how to construct it? The innocent foo() caller shouldn't bother about a quux() somewhere down the line of command. Much less of its innards. Well said. No! Not well said at all! Sorry, I misread that. I thought I was agreeng with how does a higher level exception catcher know what to change in order to make resuming the continuation useful?, especially in the light of Piers saying that the bottom-most exception should be the one resumed. I'm sorry, we appear to have lost some kind of context, the original example given only had one exception thrown, but it got propagated up through a long call chain. At no point did anything catch the original exception and rethrow. If they had, you're absolutely correct in asserting that by default things should resume from the point of the outermost rethrow. A brave exception catcher (or more likely programmer with a debugger) might want to crack that exception open and examine its inner exceptions, but in general that's not going to be safe. It doesn't really matter since 'fail'ed exceptions will simply be converted to a return with the continued value when resumed, and the question of outer/inner scopes is really irrelevant - it's like tail calls. As for die - since there is no implicit returning in die, it might or might not make sense to try and resume. However, for most situations it still looks to me like 'die foo' could be treated as return in a way. Essentially throwing an error means that the function/method who threw it is giving up since it doesn't know how to resume. If the exception handler can find an alternative for that function, and replace the value, it's immediate caller should get the fixed value, since they are the ones who need the value. Functions which delegate exceptions are, again, just like tail calls. -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: /me wields bonsai kittens: neeyah pgpjB4t4GbwlH.pgp Description: PGP signature
Re: Type annotations
Yuval Kogman skribis 2005-10-07 3:02 (+0200): my Array $a = 97; # dies eventually, but when? my Int $b = 3.1415; # dies at all? Both die at compile time, because the user explicitly contradicted him/herself. This is like saying my int = $x :: float; For my Int $c = $float, though, I'd want coercion. And I think it is wrong to have such a huge difference between literals and values: if a variable coerces, a literal has to do so too. I believe that any value should be hardcodeable at any time, for testing and debugging new code. Hard coding a value temporarily shouldn't suddenly make the program die. Otherwise we'll end up with more of the dreaded my $dummy = ... since they're constants and their types are very well known. What is the type of 1.0? I'd prefer all literal numbers to be Num and never Int (this doesn't mean that this specific case can't be optimized to an Int). Likewise, all literal strings should be Str, and all literal arrays should be Array, and all literal hashes should be Hash. (Ignore for a moment that the latter two are references.) The keyword here is all :) sub foo (Int $arg) {...} foo(hello); # should die at the latest when foo() is called There are two reasons to make this die, and I agree with only one of them. (a) Die because the argument passed is Str (b) Die because hello can't in a useful way be coerced to a number If it dies because of b, very good. If because of a, I think we have a huge difference of opinion regarding automatic coercion. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Type annotations
Ashley Winters skribis 2005-10-06 19:30 (-0700): my Array $a = 97; # dies eventually, but when? Runtime -- cannot coerce Int value to Array It is fully determinable at compile time. 97 will never be compatible with Array, so I see no reason to wait. Do remember that some programs run for weeks or months, rather than a few seconds. It's nice to get all the certain failures during compile time. sub foo (Int $arg) {...} foo(hello); # should die at the latest when foo() is called $arg should be undef but Exception::InvalidInteger(Str value 'hello' cannot be coerced to an Int at $?LINE) That'd be a problem with sub foo (Int $arg //= 5) { ... } because the hello is then silently ignored eventually. But, these unthrown exceptions should be emitted as warnings anyway, so it is not really a problem, because everyone has warnings enabled all the time. I wouldn't mind this to fail. If it fails, it can die or be undef, depending on the user's wishes. In my case: die. If bar returns a Str ~~ /Perl6::Grammar::Int/, it gets coerced; otherwise, undef but Exception hello 5 worlds? /^.../ perhaps? And I think we should match against Num, not Int, as it's very hard to have a rule that matches just integers. 0.5e3 is an integer, but 0.5e-3 is not. As stated in my previous message, I think that all numbers should be parsed the same way, and interpreted as Nums. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Type annotations
On Fri, Oct 07, 2005 at 12:42:01 +0200, Juerd wrote: For my Int $c = $float, though, I'd want coercion. And I think it is wrong to have such a huge difference between literals and values: if a variable coerces, a literal has to do so too. How do you tell the compiler this must never be a float, ever? There is a conflict between the usefulness of coercion and the usefulness of staticness, and I think we need to be able to express both. Perhaps we need two ways to type annotate: hard annotations - applies to assignment or binding lvalues, and states that the type must be an accurate subtype - no coercion is allowed at all. soft annotations - applies to assignment or binding lvalues, and specifies that the thing contained in it must always be of the annotated type, after the assignment. That is - a value must be coerced as a copy to enter this container if it's type doesn't match. -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: /me sushi-spin-kicks : neeyah pgpT5DKCUCMHu.pgp Description: PGP signature
Re: Type annotations
Yuval Kogman skribis 2005-10-07 12:53 (+0200): On Fri, Oct 07, 2005 at 12:42:01 +0200, Juerd wrote: For my Int $c = $float, though, I'd want coercion. And I think it is wrong to have such a huge difference between literals and values: if a variable coerces, a literal has to do so too. How do you tell the compiler this must never be a float, ever? By cramming it into a variable that cannot hold a float. I think there should be some syntax to disable coercion, but that coercion must be the default behavior. A simple operator that can be placed flexibily would certainly help. I'll demonstrate with (!), although that's probably not the right glyph: sub foo (Int $foo); # coerce, possibly lossily sub foo (Int(!) $foo); # coerce, but only if possible without loss my Int(!) $foo = $bar; my Int $foo = (!)$bar; sub bar (Int $foo); bar((!)$float); Unintentionally, the (!) is always left of the sigil. I like that, even though whitespace-wise I see it as two different things. Maybe the default should be configurable, allowing lossy coercion being the default default, and (?) can be used to override a current default of disallowing lossy coercion. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Exceptuations
[EMAIL PROTECTED] wrote: I'm not bashing your idea, because I think it has uses. But I'll point out that all of these can be easily accompilshed by writing a wrapper for open(). That would be the usual way to abstract this kind of thing. My take on this: resumable exceptions break encapsulation no more (and no less) than using callbacks. The function that throws a resumable exception can only do this knowingly, and it could just as well offer a callback for that specific patchable error. So why take away a potentially highly useful tool? BTW, two languages I know of have resumable exceptions: Common LISP and TOM. Neither supports continuations, instead, they separate raising exception (which runs a handler; this is implemented as a callback) from unwinding stack (which happens when the handler actually throws; it can choose to return instead, resuming execution if the raising function is okay with it). At least in Common LISP this is used a *lot* during interactive development, as it allows the developer to quickly patch things up without reruning the failed test. Assuming perl6 keeps the pugs-style interactive shell, I suspect resumable exceptions will be quickly added into the standard library if they don't pass into the standard. Yes, they're that useful. Miro
Re: $value but lexically ...
[EMAIL PROTECTED] wrote: Would this work too? 0 but role {} Most certainly, but you would have no way to refer to that role later, so it is questionable how useful that construct is. No, it's not questionable. That is a useless construct. Luke Can an inline role be named? 0 but role is_default {} Miro
Re: Exceptuations (proposal for RESUME blocks)
HaloO Yuval Kogman wrote: We have: die: throw immediately fail: return an unthrown exception, which will be thrown depending on whether our caller, and their caller - every scope into which this value propagates - is using fatal. This is enough for normal exception handling. Is it only me seeing a self-contradiction in 'normal exception'? But here are some ideas for renaming: resumeable exception - retro-fitted pre-condition or: negotiated pre-condition or sumply resumption? My mental picture is that of an outer scope in the call chain attempting to meet the requirements communicated from an unknown inner scope and then resuming where the failed pre-condition was spotted. But I wouldn't require this to be implemented in a very efficient way! When you need event handling, implement it. E.g. the fail form needs to preserve the call chain until the failure is handled. Handling might be as easy as evaluation in void context or usage of // in a non-fatal scope. Otherwise a CATCH block is needed. Or perhaps a RESUME block and a correspondingly enhanced require form? That would integrate the AUTODEF and friends with the error/exception/control/assertion system. To illustrate the idea: if !$file.writeable { require $file.writeable; } or perhaps even without the if. And then somewhere up the call chain RESUME { when .writeable { make $! writeable; resume } # more typeish syntax when File::writeable { make $! writeable; resume } } # with type outside RESUME File::writeable { make $! writeable; resume } The resume could actually be the default way to exit a RESUME block. As for recovery - the way it's done can be specialized on top of continuations, but a continuation for the code that would run had the exception not been raised is the bare metal support we need to do this. Yep, we need to agree on a form how to communicate unmet requirements outwards. The only entity that comes to my mind that usually matches requirements is the type system or meta information repository. Where this gets taken further by (IMHO overly abstract) exception handling libraries and standardization is a question that application development kits (e.g. Catalyst, GTK, Cocoa) must develop a policy for. Well, yes! A non-trivial framework will install a bunch of types. A subset of which beeing exception (sub)types. The challenge is then shifted to inter-framework unification =8) But one thing that should work is tunneling standard resumption requests through such a framework. -- $TSa.greeting := HaloO; # mind the echo!
Re: $value but lexically ...
Miroslav Silovic skribis 2005-10-07 13:07 (+0200): Can an inline role be named? 0 but role is_default {} This is a nice idea. It would require named roles (and to really be succesful, also classes, subs, methods, ...) declarations to be expressions, but I see no downside to that. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Exceptuations
Yuval Kogman wrote: On Fri, Oct 07, 2005 at 02:31:12 -0400, Austin Hastings wrote: Yuval Kogman wrote: Stylistically I would tend to disagree, actually. I think it's cleaner to use exception handling for this. Also, this implies that you know that the errors are generated by open. This is OK for open(), but if the errors are generated from a number of variants (MyApp::Timeout could come from anywhere in a moderately sized MyApp), then wrapping is not really an option. I think that what your proposal *really* requires is uniformity. There are other ways to get the same behavior, including an abstract factory interface for exception construction (would provide virtual constructor for exceptions, so permitting userspace to insert a 'retry' behavior), but it has the same vulnerability: the p6core must cooperate in uniformly using the same mechanism to report errors: throw, fail, die, error, abend, whatever it's eventually called. We have: die: throw immediately fail: return an unthrown exception, which will be thrown depending on whether our caller, and their caller - every scope into which this value propagates - is using fatal. This is enough for normal exception handling. Yet here we are discussiong abnormal exception handling. As for recovery - the way it's done can be specialized on top of continuations, but a continuation for the code that would run had the exception not been raised is the bare metal support we need to do this. No, it isn't. It's *one way* to do this. Any mechanism which transfers control to your error-recovery code in such a way that can cause an uplevel return of a substituted value is the bare metal support we need. You're conflating requirements and design. I suggested an alternative *design* in my prior message, to no avail. Try this instead: You overload the global 'die' with a sub that tries to decode the error based on its arguments. If it cannot comprehend the error, it invokes P6CORE::die(). If it comprehends the error, it tries to resolve it (querying the user, rebooting the machine to free up space in /tmp, whatever) and if successful it returns the fixed value. But wait! This requires that everyone do return die ... instead of die..., and we can't have that. So you add a source filter, or macro, or tweak the AST, or perform a hot poultry injection at the bytecode level, or whatever is required to convert die into return die whereever it occurs. Et voila! No exceptions are caught, no continuations are released into the wild. And yet it flies. Much like the hummingbird it looks a little awkward, and I'm way not sure that munging bytecodes is necessarily a better idea. But the point is that resuming from an exception (or appearing to) is not bound to implemented with continuations. =Austin Et vidi quod aperuisset Autrijus unum de septem sigillis, et audivi unum de quatuor animalibus, dicens tamquam vocem tonitrui : Veni, et vide. Et vidi : et ecce camelus dromedarius, et qui scriptat super illum, habebat archivum sextum, et data est ei corona, et exivit haccum ut vinceret. Apocalypsis 6:1 (Vulgata O'Reilly)
Re: Type annotations
On Fri, 2005-10-07 at 12:49 +0200, Juerd wrote: Ashley Winters skribis 2005-10-06 19:30 (-0700): my Array $a = 97; # dies eventually, but when? Runtime -- cannot coerce Int value to Array It is fully determinable at compile time. 97 will never be compatible with Array, so I see no reason to wait. If I added a multisub for Array assignment so that assigning an integer value set the length of the array, would 97 be compatible with Array? Do remember that some programs run for weeks or months, rather than a few seconds. It's nice to get all the certain failures during compile time. How about in unreachable code (which I do actually believe compilers can detect some of the time)? -- c
Re: Type annotations
chromatic skribis 2005-10-07 12:50 (-0700): my Array $a = 97; # dies eventually, but when? Runtime -- cannot coerce Int value to Array It is fully determinable at compile time. 97 will never be compatible with Array, so I see no reason to wait. If I added a multisub for Array assignment so that assigning an integer value set the length of the array, would 97 be compatible with Array? If that is actually possible: good point. Do remember that some programs run for weeks or months, rather than a few seconds. It's nice to get all the certain failures during compile time. How about in unreachable code (which I do actually believe compilers can detect some of the time)? I'm quite ambivalent about this. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Type annotations
On 10/7/05, chromatic [EMAIL PROTECTED] wrote:\ If I added a multisub for Array assignment so that assigning an integer value set the length of the array, would 97 be compatible with Array? You're not allowed to overload assignment. But you are allowed to overload coersion. Essentially, every expression gets a coerce:as($expr, $current_context) wrapped around it (where these are optimized away when they do nothing). If you allow definition of these at runtime, there are two side-effects: 1) No typechecking can ever take place in any form. 2) No coerce calls can ever be optimized away. These are very unfortunate. So I'm inclined to say that you can't overload coersion at runtime. Juerd writes: Do remember that some programs run for weeks or months, rather than a few seconds. It's nice to get all the certain failures during compile time. There is a tradeoff around typecheckers that bounce on either side of the Halting program. Either: There are programs you call erroneous when they are not; or there are programs you call correct when they are erroneous. I get the impression that most of us want the latter kind for annotations (in the absence of use static). Luke Luke
Re: $value but lexically ...
On 10/7/05, Juerd [EMAIL PROTECTED] wrote: Miroslav Silovic skribis 2005-10-07 13:07 (+0200): Can an inline role be named? 0 but role is_default {} This is a nice idea. It would require named roles (and to really be succesful, also classes, subs, methods, ...) declarations to be expressions, but I see no downside to that. Well, I see a cognitive downside. That is, package declarations (the default) don't create closures. It's like this: sub foo($x) { sub bar() { return $x; } return bar; } foo(42).(); # Restricting expressions to anonymous subs forces you to say what you mean. Because sometimes when you say: 0 but role is_default { } You're going to mean package role, and some of the time you're going to mean lexical. I'd be more in favor of: 0 but my role is_default { } In fact, it may be the case that that's already valid. Luke
Re: $value but lexically ...
Luke Palmer skribis 2005-10-07 15:31 (-0600): Well, I see a cognitive downside. That is, package declarations (the default) don't create closures. It's like this: sub foo($x) { sub bar() { return $x; } return bar; } foo(42).(); # Does this mean that this Perl 5 snippet no longer does the same in Perl 6? { my $foo = 5; sub bar { return $foo; } } Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: $value but lexically ...
On 10/7/05, Juerd [EMAIL PROTECTED] wrote: Luke Palmer skribis 2005-10-07 15:31 (-0600): sub foo($x) { sub bar() { return $x; } return bar; } foo(42).(); # Does this mean that this Perl 5 snippet no longer does the same in Perl 6? { my $foo = 5; sub bar { return $foo; } } Uh no. Okay, when I said that they don't close, I guess I meant they don't close like anonymous routines do. It works precisely like Perl 5's: sub foo { my $foo = 5; sub bar { return $foo; } return \bar; } I don't think I've ever seen that used in Perl 5. Closing over that $foo doesn't mean anything. That's why we're allowing my before such declarations now, so that they can close over something useful. Luke
Re: $value but lexically ...
On Fri, Oct 07, 2005 at 03:46:02PM -0600, Luke Palmer wrote: Uh no. Okay, when I said that they don't close, I guess I meant they don't close like anonymous routines do. It works precisely like Perl 5's: sub foo { my $foo = 5; sub bar { return $foo; } return \bar; } I don't think I've ever seen that used in Perl 5. Closing over that $foo doesn't mean anything. Well strictly speaking it means that bar() captures the first instance of foo()'s $foo, which isn't often very useful. -- The Enterprise successfully ferries an alien VIP from one place to another without serious incident. -- Things That Never Happen in Star Trek #7
Re: Type annotations
On Fri, 2005-10-07 at 15:22 -0600, Luke Palmer wrote: On 10/7/05, chromatic [EMAIL PROTECTED] wrote:\ If I added a multisub for Array assignment so that assigning an integer value set the length of the array, would 97 be compatible with Array? You're not allowed to overload assignment. $ perldoc perltie I don't really care how I do it, provided that I don't have to write PIR or C just to make this possible, but I want the option to have at least same power as Perl 5 to do weird things if that's what it takes to do really useful things that you or I or @Larry can't imagine right now. But you are allowed to overload coersion. Essentially, every expression gets a coerce:as($expr, $current_context) wrapped around it (where these are optimized away when they do nothing). If you allow definition of these at runtime, there are two side-effects: 1) No typechecking can ever take place in any form. 2) No coerce calls can ever be optimized away. These are very unfortunate. So I'm inclined to say that you can't overload coersion at runtime. No one can ever overload assignment or coercion at run time because you want theoretical programs you haven't yet to run VERY VERY FAST? Me, I just want to get my job done without always having to ponder the beauty of type conceptual purity while I'm fiddling with BEGIN blocks and CHECK blocks and INIT blocks, trying to dodge inscrutable type mismatch errors while guessing the combination of the locks on the escape hatches built into the language. I'm sort of feeling the inclination to argue for a lexical RUN VERY VERY FAST switch that lets you (or me sometimes) the programmer say Go on and hurt me when it's totally worth it, not to apply cheese graters, hot peppers, and David Hasselhoff CDs with fulsome BD glee to every programmer who ever types perl6 ./hello_world.pl. -- c
Re: Type annotations
On 10/7/05, chromatic [EMAIL PROTECTED] wrote: On Fri, 2005-10-07 at 15:22 -0600, Luke Palmer wrote: But you are allowed to overload coersion. Essentially, every expression gets a coerce:as($expr, $current_context) wrapped around it (where these are optimized away when they do nothing). If you allow definition of these at runtime, there are two side-effects: 1) No typechecking can ever take place in any form. 2) No coerce calls can ever be optimized away. These are very unfortunate. So I'm inclined to say that you can't overload coersion at runtime. No one can ever overload assignment or coercion at run time because you want theoretical programs you haven't yet to run VERY VERY FAST? No, you can't overload assignment at runtime because you can't overload assigment at any time, so says the language spec (well, not any formal spec; so says Larry as far as I remember). I gathered that the reason for this was not for speed, but for semantic consistency, like in Perl 5. My perspective on the argument is that if you let people overload assignment, then you make everyone uneasy about assigning for fear that it will be dwimmifully overloaded and not do the right thing. But I'm just taking that part from what I know. Also, only the second of my two reasons had to do with speed, which I agree can't be argued until we see some numbers (but I have a hunch, because not optimizing away the _many_ do-nothing coersions, you are effictively adding a complex trace condition in a debugger; and you have seen how slowly those run). As for the first argument, presumably people put type annotations on their code so that we can do some reasoning and tell them about errors. If type annotations didn't do that for my code, I wouldn't use type annotations (in fact, I probably won't end up using them too much anyway). But by allowing the definition of new coersions at runtime, you invalidate any error a type checker might think it has found. Not to say that a lexical pragma saying keep all coersions in the generated code so that if you expect to be doing something nasty in a scope, you can. But again, you kill any typechecking that code might be wanting, and you probably reduce the code's speed by an order of magnitude (again, just a guess). Luke
Re: Type annotations
On 10/7/05, Luke Palmer [EMAIL PROTECTED] wrote: On 10/7/05, chromatic [EMAIL PROTECTED] wrote: On Fri, 2005-10-07 at 15:22 -0600, Luke Palmer wrote: But you are allowed to overload coersion. Essentially, every expression gets a coerce:as($expr, $current_context) wrapped around it (where these are optimized away when they do nothing). If you allow definition of these at runtime, there are two side-effects: 1) No typechecking can ever take place in any form. I'd like to add that most people don't want typechecking if you don't insert annotations, so you're not subject to type purity there. I was arguing for making the annotations that people do willfully put in actually mean something. Luke
Re: Type annotations
On Fri, 2005-10-07 at 17:43 -0600, Luke Palmer wrote: No, you can't overload assignment at runtime because you can't overload assigment at any time, so says the language spec (well, not any formal spec; so says Larry as far as I remember). I'm wearing my just a programmer, not a denizen of p6l hat. Pretend I don't know the difference between overloading assignment and setting special STORE magic and I want the option to be able to have Array do something meaningful and significant to both of us when I assign a constant scalar to it. Again, I don't care *how* I accomplish it, as long as I don't have to root around in the source code of Perl 6 itself to make it work. As for the first argument, presumably people put type annotations on their code so that we can do some reasoning and tell them about errors. I don't want to use a module off of 6PAN that breaks my code because its type annotations have leaked out into the rest of my code and I have no idea what the compiler error messages mean. It's sort of the anti-$, except it can make my program run faster. (Correct answers: depends on the question. Wrong answers: instantaneous.) It's up to the person who *runs* the code, not the person who writes a component and can't possibly decide from now 'til forever exactly every circumstance in which he will allow people to use the component, to decide what level of compiler complexity and strictness to allow. If my program takes a second to run, I don't want to spend several seconds performing type checks more suited for a long-running program. If my program's a network-bound server process that ought to share most of its memory, maybe I don't want to JIT things. If I'm running the final customer tests before delivering frozen bytecode to customers who won't be changing the code, maybe I want as many checks and optimizations as possible. Making the author of a module decide that is wrong. Maybe allowing a module author to request stricter typing within the module is fine, but it oughtn't be the last word on the subject. I've programmed in languages that froze certain library code at a specific level of strictness for philosophical and speed-related reasons. It was painful when I needed to do something that the language designers and library developers never thought I might need to do. Sure, I have a just a programmer hat, but that doesn't mean I can't use well-encapsulated magic when I really need it. To make this concrete -- Java's final: broken, wrong, stupid. Pick three. Types are abstractions and all abstractions break sometimes. Of the possible analysis features the compiler can perform by default, I prefer to enforce sensible symbol names, as-small-as-possible scopes, and lack of near and exact duplication. These to me are much more useful than an optional-until-someone-somewhere-uses-it type system that prevents me from finding the escape hatches purposely built into the language. -- c
Re: Type annotations
On 10/7/05, chromatic [EMAIL PROTECTED] wrote: On Fri, 2005-10-07 at 17:43 -0600, Luke Palmer wrote: No, you can't overload assignment at runtime because you can't overload assigment at any time, so says the language spec (well, not any formal spec; so says Larry as far as I remember). Again, I don't care *how* I accomplish it, as long as I don't have to root around in the source code of Perl 6 itself to make it work. That's easy. Define coerce:as (Int -- Array) {...}. Don't define it after CHECK is run. As for the first argument, presumably people put type annotations on their code so that we can do some reasoning and tell them about errors. I don't want to use a module off of 6PAN that breaks my code because its type annotations have leaked out into the rest of my code and I have no idea what the compiler error messages mean. It's sort of the anti-$, except it can make my program run faster. (Correct answers: depends on the question. Wrong answers: instantaneous.) That's what this thread is about. We're trying to nail down the semantics so we know exactly how soft to be when an unannotating programmer imports an annotated module. It's up to the person who *runs* the code, not the person who writes a component and can't possibly decide from now 'til forever exactly every circumstance in which he will allow people to use the component, to decide what level of compiler complexity and strictness to allow. If my program takes a second to run, I don't want to spend several seconds performing type checks more suited for a long-running program. If my program's a network-bound server process that ought to share most of its memory, maybe I don't want to JIT things. If I'm running the final customer tests before delivering frozen bytecode to customers who won't be changing the code, maybe I want as many checks and optimizations as possible. Of course. To me, those seems like flags of the compilation (or running, since most of the time compilation will not be a separate phase). The only person who gets to specify those is the person who writes main.pl, because he has access to the #! line. I've programmed in languages that froze certain library code at a specific level of strictness for philosophical and speed-related reasons. It was painful when I needed to do something that the language designers and library developers never thought I might need to do. Sure, I have a just a programmer hat, but that doesn't mean I can't use well-encapsulated magic when I really need it. Once you start diving into the guts of another module, you should be prepared to start telling the compiler that it's wrong. I'm certainly not saying that you shouldn't be able to do that. Types are abstractions and all abstractions break sometimes. Of the possible analysis features the compiler can perform by default, I prefer to enforce sensible symbol names, as-small-as-possible scopes, and lack of near and exact duplication. These to me are much more useful than an optional-until-someone-somewhere-uses-it type system that prevents me from finding the escape hatches purposely built into the language. Okay. Some people find type annotations to be more useful than you do though. If you want to argue that Perl shouldn't have type annotations, go ahead. But for the moment, we're under the assumption that Perl has the ability to make type annotations, and that those annotations should have some affect on your program. And this thread is trying to decide what that effect is. Luke
Re: Exceptuations
On Fri, Oct 07, 2005 at 10:28:13 -0400, Austin Hastings wrote: But the point is that resuming from an exception (or appearing to) is not bound to implemented with continuations. What's the point? Continuations are good for exactly this purpose. Parrot already supports them. I see absolutely no reason why we would want to implement this any other way but using continuations. -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: *shu*rik*en*sh*u*rik*en*s*hur*i*ke*n*: neeyah pgpRP3mAuY8ah.pgp Description: PGP signature
Re: Type annotations
On Fri, Oct 07, 2005 at 12:50:09 -0700, chromatic wrote: On Fri, 2005-10-07 at 12:49 +0200, Juerd wrote: Ashley Winters skribis 2005-10-06 19:30 (-0700): my Array $a = 97; # dies eventually, but when? Runtime -- cannot coerce Int value to Array It is fully determinable at compile time. 97 will never be compatible with Array, so I see no reason to wait. If I added a multisub for Array assignment so that assigning an integer value set the length of the array, would 97 be compatible with Array? That's a compile time reachable analysis. If the compiler finds out that: a. no code will be evaled (due to 'use optimize' or just plain lack of require, eval etc in the code) b. there is no compatbile multisub then it should throw an error How about in unreachable code (which I do actually believe compilers can detect some of the time)? These errors should probably still persist, even if dead code is subsequently removed from the bytecode, because dead code can become undead code if certain things change (compile time foldable conditionals over e.g. $*OS are such a scenario) and the same program should be typed the same way everywhere for a given version of Perl. -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: /me does a karate-chop-flip: neeyah!! pgpdHU54ECTW7.pgp Description: PGP signature