Re: A6: Strict signature checking - was: Complex Parameter Types
-- On Fri, 14 Mar 2003 10:08:15 Larry Wall wrote: >On Thu, Mar 13, 2003 at 07:36:00PM -0800, Brent Dax wrote: >: I think that there should be two types of arg typing[1]: 'strict' and >: 'loose'. Strict arg typing doesn't coerce, except to turn subclasses >: into superclasses; loose arg typing, on the other hand, coerces whenever >: possible. The mechanism for choosing between strict and loose arg >: typing should be under the caller's control, not the callee's. (The >: callee decides what types they want, and the caller decides how to >: create those types. This seems consistent with Perl's philosophy of >: being flexible and making B&D optional.) > >Precisely. The parameter types are completely invariant for the >callee. They are optionally invariant for the caller depending on some >kind of stricture. But I darn well want the naive user to be able to >pass a Scalar to an Int parameter and have it DWTM without them knowing >a blessed thing about these mysterious entities called "classes". > >We've got to keep the entry ramp low, or Perl is no longer Perl. > >The real question is whether this particular stricture is part of the >default "use strict" that classes and modules assume. There are >decent arguments on both sides of that one, but just to mollify Damian >I'm inclined to come down on the strict side for that. > I'll put my vote down on strictness (as in "complain about mismatch as soon as possible") by default. But just as prototypes are ignored when we prepend & in Perl 5 can't some similar frobobnitz say "But on this here call, wait till runtime and coerce if needed"? After all, it's not the kind of thing a callee should dictate, but the caller. >This week. :-) I'm easy. -Erik > >Larry > Get 25MB of email storage with Lycos Mail Plus! Sign up today -- http://www.mail.lycos.com/brandPage.shtml?pageId=plus
Re: A6: Strict signature checking - was: Complex Parameter Types
On Thu, Mar 13, 2003 at 07:36:00PM -0800, Brent Dax wrote: : I think that there should be two types of arg typing[1]: 'strict' and : 'loose'. Strict arg typing doesn't coerce, except to turn subclasses : into superclasses; loose arg typing, on the other hand, coerces whenever : possible. The mechanism for choosing between strict and loose arg : typing should be under the caller's control, not the callee's. (The : callee decides what types they want, and the caller decides how to : create those types. This seems consistent with Perl's philosophy of : being flexible and making B&D optional.) Precisely. The parameter types are completely invariant for the callee. They are optionally invariant for the caller depending on some kind of stricture. But I darn well want the naive user to be able to pass a Scalar to an Int parameter and have it DWTM without them knowing a blessed thing about these mysterious entities called "classes". We've got to keep the entry ramp low, or Perl is no longer Perl. The real question is whether this particular stricture is part of the default "use strict" that classes and modules assume. There are decent arguments on both sides of that one, but just to mollify Damian I'm inclined to come down on the strict side for that. This week. :-) Larry
Re: Huffman coding (Was: Re: A6: Strict signature checking - was: Complex Parameter Types)
On Thu, Mar 13, 2003 at 10:52:04PM +0100, Anton Berezin wrote: : On Thu, Mar 13, 2003 at 10:21:25PM +1100, Damian Conway wrote: : : > By distinguishing a parameter that *requires* a particular type, from : > a parameter that *ensures* a particular type (by coercion if : > necessary). I've suggested that using C semantics should : > indicate "make whatever I'm actually given into one of these, if you : > can", whereas reference semantics say "this must already be one of : > these" (by their very nature, since an aliased parameter *is* the : > argument). : : It looks like a lot of people is going to use "is copy" a lot. Correct : me if I am wrong, but I see the default "is constant" trait largely as a : speed optimization. Would not it be more correct from the point of view : of good Huffman coding, that "is copy" is made the default, and let the : module authors and large project implementors to bother with "is : constant" when they deem it necessary? After all, this will be a small : added burden for folks who go the "type and trait everything" route. An : extra bonus of making "is copy" the default would be the ability to : modify a parameter locally (Huffman coding again here for short program : writers). Well, at minimum there could certainly be a "use sig copy" pragma or some such. But I don't think "is copy" will be used all that much if we set up "is constant" with the right semantics in the first place, which is that it can do a copy of basic types if it feels like it. It's only "is rw" or "is ref" that really require reference semantics, and then we're talking proxies if we want any coercion. Larry
Huffman coding (Was: Re: A6: Strict signature checking - was: Complex Parameter Types)
On Thu, Mar 13, 2003 at 10:21:25PM +1100, Damian Conway wrote: > By distinguishing a parameter that *requires* a particular type, from > a parameter that *ensures* a particular type (by coercion if > necessary). I've suggested that using C semantics should > indicate "make whatever I'm actually given into one of these, if you > can", whereas reference semantics say "this must already be one of > these" (by their very nature, since an aliased parameter *is* the > argument). It looks like a lot of people is going to use "is copy" a lot. Correct me if I am wrong, but I see the default "is constant" trait largely as a speed optimization. Would not it be more correct from the point of view of good Huffman coding, that "is copy" is made the default, and let the module authors and large project implementors to bother with "is constant" when they deem it necessary? After all, this will be a small added burden for folks who go the "type and trait everything" route. An extra bonus of making "is copy" the default would be the ability to modify a parameter locally (Huffman coding again here for short program writers). =Anton.
Re: A6: Strict signature checking - was: Complex Parameter Types
Damian Conway wrote: b) The argument passed here must be something that will definitely not cause the program to crash and burn, and we'll verify that at compile-time. I'm arguing that the former is well-nigh useless, and that the latter is what large systems developers and optimizer writers have been begging for. Besides which, the latter gives you the former. If you don't care about compile-time type checking, declare the *parameter* as Scalar, and let it accept anything. Module writers should always write their code to high standards of safety. Client code, OTOH, should be able to be more sloppy -- especially for one-liners. But I agree that (b) should be the goal: I agree run-time type checking is "well-nigh useless". But, the definition of compile-time checking can be broad. Firstly, we should distinguish between things that are explicitly typed, and things that are not. If a user does not specify the type of a value, then the compiler should make a best-effort attempt to infer the type from what it does know. e.g. sub foo () returns Int { 6 } sub bar (Int $a) { print $a+1 } ... my $a = foo; bar($a); In this case, the user has chosen not to give an explicit type to $a, but a trivial dataflow analysis will determine that type. The default mode (in non-strict contexts) should be to infer the type. I just re-read A1, the RFC:16 discussion. Larry seems to say that, outside of class definitions, strictness will not be the default. Such code is never very large (well, OK, I've seen some bad scripts: but hard cases make bad law), so we can afford to let the compiler do some work to do all the necessary inference ... and even insert coercion code if necessary. If performance becomes an issue, then the script writer will clean up the code. A quick list of the possible cases -- the compiler might determine (via type inference) that a binding is: definitely not safe: can't even be coerced -- always an error definitely safe, no corercion needed -- always OK definitely safe if we corerce -- OK in non-strict contexts undecidable -- error in strict contexts, else compile-time warning Which brings us back to the question of what is coercable. I'd say that we should only permit implicit coercion where a user has not used explicit typing; but there should be a simple prefix operator to enable coercion of typed things. Perhaps the "splat" operator could serve here: my Str $a = <>; my Int $b = $a;# Error -- $a is explicitly typed as Str my Int $c = $a.num # OK -- explicit corcion my Int $d = *$a; # OK -- splat permits implicit coercion Dave. -- http://dave.whipp.name
RE: A6: Strict signature checking - was: Complex Parameter Types
Damian Conway: # a) The argument passed here must be something that # could conceivably # not cause the program to crash and burn, and # we'll verify that at # run-time if necessary. # # or: # # b) The argument passed here must be something that will # definitely # not cause the program to crash and burn, and # we'll verify that at # compile-time. # # I'm arguing that the former is well-nigh useless, and that # the latter is what # large systems developers and optimizer writers have been # begging for. Besides # which, the latter gives you the former. If you don't care # about compile-time # type checking, declare the *parameter* as Scalar, and let it # accept anything. IMO, the semantics should be something like this: Assume F is the type of the formal parameter and A is the type of the actual parameter. If A isa F, we're fine. If F isa A, defer type checking to runtime. Else, pitch a fit. Since the default type is Object and any type isa Object, untyped formal parameters are "checked" at compile time and untyped actual parameters are checked at runtime. That's the semantics for strict typing, anyway... # But if type-specialized parameters are allowed to take # *anything*, then # they're nigh on worthless, except as a (third) coercion # mechanism (in addition # to explicit int($x), +$x, ~$x; and implicit contextual coercions). What's wrong with that? It gives us a way to ensure that we have a suitable object without having to remember to check ourselves. I think that there should be two types of arg typing[1]: 'strict' and 'loose'. Strict arg typing doesn't coerce, except to turn subclasses into superclasses; loose arg typing, on the other hand, coerces whenever possible. The mechanism for choosing between strict and loose arg typing should be under the caller's control, not the callee's. (The callee decides what types they want, and the caller decides how to create those types. This seems consistent with Perl's philosophy of being flexible and making B&D optional.) Strict arg typing should be under the control of the 'strict' pragma, and should be in strict's default export list. This would mean that the B&D would be off by default but easy to turn on. [1] Perhaps this should be generalized to strict and loose coercion; I'm not really sure yet. (Under strict coercion, adding an Int and a Str would be an error, instead of coercing the Str into an Int.) --Brent Dax <[EMAIL PROTECTED]> @roles=map {"Parrot $_"} qw(embedding regexen Configure) >How do you "test" this 'God' to "prove" it is who it says it is? "If you're God, you know exactly what it would take to convince me. Do that." --Marc Fleury on alt.atheism
Re: A6: Strict signature checking - was: Complex Parameter Types
Larry Wall wrote: On Thu, Mar 13, 2003 at 10:21:25PM +1100, Damian Conway wrote: : But if I say: : : sub foo(@a is Array of Int) {...} : ... : foo(@x); : : then I'm saying: "within &foo, @a is just another name for @x". So they are : (temporarily) the same thing. That can only (be allowed to) happen if the : actual type of @x satisfies all the requirements of the declared type of @a. Which condition holds if @x is an array of Scalar! Because a Scalar polymorphically supports the Int, Num, Str, and Ref interfaces. Err, sorry, no it doesn't. Either Scalar is the superclass of those four, in which case a Scalar isn't sufficient to satisfy the requirements of an Int; or Scalar is a disjunction of those four, in which case it's still not guaranteed that whatever the Scalar is holding will satisfy the requirements of an Int. As I said before it comes down to whether a parameter type is a specification that: a) The argument passed here must be something that could conceivably not cause the program to crash and burn, and we'll verify that at run-time if necessary. or: b) The argument passed here must be something that will definitely not cause the program to crash and burn, and we'll verify that at compile-time. I'm arguing that the former is well-nigh useless, and that the latter is what large systems developers and optimizer writers have been begging for. Besides which, the latter gives you the former. If you don't care about compile-time type checking, declare the *parameter* as Scalar, and let it accept anything. But if type-specialized parameters are allowed to take *anything*, then they're nigh on worthless, except as a (third) coercion mechanism (in addition to explicit int($x), +$x, ~$x; and implicit contextual coercions). Damian
Re: A6: Strict signature checking - was: Complex Parameter Types
> I don't see a problem. Scalar == Int|Num|Str|Ref, so > Scalar.isa("Int"). Scalar.isa("Int") && Int.isa("Scalar") __ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com
Re: A6: Strict signature checking - was: Complex Parameter Types
On Thu, Mar 13, 2003 at 11:31:30AM -0800, Austin Hastings wrote: : "Everyone Knows" that an Int is a Scalar, and therefore a sub that has : a Scalar parameter can safely be passed an Int. This is normal. : : What I want is the ability to do the opposite: Silence the warning that : occurs when I pass a Scalar to a sub expecting an Int. I don't see a problem. Scalar == Int|Num|Str|Ref, so Scalar.isa("Int"). Larry
Re: A6: Strict signature checking - was: Complex Parameter Types
--- Damian Conway <[EMAIL PROTECTED]> wrote: > Austin Hastings wrote: > > > But what's the vision for p6? > > > > My expectation is that the type-checking stuff will be heavily used > > for: > > > > 1- Large scale projects. > > > > 2- CPAN modules. > > > > I expect that the folks who want to do one-liners will still want > to be > > able to say C > > > > So the "strict" bits have to be forgiving of the "non-strict" > callers. > > To me that's a contradiction in terms. Strictness can't be > "forgiving". At the risk of stating the obvious, that's the > whole point of strictness: to be strict. Of course strictness can be forgiving. That's why the "Insert Coin" slots on soda machines have a beveled slot -- they expect the user to be a little uncoordinated, but once inside it's going to be all by-the-book. > > What we're suggesting is that if you want to be non-strict, don't use > types. After all, they're optional. > > "But," (I hear you say), "I may not have a choice! If the Cruel > Module Author chose to use types, then I'm forced to do so too. > That's not Lazy." > > And you're right. The module author gets to determine the interface > of their module. And if they determine that that interface will > provide type-safety, then you have to respect that. Just as if > they decided that it would have an OO interface, or would set > PRE and POST conditions on calls, or would only take named > arguments. > > Because the author of the module is *relying* on that interface to > ensure the correctness of their code; to prevent inappropriate data > being passed to their subroutines. Typing is yet another way in > which they can relax, knowing that the wrong type of data will be > headed off at the (compiler) pass. > But this isn't really true, is it? When you come down to cases, you can construct a case wherein the wrong type of data gets coerced into the "round hole" in every language. sub foo($a is Int); my $line = "Hello, World"; my Int $i ::= $line; foo($i); # Compiles okay, doesn't work. So the module author is relying on the module user to make sure that the intent of the interface is satisfied. The type bits are there to help them communicate, and the let the compiler jab the willing user in the ribs when he goofs. > > To me, the way around this is NOT to force interface contracts down > to > > some lowest common denominator, but rather to document what is > > expected, and then allow the developer to accept responsibility for > > stepping on his crank. > > Yep. And the way for the client of some module to accept that > responsibility > is to put in an explicit conversion. This statement gives me the heebie-jeebies. Perl5 ==[*]= Java/C extern long factorial(int); char buf [BUFMAX]; while (gets(buf)) { if (want_fact()) { int i; i = atoi(buf); printf("%ld", factorial(i)); } } Versus: use Math qw(factorial(Int $)); my $line; while ($line = <>) { if (want_fact()) { my Int $i = $line; # Or do I need C ? print factorial($i); } } Say it ain't so, Joe! > > If you say, "Give me an Array of Hash of (String => Array of > BigNum)" > > and I say, "Here's an Array of Scalars. They're OK, I promise" and > > things "gang agley", it's my fault. I can deal with that. > > But large projects -- where typing will be most important -- *can't* > deal with that. That's the point of typing: to specify and enforce > interface contracts. At compile-time if at all possible. The large project folks will have the standard C at the top of their files, so no problem. > > But at the bottom, the C++ problem is a problem of its own making > > -- people want coercion. Just like me. I want coercion. I want > > the ability to take advantage of the really nifty, carefully > > written code available from dedicated, rigorous hackers like > > this Conway fellow. But I want to do it as a slap-dash hack > > with no thought given to type stuff. How? > By distinguishing a parameter that *requires* a particular type, > from a parameter that *ensures* a particular type (by coercion > if necessary). I've suggested that using C semantics > should indicate "make whatever I'm actually given into one of > these, if you can", whereas reference semantics say "this must > already be one of these" (by their very nature, since an > aliased parameter *is* the argument). Hmm. Granted that references must be basically correct when you use them, there's really two cases here: 1- I give you something that's just wrong, but convertible. Example: Array of int/Int. In this case, I'm not sure that 2- I give you something that I know is right, but I don't have all the type fluff attached. Example: Int/Scalar. In this case, the data is essentially right, and I need a way to tell the typechecker: Hey, I'm right! Shaddap. Consider the case of an XML datastore: When I C, it's going to give me a {Hash of String => Array of Scalar} or maybe {
Re: A6: Strict signature checking - was: Complex Parameter Types
On Thu, Mar 13, 2003 at 06:28:00PM +0100, Angel Faus wrote: : : Damian Conway wrote: : > But large projects -- where typing will be most important -- : > *can't* deal with that. That's the point of typing: to specify and : > enforce interface contracts. At compile-time if at all possible. : : One quick question about this. If I write: : : sub foo (Bar $f) {..} : : my $x = some_function_that_returns_bar(); : foo($x); : : Will this fail because the compiler _requires_ that the type be known : at compile-time, or will it work because it will the delay the : type-checking until run-time? In the absence of a pragma to the contrary, type checking will be done at run time when the type can't be determined at compile time. But surely the S&M&B&D types will create a pragma that requires the type to be known at compile time. larry
Re: A6: Strict signature checking - was: Complex Parameter Types
On Thu, Mar 13, 2003 at 10:21:25PM +1100, Damian Conway wrote: : But if I say: : : sub foo(@a is Array of Int) {...} : ... : foo(@x); : : then I'm saying: "within &foo, @a is just another name for @x". So they are : (temporarily) the same thing. That can only (be allowed to) happen if the : actual type of @x satisfies all the requirements of the declared type of @a. Which condition holds if @x is an array of Scalar! Because a Scalar polymorphically supports the Int, Num, Str, and Ref interfaces. Larry
Re: A6: Strict signature checking - was: Complex Parameter Types
Damian Conway wrote: > But large projects -- where typing will be most important -- > *can't* deal with that. That's the point of typing: to specify and > enforce interface contracts. At compile-time if at all possible. One quick question about this. If I write: sub foo (Bar $f) {..} my $x = some_function_that_returns_bar(); foo($x); Will this fail because the compiler _requires_ that the type be known at compile-time, or will it work because it will the delay the type-checking until run-time? -angel
Re: A6: Strict signature checking - was: Complex Parameter Types
On Thu, Mar 13, 2003 at 10:21:25PM +1100, Damian Conway wrote: : But what we can't allow is a reference parameter to coerce its argument. : For example: : : sub loggedincr (Int $i is rw) { : print $log: "Incremented $i.id()\n"; : $i++ unless $i.constant; : } : : # and later... : : int $x = 7; : loggedincr($x); : : The $i parameter *can't* be bound to $x, because $x doesn't have the : necessary features to be an Int (e.g. it doesn't have the capacity to : respond to method or property lookups). But we've already said that an int will try to behave like an Int as much as it can, including calling methods on it as if it were an Int. The "int" is just a hint that you'd like compact storage and fast loops And it's probably a stronger hint on an array than on a solitary scalar. : Even wrapping $x in a temporary Int : wouldn't help, since it would render the logging of an .id meaningless. The : whole point of having types is to catch this kind of problem at : compile-time. A proxy Int could certainly calculate its id from the location of the actual int, if it came down to it, so that different proxy Ints have the same id. And if the outer scope establishes the proxy Int at the same time as it allocates the int, there will only be one of it anyway. And we'd only need to create the proxy if we know we might be passing it to an C parameter somewhere. C parameters on Int, Num, Str and Ref should be free to implement themselves with copy semantics anyway. If you want to take a ref to a parameter, you'll have to declare it C or C, I suspect. Things get dicier with viewing an Array of int as an Array of Int, but again, the Array of Int could know that it's a proxy for an Array of int. It's just an object with an interface, after all. And it could generate smart proxy references as the need arises, in cooperation with the Array of int as necessary to avoid .id bifurcation. I am not suggesting that we open up the barn doors to allow anything to be coerced to anything else willy nilly. I am suggesting that we maintain the easy integer <-> number <-> string semantics of Perl 5 when the rest of the type system allows it. Data structures would still have to be conformant--I'm talking about the leaf semantics, not the tree semantics. Larry
Re: A6: Strict signature checking - was: Complex Parameter Types
Damian Conway <[EMAIL PROTECTED]> writes: > Austin Hastings wrote: > >> But what's the vision for p6? My expectation is that the >> type-checking stuff will be heavily used >> for: >> 1- Large scale projects. >> 2- CPAN modules. >> I expect that the folks who want to do one-liners will still want to >> be >> able to say C >> So the "strict" bits have to be forgiving of the "non-strict" >> callers. > > To me that's a contradiction in terms. Strictness can't be "forgiving". > At the risk of stating the obvious, that's the whole point of strictness: > to be strict. > > What we're suggesting is that if you want to be non-strict, don't use types. > After all, they're optional. > > "But," (I hear you say), "I may not have a choice! If the Cruel Module > Author chose to use types, then I'm forced to do so too. That's not > Lazy." > > And you're right. The module author gets to determine the interface of > their module. And if they determine that that interface will provide > type-safety, then you have to respect that. Just as if they decided > that it would have an OO interface, or would set PRE and POST > conditions on calls, or would only take named arguments. > > Because the author of the module is *relying* on that interface to > ensure the correctness of their code; to prevent inappropriate data > being passed to their subroutines. Typing is yet another way in which > they can relax, knowing that the wrong type of data will be headed off > at the (compiler) pass. > > >> To me, the way around this is NOT to force interface contracts down to >> some lowest common denominator, but rather to document what is >> expected, and then allow the developer to accept responsibility for >> stepping on his crank. > > Yep. And the way for the client of some module to accept that > responsibility is to put in an explicit conversion. Of course, a module author could always layer on a 'non strict' version of the interface that did the type conversions itself before passing them into the more stringent internals. >> But at the bottom, the C++ problem is a problem of its own making -- >> people want coercion. Just like me. I want coercion. I want the ability >> to take advantage of the really nifty, carefully written code available >> from dedicated, rigorous hackers like this Conway fellow. But I want to >> do it as a slap-dash hack with no thought given to type stuff. How? > > By distinguishing a parameter that *requires* a particular type, from > a parameter that *ensures* a particular type (by coercion if > necessary). I've suggested that using C semantics should > indicate "make whatever I'm actually given into one of these, if you > can", whereas reference semantics say "this must already be one of > these" (by their very nature, since an aliased parameter *is* the > argument). > > Alternatively, one might imagine a separate and explicit trait that > specifies that a parameter is allowed to coerce its corresponding > argument to it's own type. But this would be better. And implementable relatively easily as a macro if it weren't availabe in the core I would have thought. Hm... it might be interesting/useful to implement a set of macros to allow developers to define and export their own traits: trait foo (...) is ParameterTrait { COMPILATION_CHECK {...} RUNTIME_CHECK {...} } (There's almost certainly a better syntax available mind). -- Piers
Re: A6: Strict signature checking - was: Complex Parameter Types
Austin Hastings wrote: But what's the vision for p6? My expectation is that the type-checking stuff will be heavily used for: 1- Large scale projects. 2- CPAN modules. I expect that the folks who want to do one-liners will still want to be able to say C So the "strict" bits have to be forgiving of the "non-strict" callers. To me that's a contradiction in terms. Strictness can't be "forgiving". At the risk of stating the obvious, that's the whole point of strictness: to be strict. What we're suggesting is that if you want to be non-strict, don't use types. After all, they're optional. "But," (I hear you say), "I may not have a choice! If the Cruel Module Author chose to use types, then I'm forced to do so too. That's not Lazy." And you're right. The module author gets to determine the interface of their module. And if they determine that that interface will provide type-safety, then you have to respect that. Just as if they decided that it would have an OO interface, or would set PRE and POST conditions on calls, or would only take named arguments. Because the author of the module is *relying* on that interface to ensure the correctness of their code; to prevent inappropriate data being passed to their subroutines. Typing is yet another way in which they can relax, knowing that the wrong type of data will be headed off at the (compiler) pass. To me, the way around this is NOT to force interface contracts down to some lowest common denominator, but rather to document what is expected, and then allow the developer to accept responsibility for stepping on his crank. Yep. And the way for the client of some module to accept that responsibility is to put in an explicit conversion. If you say, "Give me an Array of Hash of (String => Array of BigNum)" and I say, "Here's an Array of Scalars. They're OK, I promise" and things "gang agley", it's my fault. I can deal with that. But large projects -- where typing will be most important -- *can't* deal with that. That's the point of typing: to specify and enforce interface contracts. At compile-time if at all possible. But at the bottom, the C++ problem is a problem of its own making -- people want coercion. Just like me. I want coercion. I want the ability to take advantage of the really nifty, carefully written code available from dedicated, rigorous hackers like this Conway fellow. But I want to do it as a slap-dash hack with no thought given to type stuff. How? By distinguishing a parameter that *requires* a particular type, from a parameter that *ensures* a particular type (by coercion if necessary). I've suggested that using C semantics should indicate "make whatever I'm actually given into one of these, if you can", whereas reference semantics say "this must already be one of these" (by their very nature, since an aliased parameter *is* the argument). Alternatively, one might imagine a separate and explicit trait that specifies that a parameter is allowed to coerce its corresponding argument to it's own type. But what we can't allow is a reference parameter to coerce its argument. For example: sub loggedincr (Int $i is rw) { print $log: "Incremented $i.id()\n"; $i++ unless $i.constant; } # and later... int $x = 7; loggedincr($x); The $i parameter *can't* be bound to $x, because $x doesn't have the necessary features to be an Int (e.g. it doesn't have the capacity to respond to method or property lookups). Even wrapping $x in a temporary Int wouldn't help, since it would render the logging of an .id meaningless. The whole point of having types is to catch this kind of problem at compile-time. My own problem with this wrapping notion is that I consider it incompatible with the reference semantics of normal Perl 6 parameters. Specifically, I *don't* want the aliasing mechanism to be capable of implicit type coercions. Maybe you could expand on that a little? See above. On the other hand, I have *no* problem with this: sub foo(@a is Array of Int is copy) {...} ^^^ doing the kind of coercive wrapping you're suggesting. What's the difference? (Aside from the obvious, that is...) Suppose I call: foo(@x); The difference is that @a above is a lexically scoped variable into which the contents of the corresponding argument (@x) are copied (i.e. assigned). Now it's perfectly possible that the contents of @x can be assigned into @a, even if the argument and the parameter are of wildly different types. But if I say: sub foo(@a is Array of Int) {...} ... foo(@x); then I'm saying: "within &foo, @a is just another name for @x". So they are (temporarily) the same thing. That can only (be allowed to) happen if the actual type of @x satisfies all the requirements of the declared type of @a. Damian
Re: A6: Strict signature checking - was: Complex Parameter Types
Austin Hastings wrote: But what's the vision for p6? My expectation is that the type-checking stuff will be heavily used for: 1- Large scale projects. 2- CPAN modules. 3- speed When you are not on perl one liners, but maybe some inner tight loops of some algorithm or whatever, where speed does matter, we (the low level PASM folks :) have achieved a speed increase of x100 and more, on a now of course hand crafted assembler routine compared to $HLInterpLang. These are the margins that a good optimizer will be able to hopefully reach, which are for plain integers near or beyond gcc -O3 performance with the JIT runtime. When the flexibility of all the lanugage comes in, this is of course not possible, and the more of those features (caller, %MY, leave, exceptions) are used, the less, optimizations can be used. But for "what is the type-checking stuff": for sure for better diagnostic messages and for performance, when needed. =Austin leo
Re: A6: Strict signature checking - was: Complex Parameter Types
--- Damian Conway <[EMAIL PROTECTED]> wrote: > Austin Hastings wrote: > > > In this case, I rather like the idea of being able to say > > > >sub foo(@a is Array of Int) {...} > > > >my @input = read_a_bunch_o_data(); > >foo(@input); > > > > > > Where the compiler will automatically "wrap" the @input array in a > > make-it-an-int converter. This, to me, is DWIM. > > But to many others it's not DWIS ("Do What I Said"). To them, types > are about compile-time checking of constraints on the run-time > compatibility of data. No problem so far. And when they run -w, perl should tell them "subroutine call not provably (in)correct at line 3" > So they would argue that declaring C like that implies that any > argument passed to C ought to guarantee that it already > contains Ints, rather than specifying a (possibly unsuccessful) > run-time coercion to ensure that condition. But what's the vision for p6? My expectation is that the type-checking stuff will be heavily used for: 1- Large scale projects. 2- CPAN modules. I expect that the folks who want to do one-liners will still want to be able to say C So the "strict" bits have to be forgiving of the "non-strict" callers. To me, the way around this is NOT to force interface contracts down to some lowest common denominator, but rather to document what is expected, and then allow the developer to accept responsibility for stepping on his crank. If you say, "Give me an Array of Hash of (String => Array of BigNum)" and I say, "Here's an Array of Scalars. They're OK, I promise" and things "gang agley", it's my fault. I can deal with that. And if you have said "Array of Hash of (String => Array of BigNum)" then I can theoretically give you a typed array and let the compiler check it. However, if you have been forced to say "Give me an Array" in the interests of avoiding typewhacking one-liners, then (1) you've got to check and throw the exception, slowing up your code; and (2) there's no option for me if I *DO* want to conform to the rigid rules. > And many would argue that implicit coercions on typed > parameters is one of the major *problems* with C++. Of course it is. And why is that? Because they've GOT strongly typed parameters, but sometimes the data doesn't match the signature. This has been exacerbated by differentiating const from non-const types, and by that foul fire-hose of code known as the template mechanism. But at the bottom, the C++ problem is a problem of its own making -- people want coercion. Just like me. I want coercion. I want the ability to take advantage of the really nifty, carefully written code available from dedicated, rigorous hackers like this Conway fellow. But I want to do it as a slap-dash hack with no thought given to type stuff. How? > > My own problem with this wrapping notion is that I consider it > incompatible with the reference semantics of normal Perl 6 > parameters. Specifically, I *don't* want the aliasing mechanism to > be capable of implicit type coercions. Maybe you could expand on that a little? > On the other hand, I have *no* problem with this: > > sub foo(@a is Array of Int is copy) {...} > ^^^ > doing the kind of coercive wrapping you're suggesting. What's the difference? (Aside from the obvious, that is...) > > I think there may be a library of wrapper "helper-functions" used > by > > both the compiler and module-writers. Things that do coercive > behavior > > rather than try-but-maybe-fail behavior. > > Quite possibly. Though wrapping is probably too "heavy" a mechanism > for type > coercions. When I imagine type coercions in Perl 6, I imagine them as > compile-time detectable, and explicit. Ahh, but if you don't want heavy, just comply with the expected type, or do your own coercion. I certainly imagine them as compile-time detectable (I don't want all subcalls to be wrapped), but obvious, implicit coercions should get a configurable warning and a wrapper. sub foo(@a of Scalar) {...} foo(1, 2, 3); # OKAY foo(@a, @b, @c); # WARNING: foo(List of Array) will be coerced to foo(Array of Scalar) using &foo.wrap(__flattenArrays) foo(**(@a, @b, @c)); # OKAY: Fixed it using SuperMario operator. > > So the "use strict signatures;" wouldn't be a switch invoking type > > stricture, per se. What it would do is convert from "DWIM > > stricture" to "Patriot Act stricture". > > I still believe that the default level of type-checking you're > proposing is the wrong way round. Hmm. Okay. I'll let you reverse the default levels if you give me a single-letter command line switch to go back to "slouch-mode".. =Austin
Re: A6: Strict signature checking - was: Complex Parameter Types
Austin Hastings wrote: In this case, I rather like the idea of being able to say sub foo(@a is Array of Int) {...} my @input = read_a_bunch_o_data(); foo(@input); Where the compiler will automatically "wrap" the @input array in a make-it-an-int converter. This, to me, is DWIM. But to many others it's not DWIS ("Do What I Said"). To them, types are about compile-time checking of constraints on the run-time compatibility of data. So they would argue that declaring C like that implies that any argument passed to C ought to guarantee that it already contains Ints, rather than specifying a (possibly unsuccessful) run-time coercion to ensure that condition. And many would argue that implicit coercions on typed parameters is one of the major *problems* with C++. My own problem with this wrapping notion is that I consider it incompatible with the reference semantics of normal Perl 6 parameters. Specifically, I *don't* want the aliasing mechanism to be capable of implicit type coercions. On the other hand, I have *no* problem with this: sub foo(@a is Array of Int is copy) {...} ^^^ doing the kind of coercive wrapping you're suggesting. Connecting this with some thinking/talking about wrappage, it occurs to me that: C is just a keyword. Which means that instead of doing foo.wrap({ ...; call; ... }); That has to be: &foo.wrap({ ...; call; ... }); I could just as easily do: sub wrapper(...) { ...; call ; ... } foo.wrap(&wrapper); Right? &foo.wrap(&wrapper); But, yes. I think there may be a library of wrapper "helper-functions" used by both the compiler and module-writers. Things that do coercive behavior rather than try-but-maybe-fail behavior. Quite possibly. Though wrapping is probably too "heavy" a mechanism for type coercions. When I imagine type coercions in Perl 6, I imagine them as compile-time detectable, and explicit. So the "use strict signatures;" wouldn't be a switch invoking type stricture, per se. What it would do is convert from "DWIM stricture" to "Patriot Act stricture". I still believe that the default level of type-checking you're proposing is the wrong way round. Damian
Re: A6: Strict signature checking - was: Complex Parameter Types
--- Damian Conway <[EMAIL PROTECTED]> wrote: > Austin Hastings wrote: > > > You're treading dangerously close to the S&M line there... > > Sure. That's exactly what types are for. > Granted. > > Does it make sense to say C for this stuff? > > I'd much rather that simply using typed params invoked type > stricture. Sure, but there's a difference between "C" (Boy Scout Oath) strictness and "C++" (FBI will visit your home and do a thorough background check before we proceed) strictness. In this case, I rather like the idea of being able to say sub foo(@a is Array of Int) {...} my @input = read_a_bunch_o_data(); foo(@input); Where the compiler will automatically "wrap" the @input array in a make-it-an-int converter. This, to me, is DWIM. Connecting this with some thinking/talking about wrappage, it occurs to me that: C is just a keyword. Which means that instead of doing foo.wrap({ ...; call; ... }); I could just as easily do: sub wrapper(...) { ...; call ; ... } foo.wrap(&wrapper); Right? I think there may be a library of wrapper "helper-functions" used by both the compiler and module-writers. Things that do coercive behavior rather than try-but-maybe-fail behavior. So the "use strict signatures;" wouldn't be a switch invoking type stricture, per se. What it would do is convert from "DWIM stricture" to "Patriot Act stricture". =Austin