Re: supertyping
Luke Palmer wrote: Jonathan Lang wrote: > Agreed. The question is whether you think of a role as a set of > methods ("intension set") or as a set of instances ("extension set"). > FWIW, it wasn't until this thread that I even registered that the > latter possibility existed. Given the above contrast between roles > and subtypes, I would really like to keep the extension set mindset > limited to subtypes and the intension set mindset limited to roles: a > role is an interface (i.e., a set of methods); a type is a set of > possible instances. Eh, a proposal is nothing if you can't make sense of it from both mindsets, because they both are real. While you may think of a role as an interface, it still does have objects that can obey it, so the set of such objects still exists. My brain seems to prefer the extensional mindset, but it's important to try to make sense of everything from both. Hmm, the extensional is the more "spookily theoretical" of the two, since Perl will know the interface, but it won't create the set of all possible, eventual instances. OK. With this in mind, I suppose that set operations, per se, are indeed out. Let's see what can be done with "does" and "done_by" (for lack of a better name). First, note that role Foo does Bar does Baz { ... } is exactly the same as role Foo { does Bar; does Baz; ... } Likewise, I'd expect role Foo done_by Bar { ... } to be equivalent to role Foo { done_by Bar; ... } or role Foo { ... ; done_by Bar } The contents of the curly braces should always define the interface that the role brings to the table. Furthermore, "done_by" statements should have no effect whatsoever on Foo's interface, other than to define restrictions on what is legal in Foo (maybe). In extension set terminology, the above means that "Foo = ...; Bar (+)= Foo". In effect, "Foo done_by Bar" means "modify Bar to include 'does Foo'". In this way, mixtures of "does" and "done_by" work in an intuitive way: only "does" helps establish what the role is capable of, while "done_by" feeds those capabilities into another, existing role. Which gets back to the issue of whether roles should be mutable or not. If roles are immutable, then "done_by" is going to have to levy some rather heavy-handed restrictions on the new role, specifically to avoid new capabilities being back-edited into existing roles. If roles are mutable, "done_by" needn't impose any restrictions - but the creator of the new role has the responsibility to ensure that any additions that he makes doesn't break any existing classes. Unfortunately, this approach completely misses the boat in terms of what I was looking for in supertyping - namely, the ability to reuse portions of an existing interface (such as the aforementioned "extract an Order role out of the Num role") - useful when using modules where the module designer overcomplicated things, but you don't want to rebuild everything from scratch. That, I think, is the common feature of both goals: the ability to compensate for another coder who didn't do things exactly the way you want them done, but who was reasonably close. Note that I *am* arguing for a back-editing behavior. You are of course allowed to remove anything (by not declaring it), and you are also allowed to add new methods as long as they have a default implementation. You are not allowed to add new unimplemented, or required, methods. Note that the "default implementation" requirement need only be specified in terms of the done_by roles: "method foo(Foo: ) { ... }" is perfectly legitimate, as long as &Foo::foo:(Bar: ) and &Foo::foo:(Baz: ) are more solidly defined, given "Foo done_by(Bar) done_by(Baz)". (BTW: as I see it, all methods defined in Foo are "required". I'd prefer "unimplemented" or "abstract" as the description for methods with '{ ... }' as the body.) The reasoning for this is mostly utility. How are you supposed to generalize Num to Complex (okay, fine, I'll try to come up with another example. Is it okay if it is also from math?) if Num didn't know that an "imaginary part" existed? I suspect that Num vs. Complex is considered to be a poor choice for an example because Num and Complex are going to be standard types already. You could really consider that syntax sugar if you like: role Foo { method foo() { "hello" } } role Bar superdoes Foo { method bar() { "world" } } Is equivalent to declaring Bar with no methods, and then adding: multi sub bar(Bar:) { "world" } Modulo some minor differences, but the semantics are essentially the same. I don't think we'd want to disable back-editing because then we would be encouraging the idiom I just demonstrated, which is less clear (IMO). My understanding is that subs can't have invocants; only methods and submethods can, and both of those must be defined within a role or class. Back-editing seems weird from an intensional mindset, but perfectly natural fro
Re: RFC: Proposal for dynamic binding
From: Allison Randal <[EMAIL PROTECTED]> Date: Sat, 09 Dec 2006 21:55:35 -0800 Bob Rogers wrote: > This is also my definition of "dynamic scoping". Were you not aware of > this behavior of "local", or are we talking about different things > entirely? I was talking about the lifetime of the temporization not static vs. dynamic scoping. OK, then I think we agree. (Your original statement was ambiguous about whether you were talking about scope or lifetime, but then your next statement used the word "scope.") But, this does help me better understand what you're getting at. The proposal only mentions "dynamic scope" three times, but reading through it again now I can see that the whole proposal is a literal implementation of a classic textbook definition of dynamic scope. Yes. But I've been calling it "dynamic binding" because it's the variable binding that has dynamic scope. I'm willing to adopt your terminology, but you'll have to bear with me, because I've been saying "dynamic binding" for quite a while now. But what would you have me use for the verb, if not "to bind"? [For reference, Wikipedia says: "In dynamic scoping, each identifier has a global stack of bindings. Introducing a local variable with name x pushes a binding onto the global x stack (which may have been empty), which is popped off when the control flow leaves the scope. Evaluating x in any context always yields the top binding."] I saw this, too. I assume this is just a conceptual simplification for teaching purposes; it would be silly to create a literal stack for each variable when only a handful of them will ever be rebound this way at any given time. None of the compilers I'm aware of do it this way. >But I'm still unclear how this distinction is made in a Perl 6 > program. If you write > >temp $foo = 37; > > is this assignment or binding? And in either case, how do you specify > the other? Larry? (Not that understanding this is likely to be > necessary for getting Parrot to do the right thing.) That's assignment. Binding would be: temp $foo := 37; Great; thanks. >> Could you be more specific about the proposed implementation? What >> issues do you have with it? Is it worth fixing, or should I give up? > >Mainly, I don't see the proposal as it stands as a solution for 'temp' >and 'local'. Dynamic binding as you define it (what I'm calling >thread-locals), is a completely different problem. The proposal needs a >description of the problem it is solving, instead of describing one >problem and solving a different one. > > Does the Perl 5 example above convince you that it is the same problem? > Or at least a subset, given that I didn't follow the "assignment > vs. binding" thing? We're now talking about 3 different things: dynamic binding, dynamic scoping, and temporization. Dynamic binding is any association of a value with an identifier, when that association is made at runtime. It's much broader than what we're talking about here. So, let's stop using that term. Now I'm confused again. Isn't that exactly what we're talking about, but generalized to include binding of non-variables? On dynamic scoping and temporization, I agree that they're related problems, in that some definitions of temporization use dynamic scoping. But either feature can be used without the other, so it's better to separate the implementation of dynamic scoping from the implementation of temporization. OK. >Also, the particular implementation suggested -- the Location class >hierarchy of abstract and instantiable classes, the stack of stored >values -- is more heavy weight than the underlying concept merits. > > If you can think of a lighter-weight approach, I'm all ears. I proposed > something fairly lightweight nearly a year ago, with nearly the same > functionality, though it only addressed globals. Leo quite reasonably > objected that it didn't fully implement Perl 5 "local", and I agreed > that it was too particular to globals to be generalized, so I withdrew > it. The new approach attempts to address that limitation by introducing > PMC classes to support structure and variable binding distinctly in an > extensible way. Now it appears that I need to be both (a) more > complete, to handle assignment as opposed to just binding, and (b) > lighter in weight. Please pick just one. ;-} Lighter weight, by separating out the problems into separate components. Assignment and binding are relevant to temporization, not to dynamic scoping. ??? Do you mean "The assignment versus binding distinction is relevant to temporization, not ..."? If so, I'm perfectly happy to ignore it. > I would like to see this implemented, so I'm willing to go back to the >
[svn:perl6-synopsis] r13490 - doc/trunk/design/syn
Author: larry Date: Wed Dec 13 17:50:39 2006 New Revision: 13490 Modified: doc/trunk/design/syn/S04.pod Log: Generalized the do/gather syntax to other similar dynamic scoping constructs. Modified: doc/trunk/design/syn/S04.pod == --- doc/trunk/design/syn/S04.pod(original) +++ doc/trunk/design/syn/S04.podWed Dec 13 17:50:39 2006 @@ -12,9 +12,9 @@ Maintainer: Larry Wall <[EMAIL PROTECTED]> Date: 19 Aug 2004 - Last Modified: 5 Dec 2006 + Last Modified: 13 Dec 2006 Number: 4 - Version: 45 + Version: 46 This document summarizes Apocalypse 4, which covers the block and statement syntax of Perl. @@ -410,7 +410,18 @@ statement or block, and executes it once. Unlike C, its return value is a specified by calling the C function one or more times within the dynamic scope of the gather. The returned values are -flattened into a lazy list. +flattened into a lazy list. A C is not considered a loop. + +Other similar C-only forms may also take bare statements, +including C, C, C, and C. These constructs +establish a dynamic scope without necessarily establishing a lexical +scope. (You can always establish a lexical scope explicitly by using +the block form of argument.) As statement introducers, all these +keywords must be followed by whitespace. You can say something +like C, but then you are calling it using function call +syntax instead, in which case the C argument must be a block. +For purposes of flow control, none of these forms are considered loops, +but they may easily be applied to a normal loop. =head1 Switch statements
Re: 6-on-5 and read only aliasing
VINE On 12/13/06, Nicholas Clark <[EMAIL PROTECTED]> wrote: For the effort to implement a Pugs backend to run Perl 6 on Perl 5, one part that was looking tricky was how to make read only aliases of read-write values. Data::Bind fakes the functionality with magic, but I think that it's going to have limitations with corner cases. The better solution appears to be to add a type to the core, akin to references (SvRV) which acts as an automatic alias type. Since 5.000 there have been 16 internal types in Perl, which feels like a nicer number to keep than go to 17. With change 29544 I've finished moving things around to abolish the need for the PVBM type, probably the least used of any of the internal types. Its functionality, storing tables for fast Boyer-Moore string scanning, can be achieved by using PVGV after a bit of rearranging of flags and structures. So to keep at the nice number of 16, there is a placeholder for a new type, tentatively named BIND, for 6-on-5 aliasing. It's all yours, 6-on-5 hackers. I'm not exactly sure what is needed for 6-on-5, beyond read only aliases to read-write values, but I think that implementing a workable version of that should be fairly straightforward. Probably something like: a: Make all data reading functions, as their first action, check if they have a BIND, and if so dereference it immediately. Functions like sv_2iv_flags, sv_2uv_flags etc b: Make all data writing functions, as their first action, check if they have a BIND. If it's not read only, dereference it immediately. Otherwise, leave it be, and it will hit that function's readonly check for the correct error. (Look for PL_no_modify, which holds the string "Modification of a read-only value attempted" c: Ensure that the macro SvOK() chases the dereference. (As it's likely that the dereference itself won't have any of the SV flags set that mark it as "true" Although some niggling sense of doubt tells me that it will get fun before it gets pretty. Suggestions for a better name for BIND welcome. 4 letters or fewer. Nicholas Clark PS blead source is at rsync://public.activestate.com/perl-current/ -- Outside the mind, there is no Lotus Sutra..& outside the Lotus Sutra, there is no mind... (Hakuin) antiparanoid.blogspot.com
Re: supertyping
In spite of Larry's comments, I will continue to entertain this idea until it is solid to myself that I would be comfortable accepting it. On 12/13/06, Jonathan Lang <[EMAIL PROTECTED]> wrote: Agreed. The question is whether you think of a role as a set of methods ("intension set") or as a set of instances ("extension set"). FWIW, it wasn't until this thread that I even registered that the latter possibility existed. Given the above contrast between roles and subtypes, I would really like to keep the extension set mindset limited to subtypes and the intension set mindset limited to roles: a role is an interface (i.e., a set of methods); a type is a set of possible instances. Eh, a proposal is nothing if you can't make sense of it from both mindsets, because they both are real. While you may think of a role as an interface, it still does have objects that can obey it, so the set of such objects still exists. My brain seems to prefer the extensional mindset, but it's important to try to make sense of everything from both. Hmm, the extensional is the more "spookily theoretical" of the two, since Perl will know the interface, but it won't create the set of all possible, eventual instances. > But that makes no sense at all because these are the ones which are > specialized further down in the subtyping chain. There has to be > some extra that the supertype defines for the subtypes. No, there doesn't. For example, let's assume that whoever created the Num role forgot to define an Order role for it. Supertyping would let you create that role for yourself and would ensure that it has the proper relationship with Num. That's what supertyping of roles should be about: extracting subsets of its interface for use elsewhere (which is part of the reason I'm leery about calling it "supertyping"; the important part isn't the greater number of instances that it can have, but instead the simpler interface that it provides). Note that I *am* arguing for a back-editing behavior. You are of course allowed to remove anything (by not declaring it), and you are also allowed to add new methods as long as they have a default implementation. You are not allwed to add new unimplemented, or required, methods. The reasoning for this is mostly utility. How are you supposed to generalize Num to Complex (okay, fine, I'll try to come up with another example. Is it okay if it is also from math?) if Num didn't know that an "imaginary part" existed? You could really consider that syntax sugar if you like: role Foo { method foo() { "hello" } } role Bar superdoes Foo { method bar() { "world" } } Is equivalent to declaring Bar with no methods, and then adding: multi sub bar(Bar:) { "world" } Modulo some minor differences, but the semantics are essentially the same. I don't think we'd want to disable back-editing because then we would be encouraging the idiom I just demonstrated, which is less clear (IMO). Back-editing seems weird from an intensional mindset, but perfectly natural from an extensional mindset (you are just defining functions on things). If you don't think of a role as a set of methods, but rather a tree of sets of methods (like inheritance), then back-editing seems more natural (you just insert a different parent above the old role). One problem with this is that the default return value for Num.im ought to be zero; the default return value for Complex.im ought to be whatever the imaginary component of the number is. So role Complex would need both method im (Complex: ) { return .im } method im (Num: ) { return 0 } Good point. Hmm, that's a bit awkward. It can actually be averted in the Complex case, by defining the .im attribute to default to 0. But that is a hack that will not generalize. For now (because of this example, in fact), I'm inclined to change the proposal to "please don't design the language to prevent a module from implementing supertyping". I think disallowing reopening of roles will prevent that. Maybe we allow reopening of roles, but new method declarations have to come with defaults; that way you are not (as above) invalidating existing objects, just adding behavior to them. That is a tricky issue, though, because such definitions might add conflicts and invalidate those objects anyway. Maybe more-recently added methods have less priority than older ones. That stinks. Hmm. I need to think about this. Luke
6-on-5 and read only aliasing
For the effort to implement a Pugs backend to run Perl 6 on Perl 5, one part that was looking tricky was how to make read only aliases of read-write values. Data::Bind fakes the functionality with magic, but I think that it's going to have limitations with corner cases. The better solution appears to be to add a type to the core, akin to references (SvRV) which acts as an automatic alias type. Since 5.000 there have been 16 internal types in Perl, which feels like a nicer number to keep than go to 17. With change 29544 I've finished moving things around to abolish the need for the PVBM type, probably the least used of any of the internal types. Its functionality, storing tables for fast Boyer-Moore string scanning, can be achieved by using PVGV after a bit of rearranging of flags and structures. So to keep at the nice number of 16, there is a placeholder for a new type, tentatively named BIND, for 6-on-5 aliasing. It's all yours, 6-on-5 hackers. I'm not exactly sure what is needed for 6-on-5, beyond read only aliases to read-write values, but I think that implementing a workable version of that should be fairly straightforward. Probably something like: a: Make all data reading functions, as their first action, check if they have a BIND, and if so dereference it immediately. Functions like sv_2iv_flags, sv_2uv_flags etc b: Make all data writing functions, as their first action, check if they have a BIND. If it's not read only, dereference it immediately. Otherwise, leave it be, and it will hit that function's readonly check for the correct error. (Look for PL_no_modify, which holds the string "Modification of a read-only value attempted" c: Ensure that the macro SvOK() chases the dereference. (As it's likely that the dereference itself won't have any of the SV flags set that mark it as "true" Although some niggling sense of doubt tells me that it will get fun before it gets pretty. Suggestions for a better name for BIND welcome. 4 letters or fewer. Nicholas Clark PS blead source is at rsync://public.activestate.com/perl-current/
Re: Past-pm basic string types
On Tue, Dec 12, 2006 at 01:57:20PM -0800, Allison Randal wrote: > Patrick R. Michaud wrote: > >I can modify PAST-pm to provide a "send exactly this string to PIR" > >option for PAST::Val. > > Yes, good idea for the simple case. After sleeping on it overnight, I realized that PAST-pm already has this feature. Currently PAST-pm checks the PAST::Val node's "ctype" attribute to decide whether to encode the literal value as a Parrot form -- if the node doesn't have ctype that indicates "string constant", then PAST-pm just uses the literal value directly in the output. So, just don't set "ctype", and whatever the node has as its "name" attribute will go directly into the PIR output. Here's an example: $ cat x.pir .sub main :main load_bytecode 'PAST-pm.pbc' .local pmc valnode, blocknode, pir ## $S0 is the string we want to appear in the output $S0 = '"\n"' valnode = new 'PAST::Val' valnode.'init'('vtype'=>'.String', 'name'=>$S0) blocknode = valnode.'new'('PAST::Block', valnode, 'name'=>'anon') ## compile the tree to PIR and print the result $P99 = compreg 'PAST' pir = $P99.'compile'(blocknode, 'target'=>'pir') print pir .end $ ./parrot x.pir .sub "anon" new $P10, .String assign $P10, "\n" .return ($P10) .end Eventually the handling of "ctype" is going to change -- first, the name will change to be more descriptive (but I'll leave a 'ctype' accessor in place to give compilers time to switch); second, any ctype specifications will be held in a HLL class mapping table instead of in each PAST::Val node. There is a good chance that PAST-pm will treat PAST::Val nodes of type .String as needing their values to be encoded for Parrot, but to protect against this punie (and other compilers) can use .Undef: $S0 = '"\n"' valnode = new 'PAST::Val' valnode.'init'('vtype'=>'.Undef', 'name'=>$S0) Since the node isn't a string type, PAST-pm will use the "name" $S0 value directly in the output PIR without performing any encoding on the literal value, and the generated PIR from the node would look like new $P10, .Undef assign $P10, "\n" And this does exactly what you want. :-) Pm
Re: [perl #41082] [RESOLVED] [PATCH] Cygwin: conflicting types for _LIB_VERSION
In message <[EMAIL PROTECTED]>, "Jerry Gay via RT" writes: : According to our records, your request regarding : "[PATCH] Cygwin: conflicting types for _LIB_VERSION" : has been resolved. Is this a known issue? What was the resolution? Thanks, Greg
Re: Strange error message with anon subroutine
On Wed, Dec 13, 2006 at 11:31:33AM -0800, Ovid wrote: > *** Cannot use this control structure outside a 'routine' structure > at 99.pugs line 103, column 13-22 > > Take out the returns, and it works fine. Can someone tell me what I'm > missing? Is this a bug. Perl 6 differentiates between a bare Code and Routine objects. Replacing "->" with "sub" should get you what you want. -- Gaal Yahas <[EMAIL PROTECTED]> http://gaal.livejournal.com/
Re: Strange error message with anon subroutine
On Wed, Dec 13, 2006 at 11:31:33AM -0800, Ovid wrote: : In trying to compress a list, I wrote the following code: : : my $compress = do { : my $previous; : $compress = -> $x { : if !defined $previous or $x ne $previous { : $previous = $x; : $x; : } : else { : (); : } : }; : } : my @compressed = map $compress, ; : @compressed.say; : : That's a bit more verbose than I intended, but that's partially because : of this: : : my $compress = do { : my $previous; : $compress = -> $x { : if !defined $previous or $x ne $previous { : $previous = $x; : return $x; : } : else { : return (); : } : }; : }; : : As soon as I put the return statements in an anonymous subroutine, I : get this error message: : : *** Cannot use this control structure outside a 'routine' structure : at 99.pugs line 103, column 13-22 : : Take out the returns, and it works fine. Can someone tell me what I'm : missing? Is this a bug. Nope, spec. S06 says: [Pointy block] also behaves like a block with respect to control exceptions. If you C from within a pointy block, it will return from the innermost enclosing C or C, not the block itself. It is referenced by C<&?BLOCK>, not C<&?ROUTINE>. See also the section in S04 discussing control exceptions, where it says: A C always exits from the lexically surrounding sub or method definition (that is, from a function officially declared with the C, C, or C keywords). Pointy blocks and bare closures are transparent to C. So all you really need to do is change the pointy to an official sub: my $compress = do { my $previous; $compress = sub ($x) { if !defined $previous or $x ne $previous { $previous = $x; return $x; } else { return (); } } } : Also, I noticed I accidentally left off the final semi-colon on the do : block. It ran anyway and that surprised me. S04: Outside of any kind of expression brackets, a final closing curly on a line (not counting whitespace or comments) always reverts to the precedence of semicolon whether or not you put a semicolon after it. Larry
Re: Introspection and list question
On Wed, Dec 13, 2006 at 10:55:28AM +0200, Gaal Yahas wrote: : L stipulates the : results of a gather are flattened to a lazy list. I'm not sure how far : that flattenning goes, but one of these should do the trick, I think It would only flatten a recursive structure with the help of something that recurses. The flattening of gather/take itself is only one level, insofar as the various takes are treated as "pushes" onto the list being gathered. : (Pugs does not yet implement gather/take): Actually, it does, but only the block form. The generalization to any statement (using C syntax) was a very recent change. The following prints (1, 2, 3, 4, 5) in current pugs: #!/usr/bin/pugs my $a = [1,2,[3,4],5]; multi flattener ($x) { take $x; } multi flattener (Array @array) { for @array -> $elem { flattener($elem); } } sub flatten ([EMAIL PROTECTED]) { for @args -> $arg { return gather { flattener($arg) } } } $a.flatten.perl.say; Larry
Strange error message with anon subroutine
In trying to compress a list, I wrote the following code: my $compress = do { my $previous; $compress = -> $x { if !defined $previous or $x ne $previous { $previous = $x; $x; } else { (); } }; } my @compressed = map $compress, ; @compressed.say; That's a bit more verbose than I intended, but that's partially because of this: my $compress = do { my $previous; $compress = -> $x { if !defined $previous or $x ne $previous { $previous = $x; return $x; } else { return (); } }; }; As soon as I put the return statements in an anonymous subroutine, I get this error message: *** Cannot use this control structure outside a 'routine' structure at 99.pugs line 103, column 13-22 Take out the returns, and it works fine. Can someone tell me what I'm missing? Is this a bug. Also, I noticed I accidentally left off the final semi-colon on the do block. It ran anyway and that surprised me. Cleaner ways of writing that code are welcome, too. Cheers, Ovid -- Buy the book -- http://www.oreilly.com/catalog/perlhks/ Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/
Re: Gather/Take and threads
On Wed, Dec 13, 2006 at 11:01:10AM -0800, Larry Wall wrote: : Of course, it's also possible that the flipside is true--that : gather/take is just another normal way to set up interthread queueing, : if the thread is spawned in the dynamic scope of the gather. : Under that view all the subthreads share the outer dynamic scope. : Maybe that's saner... And a subdivision of that view is whether subthreads are naturally collected at the end of the dynamic scope that spawned them, or whether they are considered independent unless some dynamic scope "claims" them all for collection. In that case a gather would one way (the normal way?) to require termination of all subthreads before terminating its lazy list. Larry
Re: supertyping
On Wed, Dec 13, 2006 at 11:25:40AM +, Smylers wrote: : Jonathan Lang writes: : : > For the record, I think that "superdoes" should be spelled "done_by". : : I think it's unlikely that Larry will incorporate any keywords that : contain underscores -- certainly not without at least searching for a : single word that sums up the concept in question. And I'm not even gonna do that if I can't be convinced of a use case beyond "Num does Complex". And since my sinuses are full of the crud that is going around right now, I'm not in a very convincable mood. With the little sense of smell I have left, this smells like INTERCAL's "COME FROM" statement to me, trading a teeny bit of notational convenience in one spot for oversized headaches elsewhere. Most Perl programmers are not interested in type theory, and complexifying the little bit of intentional typing we're introducing with roles will simply cause most people to avoid it like the plague. We might *possibly* get away with reopening roles like we can reopen a class: role Num is also does Complex { method im {...} } but roles are really supposed to be fairly immutable in the Perl 6 scheme of things, so such a declaration would probably have to require that the Num role never have been composed into anything else yet. Or we could say that you can't reopen the Num role; you can only reopen the Num class and mix in the Complex role. That's where it stands at the moment. Larry
Re: Gather/Take and threads
Of course, it's also possible that the flipside is true--that gather/take is just another normal way to set up interthread queueing, if the thread is spawned in the dynamic scope of the gather. Under that view all the subthreads share the outer dynamic scope. Maybe that's saner... Larry
Re: supertyping
TSa wrote: Jonathan Lang wrote: > Assuming that I understand the terminology correctly, I'll go further > and say that one of the big differences between roles and subtypes > (using the terms in their perl 6 contexts) is that roles conceptually > operate on intension sets - everything about them is defined in terms > of their set of capabilities - while subtypes (i.e., objects with > "where" clauses) operate on extension sets - they're defined in terms > of the valid set of instances. You understand the terminology correctly. I'm kind of split of which approach to favor. I can understand Smylers objection that the very existence of these two sets and the contradictory results that set ops produce on them should prevent the usage of set syntax for type construction. OTOH, I know of nothing else that conveys the intent as terse. Agreed. The question is whether you think of a role as a set of methods ("intension set") or as a set of instances ("extension set"). FWIW, it wasn't until this thread that I even registered that the latter possibility existed. Given the above contrast between roles and subtypes, I would really like to keep the extension set mindset limited to subtypes and the intension set mindset limited to roles: a role is an interface (i.e., a set of methods); a type is a set of possible instances. > That's the brittleness: the set of methods that you are permitted to > define in the superrole is restricted to the set of methods in the > role being generalized. But that makes no sense at all because these are the ones which are specialized further down in the subtyping chain. There has to be some extra that the supertype defines for the subtypes. No, there doesn't. For example, let's assume that whoever created the Num role forgot to define an Order role for it. Supertyping would let you create that role for yourself and would ensure that it has the proper relationship with Num. That's what supertyping of roles should be about: extracting subsets of its interface for use elsewhere (which is part of the reason I'm leery about calling it "supertyping"; the important part isn't the greater number of instances that it can have, but instead the simpler interface that it provides). > The write-up that I saw in the original message seems to carry the > implication of the alternative approach (of back-editing the new > methods into the subrole). Note that if you go this route, you really > should allow yourself to define multiple versions of the new method: > one for the superrole, and one for each of the subroles used to define > it. I'd rather not go this route, though. Hmm, looks like this is exactly where I intent to go. If we detach method dispatch from the class that in the end provides the method table for its instances we get the picture that the Complex supertype creates dispatch targets for &im:(Num) and &im:(Complex) and since Num <: Complex dispatch goes to the simple 0 returning role default when called on a Num. One problem with this is that the default return value for Num.im ought to be zero; the default return value for Complex.im ought to be whatever the imaginary component of the number is. So role Complex would need both method im (Complex: ) { return .im } method im (Num: ) { return 0 } That's what I was referring to in terms of having multiple copies of a given method. Well, and of the debate of how to retype an object. I see the .im method in a position to do the right thing when given the invocant and the rhs of the assignment. The thing I don't know is how the syntax looks like. Does one write a STORE block into the method body? And how is the container involved in the process? Synopsis 6, "Lvalue subroutines". > Mind you, once you've defined a supertype, you can freely create new > subtypes of it, and you can add whatever features you want to those > new subtypes, be they lvalue access, new methods, or anything else. This is unquestioned. But my whole point is to get the Num nicely embedded in the Complex without touching the Num implementation. No can do. As soon as you add anything to Complex that isn't in Num, you've changed Num. > IMHO, the correct way to create an unordered Complex role from a Num > role is to use supertyping to remove the ordering capabilities from > Num, and then use subtyping to add "imaginary component" capabilities > to that. Yes, this means that a simple partial ordering check between > Complex and Num will result in a "no relation" result; but that's a > shortcoming of the type-checking system, not the type definition > system. Sorry again, the whole point is to get Num <: Complex in the first place. How else should a subtyping directed dispatch system pick methods? No relation can also be achieved with a unrelated implementation of Complex. I agree that "no relation" is not the desired outcome here - but neither is 'Num <: Complex'. The implication of 'Num <: Complex' is that Num can do anything that C
[perl #41082] [PATCH] Cygwin: conflicting types for _LIB_VERSION
# New Ticket Created by Greg Bacon # Please include the string: [perl #41082] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt3/Ticket/Display.html?id=41082 > Building r16097 on Cygwin fails: [...] src/platform.c config/gen/platform/cygwin/math.c:11: error: conflicting types for '__fdlib_version' /usr/include/math.h:409: error: previous declaration of '__fdlib_version' was here config/gen/platform/cygwin/math.c:11: error: conflicting types for '__fdlib_version' /usr/include/math.h:409: error: previous declaration of '__fdlib_version' was here make: *** [src/platform.o] Error 1 Removing the const qualifier from _LIB_VERSION's definition in config/gen/platform/cygwin/math.h (see attached patch) at least allows miniparrot to build, but running it is another story: [...] gcc -o miniparrot.exe -s -L/usr/local/lib compilers/imcc/main.o \ -L/usr/src/parrot/blib/lib -lparrot -lcrypt -lreadline src/null_config.o Invoking Parrot to generate runtime/parrot/include/config.fpmc --cross your fingers ./miniparrot.exe config_lib.pasm > runtime/parrot/include/config.fpmc make: *** [runtime/parrot/include/config.fpmc] Error 53 Greg Index: config/gen/platform/cygwin/math.c === --- config/gen/platform/cygwin/math.c (revision 16097) +++ config/gen/platform/cygwin/math.c (working copy) @@ -8,7 +8,7 @@ #include -const _LIB_VERSION_TYPE _LIB_VERSION = _IEEE_; +_LIB_VERSION_TYPE _LIB_VERSION = _IEEE_; /* * return true if the Numval has a negative sign.
Re: Gather/Take and threads
On Wed, Dec 06, 2006 at 07:44:39PM -0500, Joe Gottman wrote: : Suppose I have a gather block that spawns several threads, each of which : calls take several times. Obviously, the relative order of items returned : from take in different threads is indeterminate, but is it at least : guaranteed that no object returned from take is lost? Currently gather/take is defined over a dynamic scope, and I think that a different thread is a different dynamic scope (after all, why does it have its own call stack?), so by default you get nothing from another thread, and the other thread would get a "take outside of gather" error. You'd have to set up some kind of queue from the other thread and take the output of that explicitly. The microthreading done by hyperops perhaps doesn't count though. In playing around the other day with a list flattener without explicit recursion, I found that pugs currently returns hyper-takes in random order: pugs> say ~gather { [1,2,[3,4],5]>>.take } 1 2 4 5 3 pugs> say ~gather { [1,2,[3,4],5]>>.take } 2 1 4 5 3 The random order is according to spec, assuming take is allowed at all. But perhaps it shouldn't be allowed, since the threaded side of a hyperop could conceivably become as elaborate as a "real" thread, and maybe we should not make a distinction between micro and macro threads. And it's not like a take can guarantee the order anyway--the hyperop is merely required to return a structure of the same shape, but that does not enforce any order on the actual take calls (as shown above). Only the return values of take end up in the same structure, which is then thrown away. In fact, I'd argue that the value returned by take is exactly the value passed to it, but I don't think that's specced yet. A take is just a side effect performed "en passant" under this view. Then we could write things like: while take foo() {...} @thisbatch = take bar() {...} Larry
Re: supertyping
HaloO, Jonathan Lang wrote: Assuming that I understand the terminology correctly, I'll go further and say that one of the big differences between roles and subtypes (using the terms in their perl 6 contexts) is that roles conceptually operate on intension sets - everything about them is defined in terms of their set of capabilities - while subtypes (i.e., objects with "where" clauses) operate on extension sets - they're defined in terms of the valid set of instances. You understand the terminology correctly. I'm kind of split of which approach to favor. I can understand Smylers objection that the very existence of these two sets and the contradictory results that set ops produce on them should prevent the usage of set syntax for type construction. OTOH, I know of nothing else that conveys the intent as terse. Incidently, I'm using terms like "supertype", "subtype", "superrole", "subrole", etc. strictly due to a lack of a better alternative. "Supertyping" only leads to a larger set of instances because a parameter that asks for the supertype is willing to accept a subtype in its stead. Yes, this is how the argument goes. A supertype constraint allows more instances to pass the test because the set of requirements is smaller. That's the brittleness: the set of methods that you are permitted to define in the superrole is restricted to the set of methods in the role being generalized. But that makes no sense at all because these are the ones which are specialized further down in the subtyping chain. There has to be some extra that the supertype defines for the subtypes. Since Num doesn't include methods re or im, an attempt to include either method in a Complex superrole would be an error according to this approach, or it would involve changing Num to include methods re and im in the alternative approach. Then I did read Luke's post wrongly. Sorry. The write-up that I saw in the original message seems to carry the implication of the alternative approach (of back-editing the new methods into the subrole). Note that if you go this route, you really should allow yourself to define multiple versions of the new method: one for the superrole, and one for each of the subroles used to define it. I'd rather not go this route, though. Hmm, looks like this is exactly where I intent to go. If we detach method dispatch from the class that in the end provides the method table for its instances we get the picture that the Complex supertype creates dispatch targets for &im:(Num) and &im:(Complex) and since Num <: Complex dispatch goes to the simple 0 returning role default when called on a Num. So to support supertyping the lookup process of methods has to scan upwards in the inheritance and role hierarchy instead of just looking into a table in the class the object is blessed into. But I think this is how dispatch works, doesn't it? The lookup result might be cached for efficiency. Look at it according to the normal flow: if you subtype a role with read/write capabilities, the new role cannot have fewer rw capabilities than the role that it's composing has. Reversing this, if a role does not have a particular rw capability, then a superrole cannot add it. This is a variation on the "adding methods to the superrole" debate. Well, and of the debate of how to retype an object. I see the .im method in a position to do the right thing when given the invocant and the rhs of the assignment. The thing I don't know is how the syntax looks like. Does one write a STORE block into the method body? And how is the container involved in the process? Mind you, once you've defined a supertype, you can freely create new subtypes of it, and you can add whatever features you want to those new subtypes, be they lvalue access, new methods, or anything else. This is unquestioned. But my whole point is to get the Num nicely embedded in the Complex without touching the Num implementation. IMHO, the correct way to create an unordered Complex role from a Num role is to use supertyping to remove the ordering capabilities from Num, and then use subtyping to add "imaginary component" capabilities to that. Yes, this means that a simple partial ordering check between Complex and Num will result in a "no relation" result; but that's a shortcoming of the type-checking system, not the type definition system. Sorry again, the whole point is to get Num <: Complex in the first place. How else should a subtyping directed dispatch system pick methods? No relation can also be achieved with a unrelated implementation of Complex. Regards, TSa. --
Re: supertyping
HaloO, Luke Palmer wrote: Woah, that was a terrible passage. Let's try again. If your declaration is "role Foo superdoes Bar". * it is illegal to add a required method to Foo if Bar doesn't already implement it or require it With "required method" you mean an unimplemented method with a {...}, right? * any required method for Foo automatically becomes a required method for Bar, even if it wasn't there before Yes, I wouldn't allow yada methods in the superrole that are not implemented in the subrole it is based on. Lifting a yada method that exists in the subrole is fine of course. Regards, TSa. --
Re: supertyping
Jonathan Lang schreef: > what we need here is something that very > clearly says "the reverse form of 'does'": if A does B, then B ___ A. > Far more important that if it's one word or two is: "what fits most > naturally in the gap?" follows, trails, tracks, enforces, obeys, tolerates, enacts, endorses, passes, ratifies, allows, permits, takes, occupies, lets, shapes, molds, munges, shadows, marks, filters, limits, brands, models, forms, sculpts, figures, profiles, outlines, affects, carves, whittles, cuts, styles, casts -- Groet, Ruud
supertyping
Smylers wrote: Jonathan Lang writes: > For the record, I think that "superdoes" should be spelled "done_by". I think it's unlikely that Larry will incorporate any keywords that contain underscores -- certainly not without at least searching for a single word that sums up the concept in question. Entirely possible. OTOH, what we need here is something that very clearly says "the reverse form of 'does'": if A does B, then B ___ A. Far more important that if it's one word or two is: "what fits most naturally in the gap?" -- Jonathan "Dataweaver" Lang
Re: supertyping
TSa wrote: Secondly I figure you are operating on the extension set a role defines. That is union produces a supertype aka the larger set of instances. This is in accordance to the usual type theory approach. Note that Jonathan operates on the intension set of roles that is union produces a subtype. Assuming that I understand the terminology correctly, I'll go further and say that one of the big differences between roles and subtypes (using the terms in their perl 6 contexts) is that roles conceptually operate on intension sets - everything about them is defined in terms of their set of capabilities - while subtypes (i.e., objects with "where" clauses) operate on extension sets - they're defined in terms of the valid set of instances. Incidently, I'm using terms like "supertype", "subtype", "superrole", "subrole", etc. strictly due to a lack of a better alternative. "Supertyping" only leads to a larger set of instances because a parameter that asks for the supertype is willing to accept a subtype in its stead. > Things work a little differently for required methods. When a > superrole requires a method be implemented, we (the language > designers) have a choise to make: it is illegal if the superrole > requires a method that the subroles don't implement or don't > themselves require, or it simply adds the new method to the required > list of the subroles which don't implement it. I'm inclined to say > the former, even though it seems a little more brittle. I can see no brittleness. The role that is supertyped is already fully defined when the superrole is about to be created. Thus it can be checked if required but unimplemented methods---that is ones with a {...} body---are present. These should be rejected on the rational that the pre-existing code can't retroactively be made to implement the method. That's the brittleness: the set of methods that you are permitted to define in the superrole is restricted to the set of methods in the role being generalized. Since Num doesn't include methods re or im, an attempt to include either method in a Complex superrole would be an error according to this approach, or it would involve changing Num to include methods re and im in the alternative approach. The write-up that I saw in the original message seems to carry the implication of the alternative approach (of back-editing the new methods into the subrole). Note that if you go this route, you really should allow yourself to define multiple versions of the new method: one for the superrole, and one for each of the subroles used to define it. I'd rather not go this route, though. > It means that > when you are implementing a role in a class, all you have to look at > for what you need to do is the role and the roles that it includes; > you don't need to scan the entire source for superroles which > encompass the one you are implementing. That is the user-friendly way > to put it, but there is an analogous argument for independent > modularity (you don't want the definition of a new superrole to > invalidate objects that already exist). Well spoken. And agreed. > Things get a little tricky when you think about "does" and "superdoes" > together: > >role Foo does Bar superdoes Baz {...} > > What does that mean? Okay, Foo is a subset of Bar, and a superset of > Baz. Already by simply declaring this we have mandated that "Baz does > Bar". If Baz doesn't already conform to the interface of Bar, Foo > better fill in the gaps for it. Sorry, but no. If Baz doesn't already conform to the interface of Bar, you're dead in the water. "Filling in the gaps" amounts to changing Baz, which is not in Foo's purview. In the thread 'signature subtyping and role merging' I have argued the need of merging method signatures that come in from different superroles. This is less of a problem when creating superroles because one can drop the method from the interface and maintain the subtyping relation. So filling in the gaps is a hard task in general. I mean in your example Foo has to define all methods required by Bar so that Baz has at least the default provided by Foo. The gap between Baz and Bar might also contain unresolvable name clashes that are of course no problem as long as Bar and Baz are unrelated. This is why I think that having both "does" and "done_by" declarations in a role definition is a mistake: the whole thing becomes a cryptic mess far too quickly. A thing that is still unclear to me is how the issue of the supertype intercepting lvalue uses of its methods is resolved. Preferably in a declarative style. I mean a simple 'is rw' trait will hardly do because you have to return a complete object of which only an attribute is written to. The former subtype value has to be made available for the lvalue method for constructing the new supertype lvalue. Look at it according to the normal flow: if you subtype a role with read/write capabilities, the new role cannot have fewer rw capabili
Re: supertyping
TSa schreef: > Smylers: >> Jonathan Lang: >>> For the record, I think that "superdoes" should be spelled >>> "done_by". >> >> I think it's unlikely that Larry will incorporate any keywords that >> contain underscores -- certainly not without at least searching for a >> single word that sums up the concept in question. > > Starting from 'does' that means 'machen' in German and then > reversing it to 'vermachen' and looking that up in a dictionary > I end up at 'bequeath'. So it might read > >role Foo bequeaths Bar {...} > > But I'm non-native after all. delegated_to, performed_by, but why not just "by"? (role Vigilante by Charles Bronson) -- Groet, Ruud
Re: supertyping
HaloO, Smylers wrote: Jonathan Lang writes: For the record, I think that "superdoes" should be spelled "done_by". I think it's unlikely that Larry will incorporate any keywords that contain underscores -- certainly not without at least searching for a single word that sums up the concept in question. Starting from 'does' that means 'machen' in German and then reversing it to 'vermachen' and looking that up in a dictionary I end up at 'bequeath'. So it might read role Foo bequeaths Bar {...} But I'm non-native after all. Regards, TSa. --
Re: supertyping
HaloO Luke, good to hear from you again! you wrote: I'd tend to agree. This is an important feature of an object system for me, And I hope for the rest of @Larry, too. There is a nice duality in this specification. When you say: role Foo does Bar does Baz {...} You are saying Foo = Bar (*) Baz (*) ...; # intersection of Bar, Baz, and the following spec When you say: role Foo superdoes Bar superdoes Baz {...} You are saying Foo = Bar (+) Baz (+) ...; # union of Bar, Baz, and the following spec First of all it strikes me as odd that you have union as (+) and intersection as (*). Is that the official definition? I would like to see (|) and (&) because of the duality to the logical ops. Besides the fact that (+) could mean Bag addition and (*) the cartesian product. Secondly I figure you are operating on the extension set a role defines. That is union produces a supertype aka the larger set of instances. This is in accordance to the usual type theory approach. Note that Jonathan operates on the intension set of roles that is union produces a subtype. Things work a little differently for required methods. When a superrole requires a method be implemented, we (the language designers) have a choise to make: it is illegal if the superrole requires a method that the subroles don't implement or don't themselves require, or it simply adds the new method to the required list of the subroles which don't implement it. I'm inclined to say the former, even though it seems a little more brittle. I can see no brittleness. The role that is supertyped is already fully defined when the superrole is about to be created. Thus it can be checked if required but unimplemented methods---that is ones with a {...} body---are present. These should be rejected on the rational that the pre-existing code can't retroactively be made to implement the method. It means that when you are implementing a role in a class, all you have to look at for what you need to do is the role and the roles that it includes; you don't need to scan the entire source for superroles which encompass the one you are implementing. That is the user-friendly way to put it, but there is an analogous argument for independent modularity (you don't want the definition of a new superrole to invalidate objects that already exist). Well spoken. Things get a little tricky when you think about "does" and "superdoes" together: role Foo does Bar superdoes Baz {...} What does that mean? Okay, Foo is a subset of Bar, and a superset of Baz. Already by simply declaring this we have mandated that "Baz does Bar". If Baz doesn't already conform to the interface of Bar, Foo better fill in the gaps for it. As for the ..., anything which conforms to it and Bar ought to be in Foo. So I think the equation ends up: Foo = Bar (*) (Baz (+) ...); In words, you are a Foo if you are a Bar and you either are a Baz or conform to my interface. In the thread 'signature subtyping and role merging' I have argued the need of merging method signatures that come in from different superroles. This is less of a problem when creating superroles because one can drop the method from the interface and maintain the subtyping relation. So filling in the gaps is a hard task in general. I mean in your example Foo has to define all methods required by Bar so that Baz has at least the default provided by Foo. The gap between Baz and Bar might also contain unresolvable name clashes that are of course no problem as long as Bar and Baz are unrelated. Whew, I was really only going to reply with an "I dig it" sort of response, but I seem to have written some sort of complete theory. :-) I missed you in the 'set operations for roles' thread. Your theory is basically what was discussed there. Unfortunately nothing made it into the synopsis except the dropping of '|' as the separator for pre-composed roles. Actually not even the set operators are in S03. A thing that is still unclear to me is how the issue of the supertype intercepting lvalue uses of its methods is resolved. Preferably in a declarative style. I mean a simple 'is rw' trait will hardly do because you have to return a complete object of which only an attribute is written to. The former subtype value has to be made available for the lvalue method for constructing the new supertype lvalue. Regards, TSa. --
Re: supertyping
Jonathan Lang writes: > For the record, I think that "superdoes" should be spelled "done_by". I think it's unlikely that Larry will incorporate any keywords that contain underscores -- certainly not without at least searching for a single word that sums up the concept in question. Smylers
supertyping
Luke Palmer wrote: When you say: role Foo superdoes Bar superdoes Baz {...} You are saying Foo = Bar (+) Baz (+) ...; # union of Bar, Baz, and the following spec For the record, I think that "superdoes" should be spelled "done_by". It may seem like that should be Foo = (Bar (+) Baz) (*) ...; (indeed, I thought that for a while and then corrected myself). But if anything that is a Bar is a Foo, anything that is a Baz is a Foo, and some other stuff is also a Foo (this being the important case), then that should clearly be a union. Note that in your usage of the set operations, "Bar (+) Baz" requires "Bar.^methods (*) Baz.^methods" and "Bar (*) Baz" requires "Bar.^methods (+) Baz.^methods". This means that the spec that follows would act to further limit the methods that end up in Foo, such that only methods that appear in Bar, Baz, _and_ the spec would end up in Foo. (As a secondary issue, your definition of "Bar (+) Baz" strikes me as counterintuitive; but maybe that's because I tend to view roles as sets of methods.) Things work a little differently for required methods. When a superrole requires a method be implemented, we (the language designers) have a choice to make: it is illegal if the superrole requires a method that the subroles don't implement or don't themselves require, or it simply adds the new method to the required list of the subroles which don't implement it. I'm inclined to say the former, even though it seems a little more brittle. I agree with your inclination; but bear in mind that this would make it illegal to define Complex as a superrole of Num, since Complex has methods that Num doesn't have. Also bear in mind that if Complex is a superrole of Num, a parameter that asks for a Num should by all rights reject a Complex that's handed to it. I agree with the idea of being able to define superroles (for lack of a better name); my problems lie entirely with the proposed implementation of the concept. I'll reiterate my alternative: When using set operations with roles, treat the roles as sets of methods. Each set operation defines an anonymous role with the resulting set of methods; as with any other anonymous thing, it can be bound to a name. In addition, a few of the set operations establish .does() relationships between the new role and the roles used to create it: role C ::= A (+) B # C.does(A) and C.does(B) role D::= A (*) B # A.does(D) and B.does(D) role E ::= A (-) B # A.does(E) and so on. In particular, these lines would be equivalent to role C does A does B {} role D done_by A done_by B {} role E done_by A except B {} ...with the added benefit that you don't have any confusion as to how "does", "done_by", "except", etc. interact with each other or with the new spec. Further, grouping of set operations makes it easy to define "staged composition": (A (+) B) (*) C would mean "compose an anonymous role as the union of A and B, and then compose an anonymous role as the intersection of that and C". Among other things, this would allow method definitions in C to override those of the anonymous union. -- Jonathan "Dataweaver" Lang
Re: Introspection and list question
On Tue, Dec 12, 2006 at 02:19:46PM -0800, Ovid wrote: > First, how do I do introspection in Pugs? CPAN's Perl6::Bible hasn't > been updated in a while, but the various ways to get a list of methods > (from > http://search.cpan.org/dist/Perl6-Bible/lib/Perl6/Bible/S12.pod#Introspection > or http://tinyurl.com/yxukar) don't appear to work. They all throw > syntax errors or "No compatible subroutine" errors. In general you're better off looking at http://spec.pugscode.org/ for more updated synopses, but in regard to introspection, the APIs aren't well specced yet. > Also, I'm having trouble with problem 7 in > http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html > or http://tinyurl.com/tt9e7. Basically, it's flattening nested lists > and I'm embarrassed to admit that I can't figure this out in Perl6. > Thoughts? I've been reading synopses and grepping through Pugs, but to > no avail. L stipulates the results of a gather are flattened to a lazy list. I'm not sure how far that flattenning goes, but one of these should do the trick, I think (Pugs does not yet implement gather/take): sub flatten1 (@list) { gather for @list { take $_; } } sub flatten2 (@list) { gather for @list { take $_.does("List") ?? flatten2 $_ !! $_; } } -- Gaal Yahas <[EMAIL PROTECTED]> http://gaal.livejournal.com/