A6: Assignment Overloading
So, now that we have binding, is it possible to overload the assignment operator? Does the assignment operator mean value copy instead of reference copy? Luke
P6FC
hello everybody, I'm just a poor newbie here, so please bear with me :-) while reading the last Apocalypse I thought that maybe time has come to write things down (like the recent effort on properties), so I started to put down a tentative class hierarchy of the Perl6 language (I call it P6FC for Perl6 Foundation Classes, but the name may (should? :-) very well change). you can find what I've come up so far here: http://dada.perl.it/p6fc.html it's just plain ASCII for now, but I plan to have an XML file with metadata attached (eg. bibliography, apocalypse number, references and such) and a dynamically produced SVG (or something else) graph. probably I'm not the right person to mantain this (I already have my problems following p6-internals and I'm not even subscribed to p6-language), but I just wanted to throw the idea out. feel absolutely free to take over the whole stuff or reject this in disgust :-) cheers, Aldo __END__ $_=q,just perl,,s, , another ,,s,$, hacker,,print;
AW: P6FC
[snip] effort on properties), so I started to put down a tentative class hierarchy of the Perl6 language (I call it P6FC for Perl6 Foundation Classes, but the name may (should? :-) very well change). A very good idea, but i am afraid that this ML isnt the right audience. PS: But before reinventing a wheel, i would like to suggest to adopt the .NET/Java object hierarchy. Murat
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 Cperl6 -MCPAN whatever 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 Cis copy 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: Signature zones and such
Mark J. Reed wrote: 2- Yeah! ... umm, are we *paying* you for this? Not any more. In fact, like Larry and several others on the design team, I'm now paying for the privilege of doing it. ;-) If the TPF isn't supporting you folks anymore, what's the best way for those of us out in the field to contribute financial support to the development of Perl6? Thanks Mark. Your desire to support our work in that way means a great deal. I can't speak for Larry, but in my case the best way to help me help Perl nowadays is to help me find people who would like to pay me to train them (or, better still, to train their organizations). Since June last year, that's how I've been getting by. But the training market is very weak just now, so if you know anyone who might be interested in learning from me, I'd deeply appreciate hearing about it. Even if you don't know anyone with an unallocated training budget, it will help if you just bear in mind that running a training business is a full time occupation in itself, and every day I do manage to find work translates to about a week away from Perl 6, what with marketing, and contracts, and preparation, and travel, and delivery, and accounting, and etc. Sure, I was vastly more productive when Perl was my full-time job. As was Larry. But that's no longer possible. Just understanding that and accepting it patiently is a genuine way to support us. I'm sure you can imagine the weight of expectation that must sit upon Larry's broad shoulders each time another Apocalypse is due. Or upon my head, when each Apocalypse has to subsequently be explained. ;-) It has meant a great deal that people like yourselves -- who are so clearly very eager for these documents -- have waited so patiently as changing financial circumstances have continually slowed the pace at which we can produce them. And don't write off the Perl Foundation yet. TPF is just about to do a survey of what people think they (TPF) should be funding. If you believe Larry and/or myself and/or other members of the design or implementation teams are worth sponsoring, I'd certainly urge you to respond to that survey when it's announced (and, yes, I'll inform the mailing list when that happens). Meanwhile, Larry wasn't kidding when he wrote: The next major [apocalypse]...may take a while since (like a lot of people in Silicon Valley) I'm in negative cash flow at the moment, and need to figure out how to feed my family. But we'll get it done eventually. He's been in negative cash flow for some time now. As has Dan. As have several other members of the design team. That said, we certainly don't *expect* the community to fund the work we do. It would be great if they could, but as Larry points out many of them are hurting too. Meanwhile, we'll keep working on the design as best we can, come what may. None of us is asking for a hand-out. What we're asking for is that the community understand that we're all doing the best we can, within the limitations of our individual and collective resources. Damian
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 Cperl6 -MCPAN whatever 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 Cis copy 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: Signature zones and such
Damian Conway [EMAIL PROTECTED] writes: And don't write off the Perl Foundation yet. TPF is just about to do a survey of what people think they (TPF) should be funding. If you believe Larry and/or myself and/or other members of the design or implementation teams are worth sponsoring, I'd certainly urge you to respond to that survey when it's announced (and, yes, I'll inform the mailing list when that happens). Well... I've finally got my act together and invoice ORA for the summary money that's destined for TPF and I would dearly love to see all of that lump of cash go to Larry. I'd certainly like them to continue to fund the development of Perl 6 if only because I wouldn't have to change that stanza of the summary. -- Piers
Re: A6: macro invocants
The sugar I'm using here is to go from $db.do_sql(select * from Foo); to $db.select * from Foo; Since we're fishing, call it a circumfix operator, something like sql...execute. Like this: $db.sql select * from Foo; execute; __ 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 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 Crw parameter somewhere. Cconstant 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 Cref or Crw, 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 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 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
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 SMBD types will create a pragma that requires the type to be known at compile time. larry
a thought on multiple properties
This may have been asked before, and I apologize if I somehow missed it, but can junctions be used for multiple properties? I can see it possibly being useful in a situation like the following(which may be completely off, as I'm still digging my way through A6): class Foo { method bar is public is rw { } } Becoming: class Foo { method bar is public rw { } } Guess it just reads a bit better to me. And you might even be able to do some weird stuff like: class Foo { method bar is public | rw { } } Whereby bar is only an lvalue subroutine/method internally.
Re: a thought on multiple properties
On Thu, Mar 13, 2003 at 01:47:19PM -0500, Chris Dutton wrote: This may have been asked before, and I apologize if I somehow missed it, but can junctions be used for multiple properties? I can see it possibly being useful in a situation like the following(which may be completely off, as I'm still digging my way through A6): class Foo { method bar is public is rw { } } Becoming: class Foo { method bar is public rw { } } Guess it just reads a bit better to me. I don't think that junctions make sense here. Besides, the is is optional: class Foo { method bar is public rw const frob knob { ... } } -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
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 Cperl6 -MCPAN whatever 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 Cmy Int $i = $line.Int; ? 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 Cuse ludicrous typesafety; 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 Cis copy 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: struct list name=aitem value=1/item value=2/item value=3//list list name=bitem value=4/item value=5/item value=6//list list name=citem
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: a thought on multiple properties
On Thu, Mar 13, 2003 at 01:13:27PM -0600, Jonathan Scott Duff wrote: : I don't think that junctions make sense here. Besides, the is is : optional: : : class Foo { : method bar is public rw const frob knob { ... } : } That feature is still in Schroedinger's little box. Larry
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: a thought on multiple properties
Jonathan Scott Duff wrote: On Thu, Mar 13, 2003 at 01:47:19PM -0500, Chris Dutton wrote: This may have been asked before, and I apologize if I somehow missed it, but can junctions be used for multiple properties? I can see it possibly being useful in a situation like the following(which may be completely off, as I'm still digging my way through A6): class Foo { method bar is public is rw { } } Becoming: class Foo { method bar is public rw { } } Guess it just reads a bit better to me. I don't think that junctions make sense here. Besides, the is is optional: class Foo { method bar is public rw const frob knob { ... } } What we do need is some way of bundling a bunch of traits together under a simple name. This is especially useful for long involved types. Some of the type name examples in A6 are very long and if you needed to use the type several places, are not only a pain to type but you run into the is it real the same every where problem and the did I change it every where problem. As a general principle any time you have a long complicated token string that need to be use multiple places, you need a way to assign it a short hand name. Yes, a string macro will do it, but has a couple of problems: 1) difficult to generate associated error messages 2) macros are very heavy weight for this Defining a Class for this is also overkill. Maybe something like rule traitdef :w { trait ident trait* ; } So instead of saying: my %pet is Hash of Array of Array of Hash of Array of Cat; sub feed (%cats is Hash of Array of Array of Hash of Array of Cat) {...} You could say trait cat_table is Hash of Array of Array of Hash of Array of Cat; my cat_table %pet; sub feed (cat_table %cats) {...} -- Mark Biggar [EMAIL PROTECTED] [EMAIL PROTECTED]
Re: a thought on multiple properties
On Thursday, March 13, 2003, at 12:04 PM, Mark Biggar wrote: What we do need is some way of bundling a bunch of traits together under a simple name. Yes, yes, yes. Defining a Class for this is also overkill. Ye.. well, no. Why? So instead of saying: my %pet is Hash of Array of Array of Hash of Array of Cat; sub feed (%cats is Hash of Array of Array of Hash of Array of Cat) {...} You could say trait cat_table is Hash of Array of Array of Hash of Array of Cat; my cat_table %pet; sub feed (cat_table %cats) {...} I think classes are not necessarily the heavyweights some people might expect them to be... I think of them more as types, actually. Basically, if you replaced the word 'trait' with 'class', I think the current plan is that you can do exactly what you're suggesting: class CatTable is Hash of Array of Array of Hash of Array of Cat; my %pet is CatTable; sub feed (%cats is CatTable); (note I fixed the last lines to use the right syntax... before, you were actually saying that %pet was a Hash of CatTables...) MikeL
ISSUE: How is Cis variadic spelled? (was Re: A6: Signature zones and such)
On Wednesday, March 12, 2003, at 04:07 PM, Piers Cawley wrote: Michael Lazzaro [EMAIL PROTECTED] writes: Can we get a final answer, for the (documented) record? @list is variadic @list is slurpy @list is greedy @list is slurpificatious @list is slurptacular @list is bloated @list is greedy Anyone? Cis greedy or Cis variadic are both good with me too. As cute as Cis slurpy is, I'm not sure it's as obvious. And us American types will get it confused with the 7-11 spelling Cis slurpee, probably. :-) POMTC, 0.0005%. Don't care what it is, as long as it is. MikeL
Re: a thought on multiple properties
--- Michael Lazzaro [EMAIL PROTECTED] wrote: On Thursday, March 13, 2003, at 12:04 PM, Mark Biggar wrote: What we do need is some way of bundling a bunch of traits together under a simple name. Yes, yes, yes. Defining a Class for this is also overkill. Ye.. well, no. Why? Unless you mean trait-classes, because I may want the same common set of traits to apply to multiple distinct things (different classes, objects, whatever). So: type cat_table is Hash of Array of Array of Hash is traits_only; or type cat_table is Hash of Array of Array of Hash; More to the point: type sigfunc is interrupt is reentrant; sub sig_ign() is sigfunc {...} sub sig_kill() is sigfunc {...} sub sig_intr() is sigfunc {...} type null but defined but false; ... return undef but null; =Austin So instead of saying: my %pet is Hash of Array of Array of Hash of Array of Cat; sub feed (%cats is Hash of Array of Array of Hash of Array of Cat) {...} You could say trait cat_table is Hash of Array of Array of Hash of Array of Cat; my cat_table %pet; sub feed (cat_table %cats) {...} I think classes are not necessarily the heavyweights some people might expect them to be... I think of them more as types, actually. Basically, if you replaced the word 'trait' with 'class', I think the current plan is that you can do exactly what you're suggesting: class CatTable is Hash of Array of Array of Hash of Array of Cat; my %pet is CatTable; sub feed (%cats is CatTable); (note I fixed the last lines to use the right syntax... before, you were actually saying that %pet was a Hash of CatTables...) MikeL
Re: a thought on multiple properties
Michael Lazzaro wrote: Defining a Class for this is also overkill. Ye.. well, no. Why? class Foo is Bar; # normal inheritance class Baz is Bar; # the thing that we are over-killing Foo.isa(Baz) == FALSE; A lightweight, typedef-like mechanism behaves differently: class Foo is Bar; typedef Baz is Bar; Foo.isa(Baz) == TRUE; The problem biols down to the fact that inheritance hierarchies are, um, hierarchies -- trees. The lightwieght mechanism provides aliases for nodes within the tree, thus all descendent nodes are also descendents of the aliases. Dave. -- http://dave.whipp.name
Re: a thought on multiple properties
On Thursday, March 13, 2003, at 02:13 PM, Jonathan Scott Duff wrote: I don't think that junctions make sense here. Besides, the is is optional: class Foo { method bar is public rw const frob knob { ... } } Ah yes, I'd forgotten about this. Thanks. Still I wonder a bit about the idea of mutually exclusive properties, where one can take effect if the other(s) doesn't make sense in the current context. Getting mired in life can really detract from following the developments in this community.
Re: a thought on multiple properties
On Thursday, March 13, 2003, at 01:05 PM, Austin Hastings wrote: More to the point: type sigfunc is interrupt is reentrant; sub sig_ign() is sigfunc {...} sub sig_kill() is sigfunc {...} sub sig_intr() is sigfunc {...} This is WAGging based on A6, but I guess I see things like this as being implemented by making subs that inherit from subs: class sigfunc is sub (...default signature...) is interrupt is reentrant; sub sig_ign(...alternate signature...) is sigfunc {...} sub sig_kill is sigfunc {...} sub sig_intr is sigfunc {...} sigfunc sig_foo {...} # could you also say it like this, I wonder? Since Csub is itself a class, you can subclass it. And since A6 indicates that the signature, traits, and even implementing body are just properties of a given Csub object, you should be able to override them individually if you want, for example, an alternate signature. At least, I'm hoping something like that works -- there's a lot of guessing there. type null but defined but false; ... return undef but null; Hmm... I'm not entirely sure how that works for runtime properties... but what about class null is void but defined but false; return undef but null; Would something like that that be OK? Essentially using 'void' as a marker that you're defining a (heh) classless class? I'd really like to avoid making a separate keyword for combining traits, I'd love for it to just use the normal class inheritance mechanisms. class CatTable is Hash of Array of Array of Hash of Array of Cat; my %pet is CatTable; sub feed (%cats is CatTable); MikeL
Re: a thought on multiple properties
On Thursday, March 13, 2003, at 01:23 PM, Dave Whipp wrote: Michael Lazzaro wrote: Defining a Class for this is also overkill. Ye.. well, no. Why? class Foo is Bar; # normal inheritance class Baz is Bar; # the thing that we are over-killing Foo.isa(Baz) == FALSE; A lightweight, typedef-like mechanism behaves differently: class Foo is Bar; typedef Baz is Bar; Foo.isa(Baz) == TRUE; Ah, I get it. But why would you want that -- treating Foo and Baz as synonymous? Shouldn't you always be using Baz instead of Foo, if you really mean Baz and not Foo, and vice versa? Because later on, if you changed it such that: class Foo is Bar; typedef Baz is Bar is blarpy; Foo.isa(Baz) == FALSE; # BOOM! ...which would break anything that relied on the symmetry. Mind you, I'm not really against the idea, I'm just devil's advocating -- trying to think whether we really need the feature or whether we just _think_ we need it because we're all used to it from C, when in fact P6 will provide better ways of doing it. (?) MikeL
Re: a thought on multiple properties
--- Michael Lazzaro [EMAIL PROTECTED] wrote: On Thursday, March 13, 2003, at 01:05 PM, Austin Hastings wrote: More to the point: type sigfunc is interrupt is reentrant; sub sig_ign() is sigfunc {...} sub sig_kill() is sigfunc {...} sub sig_intr() is sigfunc {...} This is WAGging based on A6, but I guess I see things like this as being implemented by making subs that inherit from subs: class sigfunc is sub (...default signature...) is interrupt is reentrant; sub sig_ign(...alternate signature...) is sigfunc {...} sub sig_kill is sigfunc {...} sub sig_intr is sigfunc {...} sigfunc sig_foo {...} # could you also say it like this, I wonder? Since Csub is itself a class, you can subclass it. You are a bad, evil man for reminding me of this. I have yet to brainvomit about stack-streams. (I have found an interesting analogy between subs/blocks and streaming video compression, but it is too large to fit in the margin :-) And since A6 indicates that the signature, traits, and even implementing body are just properties of a given Csub object, you should be able to override them individually if you want, for example, an alternate signature. At least, I'm hoping something like that works -- there's a lot of guessing there. Which reminds me that sigfuncs aren't is reentrant. They're but reentrant. my sub foo = sig_kill; # foo is but interrupt reentrant, too. Which points in the direction of sticky value traits, and sticky value traits is a synonym for class. So you're right -- this case is a class extension. But then the question becomes how easy is it to override a class like this? sub sig_kill is sigfunc {...} sub sig_intr is sigfunc {...} sigfunc sig_foo {...} # could you also say it like this, I wonder? Well, no. That's going to look like a function returning a sigfunc. Obviously we're walking on an edge-case. (Lucky for me that you're Mr. Edge-Case, eh?) type null but defined but false; ... return undef but null; Hmm... I'm not entirely sure how that works for runtime properties... but what about class null is void but defined but false; return undef but null; Would something like that that be OK? Essentially using 'void' as a marker that you're defining a (heh) classless class? I'd really like to avoid making a separate keyword for combining traits, I'd love for it to just use the normal class inheritance mechanisms. Cool if you can get it. But I want to be able to handle all sorts of trait-contexts: my macro sucks() is parsed(/null/) { is slurpificatious } class foo_arg is rw is copy is coerced is optional; sub foo( $v is foo_arg, @x is foo_arg sucks) {...} =Austin
Re: a thought on multiple properties
On Thu, Mar 13, 2003 at 01:47:19PM -0500, Chris Dutton wrote: : This may have been asked before, and I apologize if I somehow missed it, : but can junctions be used for multiple properties? : : I can see it possibly being useful in a situation like the : following(which may be completely off, as I'm still digging my way : through A6): : : class Foo { : method bar is public is rw { : : } : } : : Becoming: : : class Foo { : method bar is public rw { : : } : } : : Guess it just reads a bit better to me. Er, I'm not sure how that would actually be implemented. : And you might even be able to do some weird stuff like: : : class Foo { : method bar is public | rw { : : } : } : : Whereby bar is only an lvalue subroutine/method internally. You're already confusing or with xor. This does not bode well... Larry
Re: a thought on multiple properties
Ah, I get it. But why would you want that -- treating Foo and Baz as synonymous? Shouldn't you always be using Baz instead of Foo, if you really mean Baz and not Foo, and vice versa? Because later on, if you changed it such that: class Foo is Bar; typedef Baz is Bar is blarpy; Foo.isa(Baz) == FALSE; # BOOM! ...which would break anything that relied on the symmetry. Ahh, but I think it is important. When programming in C++ I use typedefs all over the place for various reasons. A typedef is more than a class that behaves exactly the same... it's more of a pointer. To a data type. It allows you to do stuff like type-linked-lists (typelists Alexandrescu calls them), and without it, these things would actually be impossible. Of course, in the realm of Perl, things might not be so important. Because of Perl's power, typelists and their siblings aren't all that useful. You could, I imagine, get about the same effect with: my $Baz is constant = Bar is blarpy; With the psychological disadvantage of holding a type in a dollar-variable. [But then he remembers the := operator] class Baz := Bar is blarpy; I've seen the design team refer to things like this, so I think we've got it. Oh, on an off-topic note, Modern C++ Design is a super spiffy book. People who wonder what C++ has on Java haven't read this book :). Luke
Re: a thought on multiple properties
--- Michael Lazzaro [EMAIL PROTECTED] wrote: A lightweight, typedef-like mechanism behaves differently: class Foo is Bar; typedef Baz is Bar; Foo.isa(Baz) == TRUE; Ah, I get it. But why would you want that -- treating Foo and Baz as synonymous? Treating BAR and BAZ as synonymous. Coincidentally, Foo is Bar. Mind you, I'm not really against the idea, I'm just devil's advocating -- trying to think whether we really need the feature or whether we just _think_ we need it because we're all used to it from C, when in fact P6 will provide better ways of doing it. (?) macro *defmacro($t1, @rest is variadic) is parsed(/token token+ ;/) { eval macro *$t1 is parsed(/null/) { return @rest.join(' '); }; } defmacro Baz Bar; m4, anyone? =Austin
Re: A6: Signature zones and such
Simon Cozens [EMAIL PROTECTED] writes: [EMAIL PROTECTED] (Piers Cawley) writes: Well... I've finally got my act together and invoice ORA for the summary money that's destined for TPF and I would dearly love to see all of that lump of cash go to Larry. Yay, another attempt to confuse me and ORA's payments division. ;) I'll see what can be done. Nope, send it to TPF as discussed. It's what I've said in all the summaries after all. I just hope that a chunk of it ends up in Larry's pocket. -- Piers
Re: A6: Signature zones and such
Brent Dax writes: Damian Conway: # Brent Dax wrote: # #method x ($me: $req, ?$opt, +$namedop, *%named, [EMAIL PROTECTED]) { ... } # # Yikes. And I thought we were trying to get *away* from # line noise? # :^) However that's an example explicitly demonstrating all the variations. In practice I'd've thought that many people will have a coding style that nearly-always uses positional parameters and that many other people will always use named parameters. And a C? to make an argument optional isn't that hard to remember. # Seriously, can't we use something rather prettier, like this? # #method x($me: $req, $opt is optional, $namedop is # named, *%named, [EMAIL PROTECTED]) { ... } # # It's quite possible that the following equivalences might hold: # # ?$xsame as$x is optional # +%ysame as%y is named # # So that you could choose. Sweet. I don't like the alternatives being available. Having more than one way to approach things (named or positional parameters; typed or untyped variables) is good; having more than one syntax for doing exactly the same thing can be confusing. Yes, there are other places in Perl with alternative syntaxes. Cqq[...] for C... is very useful. But it's at least similar (punctuation before and after some text) and there's an excellent reason why the 'standard' syntax is defective in some circumstances, and most people use which ever syntax is most appropriate for the text in question. And there are places where an alternative syntax has been declined -- or at least declined as a standard part of the language, leaving people free to define equivalences if they want -- such as comments with something other than C#. My problem with the above alternatives is that they make the language bigger: there's more to learn. Even if as an individual you decide just to use on of the forms[*0] you still have to know the other version, because you're going to encounter other people's code using it. Things like this make Perl awkward to teach. For things like Cqq there's an obvious benefit, and it's worth it. But there doesn't seem to be a benefit here, merely different people having different preferences (which isn't surprising). Permitting both syntaxes (so that people with a strong preference can use the one they personally prefer and grimace at code written by those of the opposite persuasion) is an uneasy compromise. I'm concerned that this is an example of the 'Mozilla preferences problem': many discussions on features in 'Mozilla' led to the addition of another preference so that different people can have the feature work different ways. This shuts up both sides (of those who had strong views either way), while bloating the program with yet another confusing preference setting and baffling casual users as to why it contains so many options rather than working right in the first place. The second problem with the alternatives is that somebody who uses the symbolic version and gets used to using it may scan a parameter declaration that uses the wordy form. But not being used to the wordy form, the crucial traits aren't spotted among the other words in there, so he/she misinterprets the declaration. It's not just a case of knowing about the alternative syntax, but the fact that every time you read a declaration you have to check for both versions -- well, that's either a required positional parameter, or it's something else which'll be described in a few words' time once I've got past the type of this variable and a few other traits. I'm not particularly bothered which syntax we choose (40% in favour of the symbolic over the wordy) but much more concerned (85%) about there only being _one_ syntax. (In other words, I'd rather not have the syntax that I prefer than have multiple alternative syntaxes). [*0] And it strikes me as quite likely that most people will fix on one of them -- why would anybody flip between them? -- which provides another source of pointless style arguments. Smylers
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: overloading multis on constness of parameters
Piers Cawley wrote: Speaking of multis and constants, Greg McCarroll wondered on IRC if this would work: multi factorial (Int 0) { 1 } multi factorial (Int $n) { $n * factorial($n-1) } Probably not. We did discuss whether multimethods should be able to be overloaded by value, but concluded (for that week, at least ;-) that this might prove syntactically excessive. Besides which, since multimethod dispatch will have to use Cisa to determine type compatibility on parameters anyway, it's trivial to implement this form of value-based dispatch yourself: class Zero { multi *isa ($obj, Zero $class) { $obj ~~ 0 } } # and then... multi factorial (IntZero $g) { 1 } or, supposing we have some form of parameterized types, you could create something more generic like: class Val($N) { multi *isa ($obj, Val($N) $class) { $obj ~~ $N } } # and then... multi factorial (IntVal(0) $g) { 1 } ;-) Damian
Re: A6: Assignment Overloading
Luke Palmer wrote: So, now that we have binding, is it possible to overload the assignment operator? Not really. The problem is that Cinfix:= is really an operator on *containers*, not on *values*. So, in order to overload C=, you'll still need to define an appropriate CSTORE method on the appropriate implementation class for the container. Whether CSTORE can also be spelled Cinfix:= is another question. Does the assignment operator mean value copy instead of reference copy? The assignment operator means copy rhs's value into lhs's container. The binding operator means copy (reference to) rhs's container into lhs's symbol table entry. Damian
Re: A6: overloading multis on constness of parameters
or, supposing we have some form of parameterized types, you could create something more generic like: class Val($N) { multi *isa ($obj, Val($N) $class) { $obj ~~ $N } } # and then... multi factorial (IntVal(0) $g) { 1 } Yes, YES! Marvelous! Not that that couldn't be done with a closure anyway... { my Class %valClasses; sub Val($N) returns Class { my Class $rclass = %valClasses{$N} //= class { multi *isa ($obj, $rclass $class) { $obj ~~ $N } } } } multi factorial (Int Val(0) $g) { 1 } Hmm, would Val(0) be evaluated at compile-time in that case... or must I mark it with some sort of trait, or do some other kind of trick. Cool, anyhow. Luke
Re: A6: overloading multis on constness of parameters
Luke Palmer wrote: Not that that couldn't be done with a closure anyway... { my Class %valClasses; sub Val($N) returns Class { my Class $rclass = %valClasses{$N} //= class { multi *isa ($obj, $rclass $class) { $obj ~~ $N } } } } multi factorial (Int Val(0) $g) { 1 } I don't think so. I seriously doubt you can put a run-time-evaluated sub call in a type specification visions of Dan fainting in horror ;-) A Cmacro might do the trick though. Oh, and I was wrong to originally write: Cmulti *isa ... Multimethods live in their own namespace. No * required. Damian
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 BD 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 BD 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
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
another response to apo6 transfinite semantics challenge
However, if you access the last element using the length of the array, it may try to flatten, and fail: my @flat = (1..Inf, 1..10); $last = @[EMAIL PROTECTED] - 1]; # Kaboom! How about negative indices? We have negative indices in the slice() semantics; what if $last = @array[-1] always worked? -- David Nicol, independent consultant and contractor perl -Mcoroutine0 -e'$c=new coroutine0 VARS=[],BODY=qYIELD 74; YIELD 65;YIELD 80;YIELD 72; YIELD 10;;for(;;){print chr($c||die)};'