use less in perl6?
Perl 6 has some more interesting capabilities for lexical scoped hinting of tradeoff preferences. For example: use less precision; # the default nums created in this scope are # lower precision floats use less cpu; # many places this can have a desired effect use less memory; # especially in the underlying impls of # structures use less stuff; # might have a meaning for a library Mostly I think it's a matter of just controlling the default parrot PMC implementations underlying the structures. Aside from that there might be some other, perhaps more global settings. IMHO perl6 should allow some control over these. Here's where the design comes in: control over lexical scoped params, vs. application wide ones granuality of control and it's coupling to parrot control from the perspective of the user of a library - who is responsible? how is that expressed? is it per context? per object? per scope? globally scoped? how is it future proofed? i'd like to tell a piddle impl i want some behavior, and I'd like my program to exploit it if i subsequently update the piddle implementation, and it suddenly learns what i mean. How should this stuff be expressed? 'use less' is cute, but i don't think it really gets there. Perhaps this interface, or it's principals should also allow similarly controlled debugging/tracing. Usually when trying to look inside a big app, you are only concerned about a specific part. I think this is very analogeous to optimization hints: sometimes you want to override it form the command line sometimes you only want it to apply to calls from a certain place sometimes you want to enable it from within the code it applies to, and sometimes outside of it you often want a volume knob for this behavior you want several instances of usage to not conflict I'd like to see what the design team can do about this. Ciao! -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: /me groks YAML like the grasshopper: neeyah!! pgpeUBPYSoS0d.pgp Description: PGP signature
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Luke Palmer wrote: Unless the caller can't see the signature, as is the case with methods. [..] Again, this can't be done unless you know the signature. And in fact, we can't do type inference on methods unless we do type inference everywhere, which we can't do if we want an autoloader. This sounds to me even messier than the C header file mishap, or even the old KR days without protoyped declarations! How can the programmer know about the signature of a method? I guess from some documentation. And the prime documentation of an interface is a formal interface definition provided by the language. This is e.g. what Ada does. Also CORBA is build around its IDL (Interface Definition Language) and from version 3.0 onwards a CDL (Component Definition Language). If I understand you correctly the use statement is more like a linker/loader directive than a compile time interface include? BTW, is it foreseen to have a clear conceptual split between the compiler and the loader? Or is that all blurred? -- TSa (Thomas Sandla)
Re: use less in perl6?
On Wed, 2005-03-30 at 10:20 +0200, Yuval Kogman wrote: Perl 6 has some more interesting capabilities for lexical scoped hinting of tradeoff preferences. For example: use less precision; # the default nums created in this scope are # lower precision floats use less cpu; # many places this can have a desired effect use less memory; # especially in the underlying impls of # structures use less stuff; # might have a meaning for a library Hmmm.. I wonder what this would do: use less syntax; ;-)
Re: use less in perl6?
Aaaron~ On Wed, 30 Mar 2005 08:48:55 -0500, Aaron Sherman [EMAIL PROTECTED] wrote: On Wed, 2005-03-30 at 10:20 +0200, Yuval Kogman wrote: Perl 6 has some more interesting capabilities for lexical scoped hinting of tradeoff preferences. For example: use less precision; # the default nums created in this scope are # lower precision floats use less cpu; # many places this can have a desired effect use less memory; # especially in the underlying impls of # structures use less stuff; # might have a meaning for a library Hmmm.. I wonder what this would do: use less syntax; ;-) Back out the entire p6 grammar and put in lisp's instead... Matt -- Computer Science is merely the post-Turing Decline of Formal Systems Theory. -???
Re: use less in perl6?
On Wed, 30 Mar 2005 08:56:58 -0500, Matt Fowles [EMAIL PROTECTED] wrote: On Wed, 30 Mar 2005 08:48:55 -0500, Aaron Sherman [EMAIL PROTECTED] wrote: use less syntax; Back out the entire p6 grammar and put in lisp's instead... Huh. I suppose that's the only difference these days... ;) -- Schwäche zeigen heißt verlieren; härte heißt regieren. - Glas und Tränen, Megaherz
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Tue, 2005-03-29 at 16:00 -0700, Luke Palmer wrote: Unless the caller can't see the signature, as is the case with methods. I need to understand this piece. In this code: class X { method meth() {...} } class Y is X { method meth() is rw(int $r) {...} } sub foo { return my Y $tmp } my X $a = foo(); $a.meth() = 8; What happens? Do we impose a compiler-level restriction on the call that prevents this, or do we always allow it, and let the run-time take care of it? My preference by far is to let the compiler tell you that it's illegal because there's no valid reason for a sub-class to change the semantics of a polymorphically invoked method like this. The sub-class might introduce new semantics, but when manipulated as a base-class those semantics should only come into play when they are invoked via the interface of the base class. That sounds like an almost axiomatic truism to me, but if I read what you wrote correctly, you don't seem to agree. It's important to look at this as a two(more?)-stage process with different agendas and limitations, no? More generally, I think it's always a valid thing for the compiler to impose the restrictions of the type it knows about, regardless of what polymorphism might discover later on at run-time. This means that you can't do this: class X { } class Y { method m (int $a) {...} } my X $ob = get_me_a_Y(); $ob.m(1); because X does not provide an m. Again, this can't be done unless you know the signature. And in fact, we can't do type inference on methods unless we do type inference everywhere, which we can't do if we want an autoloader. You can combine and autoloader with type inference. You may not choose to, but it's not impossible. You can load the signatures ahead of time, and link the code at run-time. What gets dicy is this: eval use X; my X $a; $a.m(1); I think that's invalid too, but I'm not sure.
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Aaron Sherman writes: On Tue, 2005-03-29 at 16:00 -0700, Luke Palmer wrote: Unless the caller can't see the signature, as is the case with methods. I need to understand this piece. In this code: class X { method meth() {...} } class Y is X { method meth() is rw(int $r) {...} } sub foo { return my Y $tmp } my X $a = foo(); $a.meth() = 8; What happens? Do we impose a compiler-level restriction on the call that prevents this, or do we always allow it, and let the run-time take care of it? My preference by far is to let the compiler tell you that it's illegal because there's no valid reason for a sub-class to change the semantics of a polymorphically invoked method like this. The sub-class might introduce new semantics, but when manipulated as a base-class those semantics should only come into play when they are invoked via the interface of the base class. That sounds like an almost axiomatic truism to me, but if I read what you wrote correctly, you don't seem to agree. No, I think I agree with you here. But what happens if you change you're second-to-last line to: my $a = foo(); $a.meth() = 8; Perl 6 is both a statically typed language and a dynamically typed language, and the problems that I am addressing are mostly about the dynamic part. You can combine and autoloader with type inference. You may not choose to, but it's not impossible. You can load the signatures ahead of time, and link the code at run-time. What gets dicy is this: eval use X; my X $a; $a.m(1); I think that's invalid too, but I'm not sure. Again, that's invalid in the static world, but it should work if you s/my X/my/. The kinds of type inferrence people are saying would solve our problems require us to infer code like this, which we can't do. There _is_ a way to do it, actually, but we need to really screw around with what kinds of things are inferred. In the case: my $a; $a.m(1); We assign the type objects with an 'm' method that can take a single integer to $a. This is a category of objects that spans many classes, and does not fit into a nice little tree. I think that before we take on such an idea, we should look for research about this kind of type inference. Luke
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, Mar 30, 2005 at 09:40:26AM -0700, Luke Palmer wrote: : There _is_ a way to do it, actually, but we need to really screw around : with what kinds of things are inferred. In the case: : : my $a; : $a.m(1); : : We assign the type objects with an 'm' method that can take a single : integer to $a. This is a category of objects that spans many classes, : and does not fit into a nice little tree. I think it's perfectly fine for the compiler to make use of whatever information it has. The trick is to never make any unwarranted assumptions, such as Nobody will ever add another class with an 'm' method. It can assume that only if you explicitly tell it to, and if nobody has jimmied any classes to remain open and/or non-final. Otherwise you have to at least be prepared to recalculate the effective meaning of your 'm' type, and know when that recalculation is necessary. Even if classes are open and non-final, you can at least cache information that is temporarily true, and make good use of it. Perl 5 certainly takes that approach in spots. Perl 5 doesn't do a good job of localizing the damage, however. If you monkey around with your classes, it basically throws away all the cached data by incrementing a generation count. : I think that before we take on such an idea, we should look for : research about this kind of type inference. As long as we includes you, that's fine by me. :-) Larry
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
HaloO Luke, you wrote: No, I think I agree with you here. But what happens if you change you're second-to-last line to: my $a = foo(); $a.meth() = 8; Perl 6 is both a statically typed language and a dynamically typed language, and the problems that I am addressing are mostly about the dynamic part. My state of affairs is that these two lines of code lack declarations that clearly announce what the user of foo and X wanted: 1) foo returns an X 2) an X does .meth() Where, how and if these are implemented, autoloaded or what not is another business. Client side type checking ensures that no usage outside the declared behaviour occurs. For larger declarations I which to put them into an interface module, package, header or however that is called and include it. On the implementation side we get the complementary definitions: 1) here's an X that does .meth() 2) here's a foo that returns an X The dynamism of Perl6 should revolve around how to bring these two sides of an interface together conveniently and efficiently. Just using 1% of a big package shouldn't let your 10-liner become a bloated pig! And of course the builtin functionality and the packages available from CPAN save the typical small scale programmer from extensive declarations. But to use a complex module you have to read documentation to get the idea to call .meth() in the first place. And then I like to get the hint from the compiler that there is no .mth() and happily correct the spelling error. Spotting these types of errors is were computers are much better than humans :) We assign the type objects with an 'm' method that can take a single integer to $a. This is a category of objects that spans many classes, and does not fit into a nice little tree. I think that before we take on such an idea, we should look for research about this kind of type inference. Type calculations are not inherently difficult, especially when junctive values are at hand. The problem is that the inference can quickly diverge to the useless something is done to an anything. Dwimmery works best when it bridges little gaps in an otherwise very rich semantic network. -- TSa (Thomas Sandla)
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, 2005-03-30 at 11:40, Luke Palmer wrote: No, I think I agree with you here. But what happens if you change you're second-to-last line to: my $a = foo(); $a.meth() = 8; Perl 6 is both a statically typed language and a dynamically typed language, and the problems that I am addressing are mostly about the dynamic part. The way I've always thought about that one (and perhaps I'm just misguided) is that you're really saying: my unknown $a = foo(); $a.meth() = 8; And unknown does something strange (unique?) along the lines of: class unknown is scalar, pragma::everything {...} That is, logically, unknown allows you to use any interface (note that I said pragma because sub-classes of scalar don't get this behavior), but realistically, a compiler must simply throw up its hands on that ONE type of variable and allow you to get away with nearly anything (and leave it up to the run-time to use your vtable to discover the truth). The feature you get here is that a compiler that wanted to spend hours of compute-time validating your program COULD search every known interface, and tell you: Unknown method signature in dynamic call at line 100 or an even smarter compiler could say: Method signature on line 100 unrelated to previous usage on line 98 That is, you called a method on line 98 that matches no classes above, below or the same as the classes matched by the signature of the method you called on line 100. This kind of lint checking would be very handy, though I'm sure it would be too time-consuming for the general -w case. eval use X; my X $a; $a.m(1); I think that's invalid too, but I'm not sure. Again, that's invalid in the static world, but it should work if you s/my X/my/. The kinds of type inferrence people are saying would solve our problems require us to infer code like this, which we can't do. I think there, you are well justified in saying that you can try to get away with it, but a compiler that's smart enough to realize that you need a run-time loaded dynamic type to make it work should punt it. Of course, that ASSUMES that auto-loading is a two-stage process with an interface definition and a run-time code load. Given that, what you wanted was auto-loading, not run-time string eval. Those are not the same thing. If you're doing code-generation at run-time ... huh, what happens, let me think... Let's say you generate this code from a specification of some sort: class __c001 { method __m001(int $__i001) {...} } __c001.new; and then try to call: (eval $generated_code).__m001(1); Ok, that's good because eval returns the same unknown scalar type as a bare my declares. I guess you can also taint anything that comes from an eval and just avert your gaze... you'll have to taint objects that use non-Perl6 object systems in the same way, anyhoo: my $thing = Runtime::Python::re::compile('.*'); $thing.search('moo'); There _is_ a way to do it, actually, but we need to really screw around with what kinds of things are inferred. In the case: my $a; $a.m(1); We assign the type objects with an 'm' method that can take a single integer to $a. This is a category of objects that spans many classes, and does not fit into a nice little tree. I think that before we take on such an idea, we should look for research about this kind of type inference. Heh well, here's where we notice that Aaron reads and replies in series by paragraph ;-) -- Aaron Sherman [EMAIL PROTECTED] Senior Systems Engineer and Toolsmith It's the sound of a satellite saying, 'get me down!' -Shriekback
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Thomas Sandla writes: And of course the builtin functionality and the packages available from CPAN save the typical small scale programmer from extensive declarations. But to use a complex module you have to read documentation to get the idea to call .meth() in the first place. And then I like to get the hint from the compiler that there is no .mth() and happily correct the spelling error. Spotting these types of errors is were computers are much better than humans :) And it sure would be able to spot that kind of error, supposing the sub declaration is in scope. But suppose it weren't. Maybe that's a bit hard to fathom if you haven't written an autoloader. Suppose, then, that you have this code: class CodeProxy { has Code $.code is rw; sub call ($a) { $.code($a); } } This is valid Perl 6, and anyone who says otherwise (because of type signatures) is changing the Perl philosophy too much to be taken seriously. Now, tell me at compile time whether the call inside `call` is valid. Of course, the alleged type inferencer can do some magic and make sure that it is. It says that the $.code member variable is not just of type `Code`, but of type `Code is sig($x) forall $x` (are siglets still around?). Then this code would not fail to compile, but any code that tried to assign an incompatible routine to the .code member would fail to compile. At runtime, you load in a new subclass of `CodeProxy`, `DoubleCodeProxy` (this programmer apparently doesn't know that we support variadic signatures :-) class DoubleCodeProxy is CodeProxy { method call ($a, +$b) { .code().($a, $b); } } Again, undisputably valid Perl 6. Every method takes an implicit `*%`, so it's not an interface violation to add a new named parameter. And now it's okay to assign a code object to $.code which manditorily takes two parameters, if that object happens to be a `DoubleCodeProxy`. But we can't tell whether it's a `DoubleCodeProxy` by type inference, because we didn't even know what a `DoubleCodeProxy` was at compile time. C++ gets around this problem by disallowing a declaration like `has Code $.code` -- All declarations must be fully specified. Perl is not going to do that. Unless I've mis-argued somewhere (I've been straining to get this message done before my next class starts, so my thinking may be sloppy), this example case requires the check to be put off until runtime. In that case, you certainly can't use inferred type information to make any semantic choices, and the best we can do is to use it as a compile-time error checker (in the cases where it's capable of doing so) and as an optimizer. Luke
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Larry Wall wrote: I think it's perfectly fine for the compiler to make use of whatever information it has. The trick is to never make any unwarranted assumptions, such as Nobody will ever add another class with an 'm' method. Er, isn't that not just the wrong way around? The point is to do the bookkeeping that an object is needed that does .meth() and that it is stored in $a, and to complain when that is not the case when it should be. The earlier the better. I don't understand why writing 'my X $a' needs at least a declaration of X, but then '$a.meth()' does not consider '.meth' as a bare method that needs a declaration in X? Polymorphism is about requiring that objects do compare and then sort a bunch of them using that particular role---not more not less. Or think of US Postal just transporting letters irrespective of them containing Anthrax or not, as long as they bear the right stamps! -- TSa (Thomas Sandlaß)
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, 2005-03-30 at 13:53, Luke Palmer wrote: class CodeProxy { has Code $.code is rw; sub call ($a) { $.code($a); } } This is valid Perl 6, and anyone who says otherwise (because of type signatures) is changing the Perl philosophy too much to be taken seriously. Now, tell me at compile time whether the call inside `call` is valid. It's valid because it's a function call on a code ref. In that case, the compiler has to hand your request off to the run-time to check the vtable of $.code. Clearly that's a special case. I may have missed context at the start, but are we worried about the special cases or the general case or the implications to the general case of the special cases? At runtime, you load in a new subclass of `CodeProxy`, `DoubleCodeProxy` (this programmer apparently doesn't know that we support variadic signatures :-) I think this is where you're stepping off the path I thought we were on, and I agree with the rest of your message FOR ONE CASE, but not all. Runtime loading can happen in many ways, but let's break them down into two camps: with and without a compile-time interface definition. In the first camp you have autoload. In the second camp you have low-level (e.g. Parrot) code that happens to have no interface definition (because it's pure PBC or because it came from another language) and evaluated strings. What I do not think should be allowed (and I may be contradicting Larry here, which I realize is taking my life in my hands ;) is violating the compile-time view of the static type tree. That is, you can load an object foo at run-time, without and interface definition, but it can't change the shape of the type tree or its existing interfaces. If it wants to do that, it has to provide an interface def (e.g. what an autoload module should be able to provide). Why? Because if you can do that, then this: my X $a; $a.m(1) = 1; ALWAYS has to work because you might have replaced X at run-time with a class that has a method m(int) is rw(), and the compiler must silently (perhaps with an optional warning) permit it. Please think carefully about how dynamic you want Perl 6 to be Dynamic is good, but there's such a thing as too much of a good thing. -- Aaron Sherman [EMAIL PROTECTED] Senior Systems Engineer and Toolsmith It's the sound of a satellite saying, 'get me down!' -Shriekback
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, Mar 30, 2005 at 12:05:12PM +0200, Thomas Sandlaß wrote: : If I understand you correctly the use statement is more like a : linker/loader directive than a compile time interface include? That is up to the module being used. use is a linker, but it's only required to link enough information into the caller such that the caller can see the interface. Loading can happen later--though it typically happens on first use rather than first use. The point is there's no separate linker step. Everything is demand driven, and what gets linked in at compile time depends on what gets demanded at compile time. If something isn't demanded till run time, the compiler can't know it, unless you tell it in advance somehow, which presumes that *you* know it. And maybe you don't. And that is when late binding is ever so much handier than early. : BTW, is it foreseen to have a clear conceptual split between the : compiler and the loader? Or is that all blurred? Clear conceptual splits often hide false dichotomies. The split is rather blurry for Perl 5, and Perl 6 will only continue the trend. There are good uses for both early binding and late binding, and for various forms of binding in between--it's a continuum, and each module is allowed to draw the boundary wherever and however it likes. Birds naturally prefer early binding to late binding; worms will naturally disagree. Rolling stones gather no type constraints. Larry
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, 2005-03-30 at 14:29 -0500, Aaron Sherman wrote: What I do not think should be allowed (and I may be contradicting Larry here, which I realize is taking my life in my hands ;) is violating the compile-time view of the static type tree. That is, you can load an object foo at run-time, without and interface definition, but it can't change the shape of the type tree or its existing interfaces. If it wants to do that, it has to provide an interface def (e.g. what an autoload module should be able to provide). I disagree, *unless* you predeclare that you don't plan to change anything -- as an optimization hint. (Though if you write a module to do this as a policy, I won't hunt you down with my +2 club of Optimize for the Programmer, not the Compiler.) I certainly plan to continue to instrument code at runtime (and not just really slushy, partially slushy, and permafrost compile time). -- c
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, 2005-03-30 at 14:57, chromatic wrote: I certainly plan to continue to instrument code at runtime (and not just really slushy, partially slushy, and permafrost compile time). That's FINE, and no one should stop you! What I was referring to was only the items that an interface definition would be concerned with (that is, those things which would invalidate the compiler's assumptions). An example follows. Original code: class X { method m(int $i) { say Hello, world } } Valid string to eval: q{class X { method m(int $i) { die Goodbye, world } }} Invalid string to eval: q{class X { method m(int $i) is rw($string) { say $string } }} The latter changes the interface definition, and thus invalidates the compiler's assumptions, but you can instrument the code all you like, re-defining any darned thing you wish! If you allow the interface definition to change, you're not optimizing for the programmer. You're optimizing for the amount of time you spend in the debugger. Failing to eval early because code would have changed the interface (or type hierarchy) of your types will save thousands of programmers everywhere much debugging time. Like I said, if you allow run-time munging of the type interfaces, then you can't tell if this is valid or invalid: my X $a; $a.m(1); you have to allow it always, regardless of the definition of X. In fact, you can NEVER reject ANY method or function invocation based on signature, since it might change at run-time. Is that really what you want? -- Aaron Sherman [EMAIL PROTECTED] Senior Systems Engineer and Toolsmith It's the sound of a satellite saying, 'get me down!' -Shriekback
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, 2005-03-30 at 15:27 -0500, Aaron Sherman wrote: Like I said, if you allow run-time munging of the type interfaces, then you can't tell if this is valid or invalid: my X $a; $a.m(1); you have to allow it always, regardless of the definition of X. In fact, you can NEVER reject ANY method or function invocation based on signature, since it might change at run-time. Is that really what you want? I want the possibility to correct bad decisions of interfaces and signatures whenever possible in the most minimally intrusive way possible. I don't want to work around a module or class or function or method where someone tried to be helpful by saying Oh, this will absolutely never change, ever and the compiler helpfully froze that decision forever. Sometimes that means changing it outside the incorrect code. I don't trust any compiler to make every decision correctly, and in cases of ambiguity I believe that I can give it better hints than it can reason for itself if I need the extra speed or safely. A compiler that assumes incorrectly and disallows programmers to do useful things because its holds those assumptions as precious is wrong -- especially in cases where even the programmer can't tell if code is valid or invalid until the program actually runs. -- c
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Luke Palmer wrote: class CodeProxy { has Code $.code is rw; sub call ($a) { $.code($a); } } This is valid Perl 6, Hmm, a sub in a class? I guess that should be a method. OTOH a class is just a funny module, so might be OK. But that is the syntax realm. and anyone who says otherwise (because of type signatures) is changing the Perl philosophy too much to be taken seriously. Now, tell me at compile time whether the call inside `call` is valid. Ups, before we start talking past each other: I think a type system is just a tool that reminds you to your declarations. No declarations, no reminder, it's that simple. I would like the typing of $.code as Code to be necessary to apply the .() invocation operator on it. The rest is deferred to runtime if that is what you want. And I'm completly unsure how much parrot and/or perl revert back into compile state when you bring in new source code at runtime. Or how much load time activity is needed for a byte code file. The question if instances of DoubleCodeProxy are subtypes of instances of CodeProxy boils down to the question if ($) : ($, +$) with : beeing the subtype relation. Is that the right siglet syntax? Since named-only parameters are optional the relation holds. This subtype relation allows: my CodeProxy $cp = DoubleCodeProxy.new; # needs DoubleCodeProxy : CodeProxy $cp.code = sub ($x, +$y = unknown) { say x = $x, y = $y }; $cp.call( first, b = second ); # prints x = first, y = second $cp.call( one ); # prints x = one, y = unknown $t = $cp.code; $cp.code = sub () { say void }; # no problem, type is Code $cp.call( X ); # gives runtime error on closure in $.code $cp.code = $t; $cp.call(); # compile error: too few args $cp.call( 1, 2 ); # compile error: too many positional args $cp.blahh( 23 ); # compile error/warning: no such method declared method CodeProxy::blubber(: $z ) { ... } $cp.blubber( 42 ); # could die on ... at runtime if no .blubber autoloaded $cp.call( 1|2|3 ); # autothreads??? I leave that to Damian :) -- TSa (Thomas Sandla)
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
chromatic wrote: A compiler that assumes incorrectly and disallows programmers to do useful things because its holds those assumptions as precious is wrong -- especially in cases where even the programmer can't tell if code is valid or invalid until the program actually runs. Me neither. One should think of a type system like dependency declarations in a Makefile: you get out what you put in. Too few dependencies might result in incomplete rebuilds. Complete dependencies might remind you how convoluted your design is. And make doesn't manage circular dependencies :) -- TSa (Thomas Sandlaß)
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Aaron Sherman wrote: No, that was most of the point. foo did not declare a return type, and while my code was simplistic, we obviously cannot be certain what foo might return in the general case. Sorry that I've spoiled that. But I wonder if it's just in the examples here on the list or a general laxity to not specify a return type of subs and methods. I consider leaving it to the compiler to infer it bad style. BTW, what is the default return type? Just Void? Is an explicit return statement than a compile error? -- TSa (Thomas Sandlaß)
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Thomas Sandla writes: Aaron Sherman wrote: No, that was most of the point. foo did not declare a return type, and while my code was simplistic, we obviously cannot be certain what foo might return in the general case. Sorry that I've spoiled that. But I wonder if it's just in the examples here on the list or a general laxity to not specify a return type of subs and methods. It depends on the programmer. I'm sure that you and probably Aaron will always declare your return types. I'm quite sure that I will not except for when it effects a semantic that I want. Ultimately, it depends on how Perl 5-ish you want to program Perl 6 in this regard. I definitely enjoy Perl 5's late binding for the most part. Again, I usually only resort to early binding things (like type declarations and sub prototypes) when it changes the semantics in some way. Luke
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Thomas Sandla writes: Luke Palmer wrote: class CodeProxy { has Code $.code is rw; sub call ($a) { $.code($a); } } This is valid Perl 6, Hmm, a sub in a class? I guess that should be a method. OTOH a class is just a funny module, so might be OK. But that is the syntax realm. Hey, no pointing out errors when I'm arguing! :-) Yes, given a s/sub/method/ it is valid Perl 6. ;-). As for the rest of this message, see my coming reply to Aaron's message, which points out that we're beginning to talk past each other because the original context has been lost. Luke and anyone who says otherwise (because of type signatures) is changing the Perl philosophy too much to be taken seriously. Now, tell me at compile time whether the call inside `call` is valid. Ups, before we start talking past each other: I think a type system is just a tool that reminds you to your declarations. No declarations, no reminder, it's that simple. I would like the typing of $.code as Code to be necessary to apply the .() invocation operator on it. The rest is deferred to runtime if that is what you want. And I'm completly unsure how much parrot and/or perl revert back into compile state when you bring in new source code at runtime. Or how much load time activity is needed for a byte code file. The question if instances of DoubleCodeProxy are subtypes of instances of CodeProxy boils down to the question if ($) : ($, +$) with : beeing the subtype relation. Is that the right siglet syntax? Since named-only parameters are optional the relation holds. This subtype relation allows: my CodeProxy $cp = DoubleCodeProxy.new; # needs DoubleCodeProxy : CodeProxy $cp.code = sub ($x, +$y = unknown) { say x = $x, y = $y }; $cp.call( first, b = second ); # prints x = first, y = second $cp.call( one ); # prints x = one, y = unknown $t = $cp.code; $cp.code = sub () { say void }; # no problem, type is Code $cp.call( X ); # gives runtime error on closure in $.code $cp.code = $t; $cp.call(); # compile error: too few args $cp.call( 1, 2 ); # compile error: too many positional args $cp.blahh( 23 ); # compile error/warning: no such method declared method CodeProxy::blubber(: $z ) { ... } $cp.blubber( 42 ); # could die on ... at runtime if no .blubber autoloaded $cp.call( 1|2|3 ); # autothreads??? I leave that to Damian :) -- TSa (Thomas Sandla)
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Aaron Sherman writes: What I do not think should be allowed (and I may be contradicting Larry here, which I realize is taking my life in my hands ;) is violating the compile-time view of the static type tree. That sentence is getting pretty C++-derived-like, which Perl is hardly anymore. We have to reorganize your brain a bit. Let's pretend that we're in Smalltalk instead of Java (no offense or compliment to either--I'm just taking extremes). Types don't form a tree. /Classes/ form a dag, which is, for all intents and purposes, a tree. But types are something very different. There are three kinds of types: * Roles (types with behavior) * Subtypes (roles with value restriction) * Classes (roles with an implementation specification) In particular, subtypes can form very complex non-tree-like structures, and structures which are not determinable by the compiler in the general case (if they were, then we'd have Gdel's truth machine). But that's okay, because it all boils down to calling the subtype closures and having those determine the implications of the structure, bypassing the structure itself. Let's step back into Perl 5 for a moment and pretend that objects are just blessed hashes again. If every object has some metadata stuffed into that hash, then you could really factor all three of these types of types into the subtype category. Subtypes are something that you can't really do any static analysis on. That means that I can circumvent your static view rule by doing exactly that: putting metadata on objects and making every type a subtype. But because the compiler has every ability to do that for us, and might just be the way it does things, it seems like we've just run in a big circle: outlawing something possible, and then walking through a loophole to make it possible again. That is, you can load an object foo at run-time, without and interface definition, but it can't change the shape of the type tree or its existing interfaces. If it wants to do that, it has to provide an interface def (e.g. what an autoload module should be able to provide). Why? Because if you can do that, then this: my X $a; $a.m(1) = 1; ALWAYS has to work because you might have replaced X at run-time with a class that has a method m(int) is rw(), and the compiler must silently (perhaps with an optional warning) permit it. And if X were defined as `Any where { $_.can('m') }`, then could you still make that guarantee? You could say no, we can't so that would be an illegal code segment at compile time, then I ask that you consider if X were defined as `Any where { $_.can('m') $_.CLASS.m ~~ rw }` (testing whether it has an rw m method... barring syntax). You'd have to say no there, too, because there's no way to tell what that opaque codeblock is doing. Please think carefully about how dynamic you want Perl 6 to be Dynamic is good, but there's such a thing as too much of a good thing. We'd like Perl 6 to be as dynamic as Perl 5. Luke
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Aaron Sherman writes: On Wed, 2005-03-30 at 13:53, Luke Palmer wrote: class CodeProxy { has Code $.code is rw; sub call ($a) { $.code($a); } } This is valid Perl 6, and anyone who says otherwise (because of type signatures) is changing the Perl philosophy too much to be taken seriously. Now, tell me at compile time whether the call inside `call` is valid. It's valid because it's a function call on a code ref. In that case, the compiler has to hand your request off to the run-time to check the vtable of $.code. Clearly that's a special case. I may have missed context at the start, but are we worried about the special cases or the general case or the implications to the general case of the special cases? Okay, now we're starting to talk past each other. I /think/ Thomas orignially suggested that we use type inference to determine whether to lvalue cast an argument or not, which is what I got all worked up about. I'm saying that you can't determine that kind of thing in general at compile time. I'm all for an optional strong type system, as long as it remains optional and mixable (so static things and dynamic things can play nicely together, whether the module is static and the user dynamic or vice-versa). Luke
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Aaron Sherman writes: Please think carefully about how dynamic you want Perl 6 to be Dynamic is good, but there's such a thing as too much of a good thing. We'd like Perl 6 to be as dynamic as Perl 5. We'd think that is impossible. Perl 5 had full control of the run-time, Perl 6 does not. Like hell it doesn't. Parrot is designed to support Perl 5. Perl 6 can do all the fancy stuff that Perl 5 did. If the Perl 6 compiler runs in Parrot, then it can control Parrot as it compiles, and reap information from that as it compiles. Parrot can easily redefine stuff on the fly and eval code at runtime. I don't see what full control of the run-time Perl 5 has that Perl 6 won't (if you have something specific in mind, enlighten me please). What's more, Perl 6 introduces types, mmd, function signature overloading, operator overloading and a host of other features which, combined with the level of dynamism found in Perl 5 would seem to me to lead to a compiler which cannot assist the user in writing debuggable code. You keep mentioning this thing debuggable code and saying that adding dynamism impairs it. I'd say that Perl 5 is debuggable; I can certainly debug it. The kinds of modules that I work on introduce types and mmd, where Perl 5 already had operator overloading. I don't understand how adding dyanmism impairs debuggability[1]. The reason that types and MMD can be introduced into Perl 5 is because it's so dynamic. We, as language designers in 2005, can't possibly know what will be to us as MMD is to perl 5, but we want module writers to be able to implement it, whatever it is. Sorry I'm getting so worked up here It's just that in designing the next generation of a language that I cherish for its dynamism and freedom, I don't like the idea of restricting that in the interest of... whatever the interest is in (I can't actually tell with this argument). I think what Perl 6 can offer us over Perl 5 in terms of safety, on a very feature-removed level, is much more comprehensive compile information available to the program. We could easily leave out the static type system from Perl 6 (not that I actually want to do this), and a module that implements it would be a heck of a lot easier to write than a module that implements it in Perl 5. Perl 6 gives you so many levels of control: lexical syntax control, hooks for everything you can dream of, possibility of generating pure parrot code inline, continuations (which help in writing a debugger), that I can't fathom how this could less debuggable than Perl 5. If you want to see when something, anything at all, is happening, stick a debugger hook in there. The more static we make our language--the less dynamic we allow it to be--the more debugging power we're taking away from the programmer. The lose of making things dynamic is that the compiler can't make as many assumptions, but Perl 6 allows many ways to tell it when it can make assumptions. As chromatic said, the programmer usually knows when the compiler can make assumptions better than the compiler does anyway. Whew... Okay, how can I turn around my rant and make it say something productive? I probably can't tonight. Nice yelling at you. :-) Luke [1] It might in a traditional debugger, but we are free to write our debugger in the extremely dynamic Perl 6, running it right alongside our program with all of our introspection needs at hand. If our debugger isn't good enough, we have the tools to write a better one. And for people like me who don't use the perl debugger, but who prefer print statements and Data::Dumper diagnostics, more dynamism implies more debugging power, not less.
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
According to Luke Palmer: [Perl 5] had to construct lvalues out of all arguments (for which that made sense) because the sub might modify them. No, actually, that wasn't the reason. Perl 5 passes all values by implicit mutable reference because it's faster, not because it's better. I suspect Larry might have passed arguments by read-only reference in Perl 5 as well, had he found a way to make it fast. -- Chip Salzenberg- a.k.a. -[EMAIL PROTECTED] Open Source is not an excuse to write fun code then leave the actual work to others.
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
Luke Palmer wrote: Okay, now we're starting to talk past each other. I /think/ Thomas orignially suggested that we use type inference to determine whether to lvalue cast an argument or not, which is what I got all worked up about. Actually I was returning to the subject of co- or contravariance of parametric types but trying to avoid these terms. I gave an example how to get a Str into an Array of Int when you assume in general that Array of Int : Array of Any. Which is reasonable only for reading because the reader doesn't care of the type and Int is compatible with such a reading. For writing you need the reverse relation because the writer expects an array that accepts Ints and and Array of Any does this. For a read-write Array both cases must hold, thus only type equality is sound. So when the compiler knows about a 'is rw' trait on a parameter and the type of an array---and it does so the latest when the call is attempted, but that is not the compiler then---it should reject the call! I'm saying that you can't determine that kind of thing in general at compile time. Of course not, but the question is than just shifted to: do you want a runtime exception when sub foo( @a is rw ) is called with an Array of Int? If you answer no, than you take the consequence that this Array of Int might contain other things than Ints. That's all. There is no type inference per se in my argument. It just might help the compiler to gather the necessary type information to ask the above question at compile time. Larry takes the point of view that the Str goes in but the Array knows that it should be an Int and nicely converts that for you. And actually Any might just be a glb (greatest upper bound) of Int and Str, written Int|Str in Perl6, so the type checker knows that *this* case is OK. But it will complain if Any isn't a glb of SomeOtherType and you call foo with Array of SomeOtherType. Note that Int|Str : Str Str : Int|Str Int|Str : Int Int : Int|Str holds. Given an even more complex Any type that encompasses the general purpose types of Perl6---namely Str, Int, Num, Bool and Refs thereof--- the lazy Perl6 programmer gets what Perl5 did all the time. This is what is called Render the Illusion of Simplicity. This illusion fades when you get the compile time warning no glb for Any and SomeOtherType and you have to go figure what to do about it ;) But once again these might hit a strong programmer and the not so strong ones a kept in the illusion: look I just use SomeOtherType and it works. I'm all for an optional strong type system, as long as it remains optional and mixable (so static things and dynamic things can play nicely together, whether the module is static and the user dynamic or vice-versa). Optional in what sense? -- TSa (Thomas Sandla)
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, 2005-03-30 at 17:09, Luke Palmer wrote: Aaron Sherman writes: What I do not think should be allowed (and I may be contradicting Larry here, which I realize is taking my life in my hands ;) is violating the compile-time view of the static type tree. That sentence is getting pretty C++-derived-like, I think you mis-read what I wrote, and it was in a context that flowed from previous messages. I was referring to the part of the type tree (multi-root, directed, acyclical graph) which I had deemed to be static for the sake of handling interfaces sanely at compile-time. Hence the scary-quotes on static, as we were not in agreement on that point. Please think carefully about how dynamic you want Perl 6 to be Dynamic is good, but there's such a thing as too much of a good thing. We'd like Perl 6 to be as dynamic as Perl 5. We'd think that is impossible. Perl 5 had full control of the run-time, Perl 6 does not. Even Ponie cannot truly be as dynamic as vanilla Perl 5. What's more, Perl 6 introduces types, mmd, function signature overloading, operator overloading and a host of other features which, combined with the level of dynamism found in Perl 5 would seem to me to lead to a compiler which cannot assist the user in writing debuggable code. I like Perl 5, but Perl 6 is not Perl 5... we have to be willing to accept that there are trade-offs for the features we've added. One possible trade-off is increased difficulty in debugging code. One possible trade-off is slightly less dynamic code. Your other message: On Wed, 2005-03-30 at 17:15, Luke Palmer wrote: aron Sherman writes: It's valid because it's a function call on a code ref. In that case, the compiler has to hand your request off to the run-time to check the vtable of $.code. Clearly that's a special case. I may have missed context at the start, but are we worried about the special cases or the general case or the implications to the general case of the special cases? Okay, now we're starting to talk past each other. I /think/ Thomas orignially suggested that we use type inference to determine whether to lvalue cast an argument or not, which is what I got all worked up about. I'm saying that you can't determine that kind of thing in general at compile time. I'm all for an optional strong type system, as long as it remains optional and mixable (so static things and dynamic things can play nicely together, whether the module is static and the user dynamic or vice-versa). Ok, so let me start from that point and ask a question: When the Perl 6 compiler sees: my X $a; $a.m(1); What should it do? Options: * Accept the method call regardless of the definition of X * Accept the method call if it matches the signature from X * Accept the method call if {magic($*INTERP)} Not to be pushy or anything, but please pick one and if it's the last, we can start to have a conversation about what that line-noise at the end actually does. ;-) -- Aaron Sherman [EMAIL PROTECTED] Senior Systems Engineer and Toolsmith It's the sound of a satellite saying, 'get me down!' -Shriekback
Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?
On Wed, 2005-03-30 at 18:35 -0500, Aaron Sherman wrote: When the Perl 6 compiler sees: my X $a; $a.m(1); What should it do? Options: * Accept the method call regardless of the definition of X * Accept the method call if it matches the signature from X * Accept the method call if {magic($*INTERP)} That's a fair question, but I think you're leaving out several important pieces of information: * Where does $a come from? (As far as I see, it's just an uninteresting undef here, but I don't know if that's the point of the code.) * At what point in the program are you asking what the compiler sees? * Where's the definition of X in relation to this code? * What pragmas are in effect here? * What other code may have altered the type definition of X or undef? I don't think anyone can answer your question well without assuming some answers to my questions. -- c