Re: Bag / Set ideas - making them substitutable for Arrays makes them more useful
On Tuesday, 9. November 2010 01:45:52 Mason Kramer wrote: I have to disagree here. Arrays and Hashes may be about storage (I don't think they are, though, since you can change the (storage) implemenation of an Array or Hash via its metaclass and it can still remain an Array or Hash). What I mean with storage is that you put some data into a numbered slot in an array and a keyed slot into a hash. With the same index or key you can retrieve your data at any time. This is the case irrespective of the underlying implementation. A set is not about storage in this sense, because there is no way of retrieving an element. The only operation is a membership test which is of boolean nature like number comparison. The most important part of the @ sigil, and the reason I preferred it over $, is that @ flattens (moritz++'s word), when used in a list context such as for @blah, map {...}, @blah. I wonder if it is not possible to bind flattening to Iterable. This of course has the drawback that it is not syntactically distinguished. But doesn't my $x = (1,2,3); my $y = map {$^x * $^x}, $x; result in $y containing the list (1,4,9)? And if $x happens to be a scalar isn't it just squared? In the end we just need map:( closure, Set $data -- Set) as an overload. Or perhaps map:( closure, Iterable ::T $data -- T). Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Smart match isn't on Bool
HaloO, On Monday, 2. August 2010 20:02:40 Mark J. Reed wrote: On Sun, Aug 1, 2010 at 6:02 PM, Jonathan Worthington jonat...@jnthn.net wrote: No, given-when is smart-matching. The RHS of a smart-match decides what happens. If you do True ~~ 1 then that's 1.ACCEPTS(True) which is going to do +True and thus match. OK, but what about 0 ~~ True? That's what started this thread, extricated from the complicating trappings of given/when. Right now, (anything ~~ True) is true, and IMHO that's a misfeature; it's at least surprising. I'd expect (anything ~~ True) to be synonymous with ?(anything): true only if the LHS boolifies to true. By the same token, (anything ~~ False) would be synonymous with !?(anything). Note also that ($anything ~~ foo()) just throws away $anything. I would opt for a regularization of the smart match table. First of all the generic scalar rule should coerce the LHS to the type of the RHS and then use === on them. This is how the Any ~~ Set case is specced. The cases Stringy and Numeric fall out naturally from this definition. The Bool case should become a special case just like Stringy and Numeric. The auto-invocation of Callable is a good thing but the fact that the return value is not subject to the generic scalar case is a misfeature. That is we loose: given 42 { when foo() {...} when bar() {...} when baz() {...} } which could mean to execute that block whose controlling sub complies with the given and not the one that returns True first. Note that this style is particularly usefull with given True. But then we sort of have the coercing the wrong way around because the idea is to check the return value in boolean context not coercing the True to whatever the type of the return value is. BTW, how is the case with a unary sub written? Could someone please give a rational for the interspersing technique given $anything { when $one {...} when two() {...} when $three {...} } where two() returning a true value prevents the case $three. And if it is considered usefull I support the whenever proposal because different things should look different. BTW, would given $anything { when $one {...} if two() {...} else { when $three {...} } } still smart match $anything with $three? Or is the topic the return value of two() at that point? Regards TSa -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Smart match isn't on Bool
HaloO, On Saturday, 31. July 2010 20:47:49 Patrick R. Michaud wrote: On Sat, Jul 31, 2010 at 10:56:47AM -0600, David Green wrote: It's not unreasonable, especially if that's what you expect. But it's even more reasonable to expect this to work: given $something { when True { say That's the truth! } when 42 { say Good answer! } when viaduct { say You guessed the secret word! } } I'm not so sure about this. There's an argument to be made that the Cwhen 42 and Cwhen viaduct cases should never be reachable, since both C42 and Cviaduct are considered true values... Sorry, I don't understand this possible argument. Isn't the intent of a given/when to select one alternative by means of the given? This is what a switch statement does. Perl 6 allows non-constants after when, so it's reasonable to have the constant in the given and to see e.g. which function returns it. Of course the first actually doing this determines the switch. ... unless you want Cwhen True to do a value-and-type check, in which case it doesn't exactly follow the pattern for smartmatching of the other builtin types (which only check value equivalence, not type equivalence). This is true only if you want to distinguish 1 and True which are the same value. But 42 should be distinct from this. Same goes for viaduct. So these three should be a valid disjoint set of choices that can be made given $something. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Smart match isn't on Bool
HaloO, On Saturday, 31. July 2010 18:56:47 David Green wrote: On 2010-07-31, at 1:33 am, Moritz Lenz wrote: sub test() { True }; given 0 { when test() { say OH NOEZ } } I don't think it's unreasonable to expect the output to be OH NOEZ. How does this relate the given to the when? If I get you right the given is completely ignored and the truth of test() gives OH NOEZ. I think the given must determine the result. It's not unreasonable, especially if that's what you expect. But it's even more reasonable to expect this to work: given $something { when True { say That's the truth! } when 42 { say Good answer! } when viaduct { say You guessed the secret word! } } Here I expect the $something to *select* one of the alternatives. It can't be that a literal True ignores the given and just executes the block. In both these examples, the intent is fairly clear from the context. It's easier to forget that Bools behave differently from other types when you only have some variable that could be any type: if $guess ~~ $answer { say Correct! } # hope your question wasn't T/F! Maybe we can't please everyone, but we can at least try not to displease anyone. Perl is awfully clever at keeping your eaten ponies, and there is a way we can have both the helpful syntax and the consistent one: given $who-knows-what { when True { say It's a true thing! } when 42 { say It's numbery! } whenever timeout() { say Who cares what you say, time's up! } whenever $override { say Whatever, switching to automatic override } } Am I getting your intention to be that when honors the given and whenever just checks truth? Couldn't we use if for this? That would avoid the new keyword. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Suggested magic for a .. b
On Wednesday, 28. July 2010 05:12:52 Michael Zedeler wrote: Writing ($a .. $b).reverse doesn't make any sense if the result were a new Range, since Ranges should then only be used for inclusion tests (so swapping endpoints doesn't have any meaningful interpretation), but applying .reverse could result in a coercion to Sequence. Swapping the endpoints could mean swapping inside test to outside test. The only thing that is needed is to swap from to ||: $a .. $b # means $a = $_ $_ = $b if $a $b $b .. $a # means $b = $_ || $_ = $a if $a $b Regards TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Type system for Perl 6
HaloO Mr Castagna On Friday, 5. February 2010 16:43:26 you wrote: I see I'm going out of the scope of this list. I apologize for spamming, but please continue to post here or send me by PM every information about Perls 6 types. I'm delighted to have you interested in Perl 6. I know your book and articles and have argued for a type system of Perl 6 here on the list for quite a while. Unfortunately I'm not able to implement one for Parrot or so. But if you are willing to port the CDuce code this is a great thing! There is no formally defined subtype relation or rules for subsumption. A type is called narrower without details what that means. And the odering in dispatch is not a type lattice as in Cecil but a topological ordering. Again I've no clue what that means. It is possible for one role to do another as in role A does B {...} and all objects that do A are also B doers. So one could infer that we have A : B. But note that this subtype relation is not enforced in the body of the role or in the class it is composed into. The spec says nothing about class inheritance and type narrowness. Parametric roles are covariant on their type parameter irrespective of its use. E.g. you can declare a read/write attribute of that type. Regards TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Type system for Perl 6
HaloO Mr Castagna, On Friday, 5. February 2010 23:13:25 you wrote: Actually I noticed an old post you did on this list 5 years ago. It contained the following drawing Yeah it's a long time. And I've sort of lost interest in type theory. But then I tried to persuade the list of a sophisticated type system. But since I couldn't hack it myself nothing has happend. And Audrey Tang is gone. He/She was a big fan of a type system as well and hacking Pugs in Haskell. A|B lub (lowest upper bound) / \ / \ A 0 B / \ / \ / \ / \ / AB \ glb (greatest lower bound) / 1 / \ 2 \ / / 3 \ \ and it is the only reference I found to intersection types (since AB is the intersection of A and B (if you consider a class type as the set of all its instances) that is it contains all objects that are instance both of A and of B. Is this notation (or the general idea of intersection types) has been abandoned since then (I was not able to find it in the synopsis) Yes, Larry never liked the idea of a type lattice and intermediate types like A|B or AB. The syntax is now used to simply mean doing A or B. I've also proposed to have a constraint language in the where clause of subset declarations that is usable for type checking. But the where clause is now only a closure that is called when needed. So { $_ 10 } is not a subtype of { $_ 20 }. So no predicate dispatch either. Someone should explain the dispatch algorithm to you. I don't remember exactly how the voting there works. This would explain what type narrowness in the spec means. Regards TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: How does List.map: { .say } work?
HaloO, On Tuesday, 3. November 2009 17:13:22 Carl Mäsak wrote: That would make statement modifier for loops less useful. For those, there's nowhere to put the lambda arrow. ++$_ for @things; I think this is resolved with the is ref binding which implies that the thingy that is bound to $_ is a cell accessor of an array that provides a STORE method. BTW, the situation of STORE and FETCH methods in classes is kind of funny. While an object is stored in a container the respective methods of the container are called. Only in an is ref binding assignment affects the object directly. That is, in the scope of the binding the object goes kind of naked. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Int/Rat max precision (was Re: r28882 - docs/Perl6/Spec)
HaloO, On Friday, 23. October 2009 02:27:00 Darren Duncan wrote: Thinking further, my interpretation of what you said above is that the Rational role is now basically saying that a number is represented in terms of numerator/denominator and that certain operators are supported, but now it is sounding like the details of whether the operators will produce Rational results or Num results is now determinable on a per-class basis, so we may end up working with types like Rat32, Rat64, BigRat (just this one being unlimited precision), etc after all. I believe that the thing people that don't care about the precision should use in sigs and variable declarations is the Rat role. That is I think that Rat should be the role that is currently named Rational. More specific instantiations of that role are then written in my proposed type signature invocant slot syntax as Rat[Rat64:]. Note that this is no problem because e.g. 'my Rat $x = 3/4' doesn't require Rat to be an instantiable class. Actually the class that implements Rat is chosen by the compiler to be e.g. Rat64. Then there need to be installation time defaults, command line switches and lexical pragmas to influence this choice. The second thing that needs to be hookable to different classes is the handling of overflow and underflow of e.g. Rat64 to either upgrade to BigRat or wrap the offending value back into Rat64 or switch over to Num. Then there is the problem of mixed precision cases etc. Presumably then with the Integer role we'll also have types like Int32, Int64, BigInt that do the role and also convert to a Num when their bounds are exceeded? Does that sound about right? Yes. I think there should be an Int role and classes implementing it. The Int role must be a subrole of Rat. E.g. it adds the bit manipulation operators which are difficult to define for rationals if not outright meaningless. This subroling is needed for calling Rat routines with an Int, of course. From a Huffman POV the roles for generic integers and rationals must be short, so the Numeric and Rational roles in S32 are going in the wrong direction. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: unusual invocants
HaloO, On Sunday, 25. October 2009 01:38:21 Martin D Kealey wrote: Sounds like going back to static typing -- which does sometimes have some advantages. Well, you can also consider it dynamic. The important point is that it is a constraint on allowed types e.g. in the sig of a sub or on a variable. In my proposal they are handled through conversion on class level. One way to implement at would be to use proxy objects, which only do one of the roles (by passing them through to the appropriate methods on the original object). Do I understand you right that you propose to have a Dogwood class and two auxiliary proxy classes for the Dog and Wood roles? Isn't that too much effort? OTOH, a conversion routine could indeed return such a proxy if the original shall be kept unchanged. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: role invocant slot in type sig (was: unusual invocants)
HaloO, On Thursday, 22. October 2009 20:58:15 I wrote: The class Dogwood however might be written as class Dogwood does Dog[Dogwood:] does Wood[Dogwood:] { method Dog {...} method Wood {...} method bark {...} } On #perl there was the question if any type could be put into the brackets, e.g. 'class C does B[A:]'. But this is a semantic error like using a role in an is clause or a class in a does clause. However I see this as a weakness of my proposal. So we could actually use 'class Dogwood does Dog:self does Wood:self' as alternative. This is hopefully closer to the point. where the explicit invocant type prevents the creation of the subclass relations between Dogwood and Dog and Wood. So in an environment which requests plain Dog a Dogwood instance is only applicable after the call of the coercion routine which could setup things so that Dog::bark is dispatched to. Environments that want Dogwood::bark need to explicitly coerce Dogwood instances to Dog[Dogwood:] which actually is a no-op. But then other non-Dogwood Dog doers are excluded unless they have a Dogwood coercion routine. Or they use the Dogwood class directly. While pondering the consequences of my proposal it occurred to me that the use of a juxtaposed type Dog Wood should not mean Dog[Dog:] Wood[Wood:]. That is each with its role as invocant, because this would force an ambiguous type conversion on Dogwood. So I change the proposal such that a juxtaposition means Dog[::T:] Wood[T] which nicely gives the Dogwood implementation of bark as requested by the two roles. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
role invocant slot in type sig (was: unusual invocants)
HaloO, On Thursday, 22. October 2009 18:31:16 I wrote: The invocant slot of the role signature is sort of implied in the spec already! I also like this because a type in Perl 6 is then always written as SomeRole[SomeClass:]. Classes without explicit roles are Any[SomeClass:] and untyped is Any[Object:]. Note that a class C doing multiple roles spawns several types R1[C:], R2[C:], etc and the class name is a short form of their juxtaposition. Here is an improvement of the concept that also allows to settle the Dogwood case in the Dogwood class. The change is that plain Foo does not mean Foo[Object:] but denotes the F-bound fixpoint type Foo[Foo:]. A class Bar doing Foo still creates the type Foo[Bar:] but also enters the subclass relation between Bar and Foo so that Foo[Bar:] : Foo[Foo:] makes Bar instances applicable where Foo is required. The class Dogwood however might be written as class Dogwood does Dog[Dogwood:] does Wood[Dogwood:] { method Dog {...} method Wood {...} method bark {...} } where the explicit invocant type prevents the creation of the subclass relations between Dogwood and Dog and Wood. So in an environment which requests plain Dog a Dogwood instance is only applicable after the call of the coercion routine which could setup things so that Dog::bark is dispatched to. Environments that want Dogwood::bark need to explicitly coerce Dogwood instances to Dog[Dogwood:] which actually is a no-op. But then other non-Dogwood Dog doers are excluded unless they have a Dogwood coercion routine. Or they use the Dogwood class directly. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: unusual invocants
HaloO, On Wednesday, 21. October 2009 12:40:06 Mark J. Reed wrote: Rather than disallow the composition, I'd say that any class, role, or object that does both roles must override the method in question. The problem that Ovid posed needs to be resolved in the dispatch tables seen in certain methods of a class. So the solution is not overriding the offending method x but the calls to it in methods foo and bar! The interesting thing is that you have to dig that information out from the source of the roles T1 and T2. I doubt that a programmer making the dependency mistake also documents it ;) I've never seen a call graph of a library in any documentation. Which takes us back to Jon's branch of the thread: it would be nice to be able to declare such an override in a general way that will apply to any such composition that doesn't otherwise override it locally. But what should that declaration look like? Here is a direct syntax for the freeze feature of the paper: class C does T1 does T2 { freeze T1::x for foo; freeze T2::x for bar; method x {...} # for all other methods } The implementation is strait forward: on entry to foo and bar the dispatch table of the invocant is temporarily patched to contain the right x. After the call the original is restored. Heretic question: would it make sense to have a method registry for roles in CPAN? At least for a set of 'standard' modules that then allow arbitrary role combinations without conflict. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: unusual invocants
HaloO, On Tuesday, 20. October 2009 18:35:36 David Green wrote: So what the OP wants to do is declare a method that is available on all those invocants - and only those invocatnts - which do all of roles X, Y, and Z. Granted, you can declare a new role XandYandZ that does X, Y, and Z, and define the method there, but that won't work on $foo unless you declare explicitly '$foo does XandYandZ' . The goal is to have the method show up no matter how $foo comes to do all three roles. Right. I have difficulty seeing the need for a method here. The distinguishing feature of a method is the access to the private data of an object that can hardly be granted by doing the three roles X, Y and Z. After all there's no unique implementation of these roles! Perl 6 is a hybrid language as far as dispatch is concerned. There is the class based method dispatch that I call slot dispatch because the usual implementation is to have the objects carry a ref to a slot table. The other dispatch is the type based MMD. Unfortunately this also goes by the name of method. This is because other languages use classes as types and conflate the two dispatch regimes that Perl 6 clearly separates. There used to be fail-over from class dispatch to MMD but this didn't work---even though I forgot what the exact problems were ;) So in the end the only problem is that the calling conventions of $object.method versus method($object) are not interchangeable. But it makes the priority clear. In the $object.method case the object is the primary concept. We think of it as the object doing something. In many cases to its own state. In the method($object) case the method is the primary concept. The object influences how it is done or what is the output. The method can of course call mutating methods on the object but this is a secondary concern. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Freezing role methods
HaloO, On Wednesday, 14. October 2009 12:18:30 Ovid wrote: You *could* (this wasn't explained in the paper) extract those methods into C::x(), check your callers and dispatch as appropriate, but that would get very problematic, particularly with roles composed of other roles. I consider the dependence of T1 and T2 on their respective public method implementation a design flaw of these methods. They should each have a private service routine that in turn is called by the public x method. But here is how this can be worked around in C: role T1 { method foo { self.x } method x { say T1 } } role T2 { method bar { self.x } method x { say T2 } } class C does T1 does T2 { enum Source other from_foo from_bar has Source $!source = other; method foo { self!source = from_foo; T1::foo } method bar { self!source = from_bar; T2::bar } method x { given self!source { when from_foo { T1::x; self!source = other } when from_bar { T2::x; self!source = other } default { say C } } } } I admit that this is clumsy. So we need an automatic procedure and some nice syntax. But it looks to me as code analysis of T1 and T2 is needed to generate the wrappers in C. One point I don't like in the paper is that freezing methods can be used to erase methods from a role. This is diametrically opposed to the intent of roles to make a guaranty to provide an interface. Regards TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Synopsis 02: Range objects
On Thursday, 27. August 2009 23:58:51 Jon Lang wrote: It might also be nice to have a stringifying version; perhaps 'be', using the same everything's an acronym naming convention used by other stringifying operators (e.g., 'lt' is less than, 'le' is 'less than or equal to', 'leg' is less than, equal to, greater than) - in this case, 'be' would be 'beginning to end'. At the very least, this would avoid the inevitable questions about why there isn't a stringifying version. :) That said, it may not be good for much more than that. Yeah, sometimes orthogonality of features is too much of a good thing! Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: On Sets (Was: Re: On Junctions)
HaloO, On Friday, 27. March 2009 12:57:49 Daniel Ruoso wrote: 1 - multi infix:+(Set $set, Num $a) This would return another set, with each value of $set summed with $a. I think that this mixed case should numify the set to the number of elements to comply with array semantics. infix:+ should remain a numeric operator and numify other operant types. This operator orientation is a strong feature of Perl 6 and should not be diluted by overloads with non-numeric meanings. 2 - multi infix:+(Set $a, Set $b) This would return another set, with $a.values X+ $b.values, already removing duplicated values, as expected from a set. Even the homogeneous case should adhere to numeric semantics. Set operations are with parens. So disjoint union creation is (+). We could try to get a meta parens so that (X+) is conceivably auto-generated. OTOH it collides with (+) visually. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Logo considerations
On Tuesday, 24. March 2009 05:47:12 Darren Duncan wrote: If you're going for sciencey or mathey illustrations, then I think its important to include something that speaks quantum physics in there, since quantum superpositions aka Junctions are one of the big central user features that Perl 6 provides which is relatively new to languages in general. The concept of superimposed shapes is very well done in the Trisquirclehedron. See http://lucacardelli.name/Topics/TheoryOfObjects/ObjectSubject.html Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: a junction or not
HaloO, On Tuesday, 17. March 2009 10:25:27 David Green wrote: That is, it would return a Junction of Str, not a Str. So the question is how to get something that returns an expression to the effect of: 'any(' ~ $choice.eigenstates.«perl.join(',') ~ ')' say $choice.perl ...which will ultimately call (junction-of-.perl's).Str, and Str(Junction:) is what produces the any(XXX) string. [Unless it ends up being implemented some other way, of course!] Note that this contradicts Larry's statement that .perl autothreads. I think it can't autothread because we expect it to put the junction constructor in front of the values or the right operator as infix. So .perl is junction aware! But it threads the .perl method through the eigenstates, of course. The other question is: given $choice as defined above, how do I find out which type of junction it is? I guess really Junctions need two public methods: .eigenstates for the values, and, er, .eigenop(?!) to return how they're joined -- I'm thinking it would return a code ref, i.e. any, all, etc. A simple solution is to have subtypes of Junction like AnyJunction, AllJunction, OneJunction and NoneJunction or perhaps like Junction::Any, Junction::All, Junction::One and Junction::None. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Range and continuous intervals
On Friday, 27. February 2009 07:42:17 Darren Duncan wrote: I was thinking that Perl 6 ought to have a generic interval type that is conceptually like Range, in that it is defined using a pair of values of an ordered type and includes all the values between those, but unlike Range that type is not expected to have discrete consecutive values that can be iterated over. Hmm, it might not be a bad idea to make Interval a subtype of Range and allow for iteration if that is requested. This allows an Interval where Range is expected. The benefit of a dedicated Interval type comes from supporting set operations (), (|) etc. which are still unmentioned in S03. BTW, what does (1..^5).max return? I think it should be 4 because this is the last value in the Range. Only in 4.7 ~~ 1..^5 does the five matter. How does ~~ retrieve that information? For open intervals the .min and .max methods should return the bound outside. Or better, we should introduce infimum and supremum as .inf and .sup respectively. I'm thinking of a Range-alike that one could use with Rat|Num or Instant etc, and not just Int etc. There would be operators to test membership of a value in the interval, and set-like operators to compare or combine intervals, such as is_inside, is_subset, is_overlap, union, intersection, etc. Such an interval would be what you use for inexact matching and would be the result of a ± infix operator or % postfix operator. Also, as Range has a .. constructor, this other type should have something. Since the Interval type shall be an addition to the Set subsystem I propose the (..) Interval creation operator together with the open versions. Admittedly that leaves (^..^) at a lengthy six chars. But Jon's proposal of setting the by to zero isn't any shorter. Note that the open versions are more important for Interval than they are for Range because for Range you can always write it without ^ at the ends. Barring a better name coming along, I suggest calling the type Interval, and it would be immutable. The only other name that comes to mind is RangeSet. But I prefer Interval because this is the name of the concept in math. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: min= (from Rakudo Built-ins Can Now Be Written In Perl 6)
On Tuesday, 24. February 2009 07:30:05 Carl Mäsak wrote: my $foo is limited(100..200); $foo = 5; # really does $foo = 100 Sounds like a good idea for a CPAN module. You can already do something similar with the subset keyword, though: subset Percentage of Int where { 0 = $^perc = 100 }; sub set_percentage(Percentage $perc is rw, Int $value) { try { return $perc = $value; CATCH { return $perc = 0 if $value 0; return $perc = 100 } } }; my Percentage $p; say set_percentage($p, 50); say set_percentage($p, 101) I would use a parametric role to implement that: role Limited[Order ::Type, Order $lower, Order $upper] { multi sub infix:= (Limited $lhs is rw, Type $rhs -- Type) { if $rhs before $lower { $lhs.STORE($lower) } elsif $rhs after $upper { $lhs.STORE($upper) } else { $lhs.STORE($rhs) } return $rhs; # provide original for outer scope } } my Limited[Int,0,100] $p; $p = 50; # assigns 50 $p = 101; # assigns 100 This is an interesting example of a role that can be instanciated without a class unless one regards the generated multi target an instance of a code class. I used STORE to avoid an infinite recursion in dispatch of infix:=. I could also have called infix:=:(Type is rw, Type -- Type) explicitly. This is necessary if it is overloaded as well. I'm unsure if parametric roles work like that, especially the use of Limited inside the sub. This role should be an easy candidate for inline expansion by the compiler. Also the 'is rw' on the first parameter enforces an exact match so there's no need for dynamic dispatch. I assume that an 'is rw' actually dispatches on the declared container type of the lhs. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Comparing inexact values (was Re: Temporal changes)
On Tuesday, 24. February 2009 17:59:31 Larry Wall wrote: So it might be better as a (very tight?) operator, regardless of the spelling: $x ~~ $y within $epsilon This is a pretty add-on to smartmatch but I still think we are wasting a valueable slot in the smartmatch table by making numeric $x ~~ $y simply mean $x == $y. What is the benefit? Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: References to parts of declared packages
On Friday, 13. February 2009 20:30:24 Larry Wall wrote: While taking a shower I refined the design somewhat in my head, thinking about the ambiguities in package names when you're redefining. By my previous message, it's not clear whether the intent of multi package Foo::Bar {...} is to overload an existing package Foo::Bar in some namespace that we search for packages, or to be the prototype of a new Foo::Bar in the current package. In the former case, we should complain if an existing name is not found, but in the latter case we shouldn't. So those cases must be differentiated. Sorry, you lost me. I thought that classes are for implementation and therefore need to allow re-definition in the sense of open classes. But aren't packages/modules just for holding names? As such they always make sure that there is exactly one entity in the scope with a unique name? So I would advocate a clear split between the functionality of packages on the one hand and the implementation orientated classes, roles and subs on the other. The latter have dispatch and overwriting, the former are just for uniqueness of names. I know that the current design involves dispatch to packages but I think that blurs the distinction between packages and classes. If they are all the same anyway then why have the module, package and class keywords? This is a bit too much redundancy for me. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: returning one or several values from a routine
On Tuesday, 6. January 2009 22:01:36 Jon Lang wrote: item($x) # Dwimmey use of item context. IIRC this is the same as $$x, right? Or does that extract the invocant slot without dwimmery? list($x) # Dwimmey use of list context. hash($x) # Dwimmey use of hash context. $x._ # the Capture object's invocant, as an item. How about $x.() here? That looks symmetric to the other postfix operators and should be regarded as a method dispatched on the invocant or some such. $x.[] # the Capture object's positional parameters, as a list. $x.{} # the Capture object's named parameters, as a hash. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: [svn:perl6-synopsis] r14585 - doc/trunk/design/syn
On Wednesday, 1. October 2008 21:54:12 [EMAIL PROTECTED] wrote: If you apply an assignment operator to a protoobject, it is assumed that you are implementing some kind of notional reduction to an accumulator -variable. To that end, the base operator is dropped and a simple -assignment is done instead. Hence you may correctly write: +variable. To that end, the operation is defined in terms +of the corresponding reduction operator, where the protoobject +becomes the operator's identify value. So if you say: + +$x -= 1; + +it is more or less equivalent to: + +$x = [-]() unless defined $x;# 0 for [-]() +$x = $x - 1; + +and $x ends up with -1 in it, as expected. Can't we have that as a general feature of all operators? That is: my ($x, $y); say $x * $y; # prints 1 say $x + $y; # prints 0 It is a cleaver idea to make the operator choose an appropriate value for a Nothing value. Why having that only for meta operators? Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Smooth numeric upgrades?
HaloO, On Sunday, 5. October 2008 04:23:42 Darren Duncan wrote: Note that just as integers are naturally radix independent, the unlimited rationals should be too, and the latter can compactly represent all rationals as a triple of integers corresponding roughly to a (normalized) [mantissa, radix, exponent] triple; with that approach you also get unlimited floats for free, so no reason to make floats an exception where they aren't unlimited where integers and other rationals are; after all, what is a float or scientific notation than just another notation for a rational value literal. I want to stress this last point. We have the three types Int, Rat and Num. What exactly is the purpose of Num? The IEEE formats will be handled by num64 and the like. Is it just there for holding properties? Or does it do some more advanced numeric stuff? Another matter is how to represent irrationals. With IEEE floats which are basically non-uniformly spaced integers imprecession is involved anyway. But sqrt(2) is a ratio of two infinite integers. How is that handled? Here I see a way for Num to shine as a type that also involves lazy approximations. But then we need a way for the programmer to specify how these approximations shall be handled. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: How to define a new value type?
On Sunday, 14. September 2008 16:08:19 Patrick R. Michaud wrote: So, how does one get an object to pretend to be a value type for purposes of assignment? I think a straight forward approach is to overload the assignment operator on the actual types of the lhs and rhs. The dispatch target than clones the value to be stored in the lhs container after being checked against the container's constraint. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: What happened to err operator?
HaloO, On Thursday, 4. September 2008 03:39:20 Larry Wall wrote: Another potential issue is that CATCH doesn't distinguish exceptions coming from the current block from those coming from the subcall to a(). So it could end up returning Failure from the current block when you intended to force return of Failure from a(). Not sure what to do about that... I don't understand this issue. I think we have the fact that *every* operator is at least conceptually dispatched and as such everything in a block is at least one level down in the call chain just as a() as a sub call is. This is why a CATCH block inside the block is so natural to me. If I understand your intention correctly you want to be able to force a thrown exception from a() into a returned value and proceed where this return value is supposed to show up in the current block, right? The simplest solution that comes to my mind is some form of goto to that position. Or is that too inelegant? The point is how the CATCH block knows from which subordinate scope the exception originates. a() proceed: orelse b(); CATCH { ... # make $! into return value goto proceed; } This kind of needs to know the variable the return value of a() is stored into. This is easy if orelse is checking $! anyway. But does it? And is it possible to have labels in the middle of a line as above? Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: arrayref/hashref in spectest suite
On Monday, 18. August 2008 20:38:05 Patrick R. Michaud wrote: I would somewhat expect a reference to be instead handled using a statement like $foo[1] := $bar; Comments and clarifications appreciated. I would also opt for copy semantics whenever = is used for assignment. But it seems to be the case that this is not deep, just like captures are only one level deep readonly. So, I would also expect $foo[1] = \$bar to result in 24. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Some details of function return captures
HaloO, On Saturday, 9. August 2008 01:32:35 John M. Dlugosz wrote: TSa Thomas.Sandlass-at-barco.com |Perl 6| wrote: If such a ReturnCapture could also be preliminary of some kind, then lvalue subs could be lazily resumed when the rvalue comes in. Can you elaborate on that? I don't follow. The fundamental problem with lvalue methods is that some of them want to have control *after* they returned their value. One ugly way to achieve this is how it is usually done in C++ or Java: the rvalue is a parameter of the method. So instead of $obj.foo(1,2) = 3; #1 one writes $obj.foo(1,2,3); #2 which doesn't look like an lvalue method at all. And you can't use it in rvalue context as the former: my $x = $obj.foo(1,2); #3 Here the ReturnCapture collapses right away. But in #1 it could be resumed with rvalue 3. That is the invocation of .foo(1,2) resumes after the statement that produced the ReturnCapture. In the assignable mutators thread I proposed to call that statement 'yield'. To the function it behaves like the declaration of a variable that receives the value that is assigned later. To the outside it is the preliminary rvalue. If no assignment takes place no resumption is made. The new thing here is that one needs to write my $x = |$obj.foo(1,2); #4 to keep the ReturnCapture, and call it later either explicitly $x.resume(3); or implicitly $x = 3; Hope that helps, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
meta_postfix:*
HaloO, I know that the hot phase of the operator discussions are over. But here's a little orthogonalizing idea from my side. The observation is that * can be regarded as repeated addition: 5 * 3 == 5 + 5 + 5 and ** as repeated multiplication. Now imagine having a meta_postfix:* that gives +* as multiplication (perhaps abbreviated as *) and ** as (integer) exponentiation. We can then continue with replication as ~* for strings and ,* for lists thus freeing x and xx as some generic multiplication operators. The meta * also is useful e.g. as (1,2) Z* 3 === (1,1,1),(2,2,2). Also when we apply it to unary postfix as well: $x++* 3 === $x++.++.++ which is useful when $x is of some class with overloaded ++ where the single steps are important. The meta postfix * could also be stacked and tetration falls out naturally as ***. With + as the default case for meta_postfix:* we win the advantage that we have +* and * as multiplication operators with the latter being a special form of the former. But for Vectors +* would automatically yield the scalar multiplication infix:+*:(Vector,Num) when infix:+:(Vector,Vector) is defined as expected. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Rakudo test miscellanea
HaloO, On Thursday, 26. June 2008 18:46:25 Larry Wall wrote: Neither is nor does is quite right here, because the mathematicians have seen fit to confuse representation semantics with value semantics. :) Hmm, but the uppercase types should hide the representation type. IOW, there's only one Int but int8 to int64 or so. Same with Num and num32 to num128 and perhaps num8 and num16 in the OpenGL world. I think what we want is something more like Int as Rat Rat as Num Num as Complex So, how does this auto-coercion interact with dispatch? And how do these in turn interact with generic function/type instanciation? I imagine a first round of dispatch then some well defined second attempt after standard coercions. Note that there might be coercion conflicts if several paths of conversion are available. Then we need some concept of coercion distance that favors more direct paths over longer ones and less lossy ones over lossier ones. The tricky part then becomes the interaction of coercion with dispatch. E.g. if there is an Int arg and two dispatch targets for Rat and Num and two conversions Int as Rat (lossless) and Int as Num (lossy?). OTOH, I regard Complex as a structural type like e.g. Vector or Matrix that is built on top of other numeric types. That is we have Complex[Int] as the Gaussian Integers and Complex[Rat] and Complex[Num] in the same coercive relations as the underlying Rat and Num. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: constraint imperative programming (CIP)
HaloO, On Monday, 16. June 2008 10:03:13 Ovid wrote: --- TSa [EMAIL PROTECTED] wrote: ... why do you think that the way to get at the constraint programming paradigm are the subset type definitions? Because I can't think of any other way to do it :) So I´ll try to come up with some creative thoughts =8() Now it's my turn to say that I can't follow that statement. I hope the asymmetry in standard Perl 6 ´$x = $y´ is obvious. By contrast in constraint programming (CP) ala Oz translated to Perl 6 we have $x = $y; # 1 42 = $y; # 2 say $x; # 3 (prints 42) where line 1 just stores the equality of $x and $y in the constraint store and goes ahead. Line 2 binds 42 to $y directly and by constraint solving to $x as well. That is what I call symmetric and which causes fundamental troubles in implanting CP into imperative Perl 6. Thanks, btw for the ref to the Kaleidoscope paper, it always amazing how many languages I haven´t heard about ;) Now we need a way to express constraint enforcement---called CIP in the paper. My idea is that it naturally belongs to the variable subsystem. I.e. we need declarations that declare constraints between variables. My first attempt is simply sub move_vertical_line (Line $line, Event $event) { constrain $start := $line.start.x, $end := $line.end.x to { always $start == $end; # constraint SOLVE # enforcer { $end = $start; # normal assignment through bound vars } } my Event $motion; while ($motion = get_next_event()) ~~ ButtonMotion { $line.start.x = $motion.x; # $line.end.x is enforced } if $motion ~~ ButtonUp # last event application { $line.start.x = $motion.x; # $line.end.x is enforced } } This is the value constraint from the paper. I would call the other types almost as in the paper: identity, type and structure constraints. A type constraint comes closest to the subset type constraints that are not enforced and hopefully side-effect free. So a global definition might look like constrain PosInt of Int to { always $_ 0; SOLVE { $_ = 1 } } my PosInt $x; $x = -17; # invokes SOLVE block say $x; # prints 1 The SOLVE closure needs beefing up, like e.g. if you have more than one constraint it has to topicalize the constraint somehow: constrain $x, $y, $z to { always $x + $y == $z; SOLVE { when $x changed { $y = $z - $x; } when $y changed { $x = $z - $y; } when $z changed { $x = $Z / 2; } # calls first when } } Comments? -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: fallback semantics of list methods
HaloO, On Saturday, 14. June 2008 18:43:05 Daniel Ruoso wrote: Moritz convinced me that there's actually no real reason to support $nonlist.listmethod I wouldn´t do that either. But I come to that conclusion from the line of thought that it is generally a bad idea to block an Any slot in a multi for a mere casting operation. The whole point of type based dispatch is to name the intended type in the first place. That is, a programmer choosing the item sigil $ in combination with a list operation should be punished with a dispatch error if he doesn´t know for sure that everything he sticks in the variable is a list anyway. Note that the other way around is bloody easy in Perl 6. A @ variable can handle items just fine! I´m aware that this makes me opt for solution three, the dropping of fallback from method to sub dispatch. But I consider that a good thing. They are nicely distinct syntactically, so why mix them semantically? And if we stop, and think for more two seconds, we realise that supporting that could end up having a lot of non-interesting side effects, because an exported sub with the signature :(Any, Str) is most likely to have a lot of false hits. Technically there are no false hits on an Any slot ;) In the case at hand it listifies the item and re-dispatches. IOW, the false hits will be surprises for unaware programmers who get unexpected dispatches silently. BTW, there´s the same problem with stringification of the separator. Combining that with the listification would end up blocking *join:(Any,Any) globally. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Complete type inferencing
HaloO, Autrijus Tang wrote: Yes, I'm aware of Theta's static where clauses, but Perl 6's where clause is much more dynamic and almost always undecidable. I know, but what does that buy the programmer? I see a type system as support of a declarative programming style. Thus the dynamic part of the type system, that is method dispatch and type instanciation, has to play in a frame set by the programmer. This is very similar to regular expressions and grammars. They declare the interpretation of a string/stream of chars/data. The type system goes on from there to watch over constraints while this data is processed. In Litvinov's paper, where clauses are determinisitic at compile time, as a way to encode structural subtyping (aka duck typing). Huch, who has coined 'duck typing'? I never heard that before. The important difference is that the .can() call in Perl 6 would be a runtime call. It has to be that way, because .can is not a special form; it's just a normal method returning a boolean. If you really want static treatment, that needs a special form: sub foo ( $obj can bar:(() returns Int) ) returns Int { $obj.bar(); } It will allow constructs such as this: my subtype Duck has $.half_life can doom:() can quake:(() returns Wolfenstein); Yes, I like that. I also proposed an object special form for classless instances in namespace. # Automagically satisfied iff $obj's interface is compatible $obj.does(Duck); Such implicitly-declared Roles is certainly powerful, and we can apply the same inferencing treatment as for nominal subtyping violations -- fatal error under closed/finalized, raise warning by default. I think it's cute, and adds real power of row polymorphism to the What is 'row polymorphism'? language, iff Perl 6 indeed adopts a compile-time inferencing engine. I would call it a bit different, but yes please! My idea is, that the programmer of Perl 6 can 'store' a lot of information in name/type space that is later---even at runtime---used by the code generation, class composition, type instanciation and dispatch system without forcing the programmer to rummage in the guts, which might actually be very difficult to do platform independently if not even Parrot is fixed as the underlying VM! BTW, is 'special form' a fixed term? I just started using it to decribe things like sub, class, role, etc. declarations/definitions. -- $TSa.greeting := HaloO; # mind the echo!
Re: Do slurpy parameters auto-flatten arrays?
HaloO, Luke Palmer wrote: On 8/3/05, Aankhen [EMAIL PROTECTED] wrote: On 8/3/05, Piers Cawley [EMAIL PROTECTED] wrote: So how *do* I pass an unflattened array to a function with a slurpy parameter? Good question. I would have thought that one of the major gains from turning arrays and hashes into references in scalar context is the ability to specify an unflattened array or a hash in a sub call without any special syntax... I thought that the obsoletion of special syntax stems from the type system. Piers seems to have the same view. See his example of map in his parallel reply. Well, you can, usually. This is particularly in the flattening context. In most cases, for instance: sub foo ($a, $b) { say $a } my @a = (1,2,3); foo(@a, 3); Passes the array into $a. If nothing flattened by default, then you'd have to say, for example: map {...} [EMAIL PROTECTED]; And even: for [EMAIL PROTECTED] - $x {...} Which I'm not sure people want. Ups, I thought the for special form would work as follows. 0. the syntax: for expression block 1. determine (return) type of expression 2. create an iterator for that type 3. Use the iterator until it runs out (is that when it returns undef?) 4. bind the block owner to successive return values of the iterator and call the block; if the block is pointy bind its environment as well. With the above for @a - $x {...} # use Iterator of Array and for [EMAIL PROTECTED] - $x {...} # use Iterator of List produc the same sequence of values in $x but through different paths in type space. As long as no user defined types are involved, I dought they are distinguishable at all. Here's an idea how a sub becomes its own iterator: sub foo() does Iterator[foo] { random; } for foo() - $x { say } # endless loop of random output How are roles/types composed into Code subtypes? And the way you pass an array in slurpy context as a single reference is to backwhack it. What it comes down to is that either you're backwhacking things a lot or you're flattening things a lot. Perl currently solves it by making the common case the default in each zone of parameters. I would be interested to hear arguments to the contrary, however. OK, I gave my 0.02. -- $TSa.greeting := HaloO; # mind the echo!
Re: zip with ()
HaloO, Luke Palmer wrote: On 8/1/05, Ingo Blechschmidt [EMAIL PROTECTED] wrote: In general, (@foo, @bar) returns a new list with the element joined, i.e. @foo.concat(@bar). If you want to create a list with two sublists, you've to use ([EMAIL PROTECTED], [EMAIL PROTECTED]) or ([EMAIL PROTECTED], [EMAIL PROTECTED]). But of course, I could be totally wrong. :) I think that's right. However, it might be a good idea not to auto-enreference such bare lists: I don't like this notion of auto enreference/dereference at all. Either the type system manages to dispatch things correctly or you get an error. For the List versus Array problem this dispatch is IMHO decideable at compile time by strictly typing @ vars as Array and subtypes thereof. The List type to me is a Code subtype and as such travels in vars. I'm only unsure how easily such variables should enter name space, that is how they behave without sigil. sub foo ($x) {...} foo (1,2,3,4,5); # foo gets called with [1,2,3,4,5] Yes, the $x makes foo an Item or even Value taker of arity 1. The call foo (1,2,3,4,5) OTOH calls it with a List. This should result in a type error. But sub foo (x) might then work for a List but not for an Item|Value call foo(1). Since I think that * in a signature is for extending the arity of the sub to infinity I wonder if it is possible to capture the caller's list into a single *$arg? sub foo (*$x) {...} foo (1,2,3,4,5); # type of $x is now Ref of List of Int? But with an additional array the slurpy item gets at most one value. sub foo (*$x, [EMAIL PROTECTED]) {...} foo (1,2,3,4,5); # $x == 1; [EMAIL PROTECTED] == 4 foo @array; # type of $x is now Ref of Array; @a is undef When you could just as easily have said: foo [1,2,3,4,5]; And we'll probably catch a lot of Perl 5 switchers that way. That actually makes a lot of sense to me. The statement: my $x = (1,2,3,4,5); Looks like an error more than anything else. Yep. I opt for type error Can't assign List to Item. By the same token I would disallow my @a = 3; # type error Can't assign Item to Array. It should be my @a = *3; or my @a = (3,); Hmm, wasn't there a nullary *? my @a = *; say [EMAIL PROTECTED]; # prints 0 That's the scalar comma, which has been specified to return a list. But maybe it should be an error. Sorry, I don't understand this. I thought comma just is *the* List constructor per se. Parens required to lift precedence :) Same applies to semi-colon. (1,2,3;4,5,6) is a List of List of Int. The main reason that we've kept a scalar comma is for: loop (my $x = 0, my $y = 0; $x*$y = 16; $x++, $y++) {...} However, I think we can afford to hack around that. Make the first and last arguments to loop take lists and just throw them away. My interpretation of the loop block controler special form is that it gets a 4-tupel (Block,Block,Block,Block). The last one is of course the loop's body. The first is the initializer that is executed in a scope outside the body. The second and third are the condition and the stepper and also scoped outside the body. Now to the comma. It should be parsed as List of Block. In your example the argument type of loop is (List of Block,Block,List of Block,Block). The loop instanciates an Iterator[List of Block] and uses it to execute the Blocks one at a time. The only special case is in the condition which evaluates only the last Block from the List of Block for truth and the others in Void context. Is loop supposed to be a topicalizer? Does it bind the block owner? Does a pointy body block make sense? loop (my $x = 0; $x 10; $x++) - {...} # current count in $_? loop (my $x = 0; $x 10; $x++){...} # $_ unchanged from outside? loop (my $x = 0; $x 10; $x++) { .blubber # what is the invocant? } Can the last Block also be separated with semi-colon? I guess not. How about a Code var? loop my $x = 0; $x 10; $x++; say $x; # works? loop my $x = 0; $x 10; $x++; foo; # works? loop( my $x = 0; $x 10; $x++; foo ) # perhaps as function call? loop my $x = 0; $x 10; $x++; say $x; # still the loop body? Or does it need { say $x }? loop foo; bar; blubb - { say # prints return value of blubb while bar returns true # first iteration prints return value of foo } Can anyone think of any other common uses of the scalar comma? Not me. It's a C relict. -- $TSa.greeting := HaloO; # mind the echo!
Re: Do slurpy parameters auto-flatten arrays?
HaloO, Piers Cawley wrote: By the way, if flattening that way, what's the prototype for zip? We can after all do: zip @ary1, @ary2, @ary3, ... @aryn How about sub zip( List [EMAIL PROTECTED] ) {...} a slurpy List of Array of List. The return value is a not yet iterated Code object that knows how to produce tuples from the outer lists. This implies that zip(@array) basically returns an unstarted iterator on @array. -- $TSa.greeting := HaloO; # mind the echo!
TSa's Perl 6 type lattice version 1.0
HaloO, in case someone might be interested, here is my more or less complete idea of the Perl 6 type lattice as ASCII art. Enjoy. Comments welcome. ::Any ...| ... ___:___/|\:_: | :| : | | static type : Package:| : Void ?Bool = context : | :| :__|__| : Module:|/:.: ___|___:| | | :| Class Grammar :| |___| :| | :| Role : Object Record =::= Frame =::= Dictionary :| : __/ \_ with:| || || | invocant(s) : Code $Item%Hash Frame@Array Tuple :| ||_||___| block owner : topic | | | $/ : $_ | | | :___/ \_ ___| | |: |\ | || | | | | .Method : Sub\ -Block \Ref Value Undef Inf Junction | /|: |\ \ || | / |: | \ \ __||_ | Rule |: | Macro \/ || | | || |:_/|Ref[Code] | :Pair /Match/ ~Str +Num | |: ||| | || Multi : ||| |Int | ..: ||| | / || ||___ ___| Enum || || \/ | || || Entry[::T.does(Hash)] Bit || _|__ |___ _|| || | \/ | =Iterator *List | Pos[::T.does(Str|Array)] | | | | |_ _|___| | | ||\ / | ..Range Pipe Lazy **Eager Ref[Array|Hash] | |__|_|| _| \ / (to | all leafes) \|/ ::All -- $TSa.greeting := HaloO; # mind the echo!
Re: Eliminating {} and *{}
HaloO, Autrijus Tang wrote: All this led us to think about whether (my foo) can be merely treated the same as (my Code $foo). The mutable form will enable convenient notations such as: I think (my Code $foo) should be an error on the same reason as (my Array $foo) is an error. A $var can only contain explicit Ref types like (my Ref of Array $foo) or (my Ref of Code $foo). But the following should be allowed my pi = 3.14; if $num == pi {...} foo = sub { ... }; So instead of having to explain to newcomers that you cannot assign to a -sigil symbol, it would all just work. Under this view, {$x} would be eliminated with *{}. I think *{1,2,3} is valid syntax which means listify the code literal. But it's no special form. In particular * {1,2,3} is the same because * is a normal prefix op. Another idea is to treat (my foo) the same way (my Code $foo is constant). That will discourage people into assigning into functions, and enable the compiler to detect function variables at lvalue position as errors, but on the whole I don't think it's worth the complexity. Does this make sense? Yes. I think of the (fantastic) four sigils as referential expressions that are somehow bound to 'real' data. When and how that binding takes place is another matter. But in particular I like my idea that the corresponding dot twigils are firstly applicable only in methods and are secondly then bound through the invocant. E.g. .action calls the action slot of the current invocant---method level block owner aka $?SELF. This is basically the vtbl dispatch. Note that . slots are auto-generated accessor methods if not explicitly given by the class implementor. A method special form is *not* a slot method by a 'free' method specialized on the surrounding class. PS: could someone give a summary which sigil forms are still in effect. E.g. ${}, $(), etc. -- $TSa.greeting := HaloO; # mind the echo!
Re: [S29] Mutating map and grep
HaloO, Ingo Blechschmidt wrote: Is this a bug in S29 or will this be feature removed from Perl 6 and you'll have to say (for example) use listops :mutating; my @result = map { $_++; 42 } @array; # works now Why not just my @result = map - $_ is rw { $_++; 42 } @array; # works now which could be abbreviated as my @result = map:rw { $_++; 42 } @array; # works now And as usual the :rw binding needs the confirmation of @array. BTW, would the following be parseable in an extreme interpretation of optionality of block owner and block topic: my @result = map:rw{ .++; 42 } @array; # ++ as method on owner my @result = map:rw - { ++; 42 } @array; # ++ as sub with topic my @result = map:rw - { .++; 42 } @array; # both: $/.++($_) -- $TSa.greeting := HaloO; # mind the echo!
Re: zip with ()
HaloO, Andrew Shitov wrote: Is it possible to avoid significance of whitespaces? Yes, with: say zip .(@odd, @even); Looks like a method and *is* a method in my eyes. First zip is looked-up and then bound as block owner. Arguments are of course two array refs to @odd and @even respectively. BTW, you didn't mean originally: say zip (@odd), (@even); # prints 13572468 or 12345678? Does zip now interleave two array refs instead of flattened arrays? I think, such an aspect of Perl 6 would be awful. IB Whitespace is significant: IB say zip(@odd, @even); IB say zip (@odd, @even); -- $TSa.greeting := HaloO; # mind the echo!
Re: zip with ()
HaloO, Ingo Blechschmidt wrote: Whitespace is significant: say zip @odd, @even;# zip gets two arguments, result is # 12345678. say zip(@odd, @even); # zip gets two arguments, result is # 12345678. say zip (@odd, @even); # zip gets only one argument, the flattened # list (@odd, @even), containing the Why flattened? Shouldn't that be *(@odd, @even)? # elements (1,3,5,7,2,4,6,8). Then zip Why not ([1,3,5,7],[2,4,6,8]) list of two array refs? # tries to zip this one list, resulting in # 13572468. If the list of two array refs is not flattened, the result should be 12345678 because how should zip distinguish it from the other cases? The crux of the first case not requiring parens is that zip is declared as listop and as such consumes the @even after the , which otherwise would be left for say. And if say weren't declared/assumed listop, the @even would be evaluated in Void context and not appear in the print at all. Or do I miss something important? E.g. has () become a circumfix deref op? -- $TSa.greeting := HaloO; # mind the echo!
Re: zip with ()
HaloO, Andrew Shitov wrote: TTS BTW, you didn't mean originally: TTSsay zip (@odd), (@even); # prints 13572468 or 12345678? That is exactly like with similar printing result of sub() call: print sqrt (16), 5; # shout print 45. That all hinges on the type of the symbol. I guess sqrt is a unary prefix. Then print sqrt 16, 5; # should print 45 as well. The point is, to not let sqrt 'swallow' the 5 unless it is declared listop. -- $TSa.greeting := HaloO; # mind the echo!
Re: sub foo ($x) returns ref($x)
HaloO, Autrijus Tang wrote: [..] For example, assuming argument types are unified in a single phase, the example below does nothing useful: sub equitype ((::a) $x, (::a) $y) { ... } It won't not help even if we replace the implicit does with of: sub equitype ($x of (::a), $y of (::a)) { ... } The reason, in Luke Palmer's words: The trouble with this is that it doesn't provide any type safety. In the case of a type conflict, a just degenerates to the Any type. (cf. pugs/docs/notes/recursive_polymorphism_and_type) Luke's analysis is indeed correct. And describes what can be inferred from the caller side. And I wouldn't introduce the subtlety that the first ::a is bound to the exact type of $x in the call environment, while the second is a constraint on $y's type. But I would prescribe exactly this as the meaning if you use plain 'a' as the type of $y. Thus I opt for: sub equitype ( ::a $x, a $y) { ... } which is the same behaviour as for the value of $x which can be used immediately for subsequent parameter bindings. Hmm, how do coderefs behave in that respect? sub codeparam ( foo, ?$val = foo ) {...} Does this invoke a bar argument once for the call codeparam( bar ) and capture the result in $codeparam::val while the call codeparam( bar, 42 ) stores 42 without invoking bar through codeparam::foo? And in which exact environment does a call to bar take place when needed to bind $val? Purely ::CALLER? Signature as bound so far? ::OUTER of the use'er of the package which contains codeparam? Or the ::OUTER of the 'real' package file? The other remark I have for the form with double ::a is that there's also an inside view of that type. All type information inferred can be stored as constraints on ::equitype::a in the ::equitype Code class. Interesting is how the syntax for a more explicit form reads: sub equitype( ::a $x, ::a $y ) where { a.does(SomeRole) } {...} This fact, coupled with the unappealing (::a) syntax, I like the syntax. BTW, does it have to have parens? I would actually promote :: to a very fundamental operator/token. Even if that costs some parens for the ternary ( ?? :: ). leads me to look for a more Perlish representation. Adopting an idea from Odersky's Nested Types paper, we can let terms occur at type variant position, by introducing a ref form for types: sub equitype ($x, $y of ref($x)) { ... } sub subtype ($x, $y does ref($x)) { ... } sub identity ($x) returns ref($x) { ... } Uhh, please make that sig read ($x, type($x) $y) or at least ($x, $y.does($x.type) or something else with 'type' in it. Ref is way to overloaded with meanings in Perl6 which are not easy to unify away because of mismatches on the levels of abstraction involved. E.g. the sub identity looks like an alias for \ which it isn't from the type perspective. This reads like Perl, and can be guarded with trivial compile time and runtime checks. We can also use type selectors to check that pick can always return Int from an Array[of = Int]: sub pick (@x) returns ref(@x).of { ... } The only problem I can find is that the possible confusion between the ref() operator and the unboxed basic type ref. Another thought is to simply use ::() as a special ref form: sub pick (@x) returns ::(@x).of { ... } But that can confuse with the symbolic dereference syntax. All in all Uhh, could we agree to call ::(symbolic) the symbolic lookup form and ::bareword the bareword, pre-runtime lookup form? Let's not add another referencial thing to the 'Many Refs of Perl6'. In the end we'll need a dedicated reference manual :) I guess it would be S08. Since I opt for ::pick beeing the innermost namespace immediately after its introduction with 'sub pick' ::x could refer to @x from the signature. Note that if there are x, $x, @x and %x in the signature a simple ::x is typed as their supertype Object. Disambiguation would go as ::x::Code, ::x::Item, ::x::Array and ::x::Hash respectively. And of course you can further descent into these namespaces as in pick::x::Array::of. Descending along multiple pathes essentially means any'ing the types together ::x::*::of. Well, in some namespaces things are all'ed together :) The supertype of all array entries is of course pick::x::Array::values::* and single items show up numerically under pick::x::Array::values:: e.g. pick::x::Array::values::8. Note that this is *not* a symbolic form but well defined. It might evaluate to undef though. Finally the .of method might just be syntactic sugar for the above: sub pick( @x ) returns @x.of {...} or just sub pick( @x ) returns x.of {...} or sub pick( @x ) returns x::of {...} I'm more happy with ref(), but better suggestions welcome. I suggest type(), tie() or soul()---the latter is from '.bless() my .soul()'---if none of the above pleases @Larry. -- $TSa.greeting := HaloO; # mind the echo!
Re: sub foo ($x) returns ref($x)
HaloO, Autrijus Tang wrote: On Mon, Aug 01, 2005 at 03:16:50PM +0200, TSa (Thomas Sandla�) wrote: sub equitype ( ::a $x, a $y) { ... } That's not a bad idea at all. I rather like it. I'd just still like an explicit type-unifying parens around ::a, just so people won't say I try to maintain the 'parens only group' point of view. But it seems to be violated elsewhere, too. sub foo (::Int $x) { ... } and accidentally rebind Int. Why so shy? It would rebind foo::Int with respect to the inside of foo. Of course the funny effect is that for a call foo( blahh ) foo::Int means Str :) I guess this is why $Larry wants a role wrapped around such type parameter instanciators: role Foo[::Int] # hides *Int { sub foo (Int $x) { ... } } and explicit instanciation use Foo[Int]; # or some such use Foo[Str]; use Foo[Num]; But I don't know if he also wants to carry that on to the actual calls: Foo[Int]::foo(42); Foo[Str]::foo('42'); Foo[Num]::foo(3.14); OTOH, one has to use *::Int or *Int to surely get the standard Int, anyway. And for getting guaranteed type locality inside foo a sub foo( MY::Int $x ) {...} might be needed, too. This nicely fits other pseudo namespaces: sub foo( Int $x ) {...} # whatever Int is in effect # at compile time sub foo(::Int $x ) {...} # deferred lookup to CHECK time sub foo( MY::Int $x ) {...} # dynamically from $x sub foo( foo::Int $x ) {...} # same for all invocations? error? sub foo( OUR::Int $x ) {...} # from package How usefull OUTER::, CALLER::, etc. are I have no idea. Perhaps it's a good idea to reserve single capital letter barewords for type params. Or a twigil if we think of '::' beeing s sigil: sub foo( ::^a $x ) {...} This saves one character compared to your (::a) which is the same length as MY::a. -- $TSa.greeting := HaloO; # mind the echo!
Re: Slurpy is rw arrays ([EMAIL PROTECTED] is rw)
HaloO, Adriano Ferreira wrote: Only sub foobar (@args) { push @args, 42 } would change @some_array in foobar @some_array; That is how I undestood that. Can someone confirm this belief? I share your belief. It's up to others to confirm it. I just want to add that I further believe that the push call is dispatched on the type of the array and only succeeds if @array.does(Pushable). I guess a default array does this or another role that implies it. -- $TSa.greeting := HaloO; # mind the echo!
Re: Elimination of Item|Pair and Any|Junction
Larry Wall wrote: On Wed, Jul 27, 2005 at 06:28:22PM +0200, TSa (Thomas Sandlaß) wrote: : Since we are in type hierachies these days, here's my from ::Any : towards ::All version. That's pretty, but if you don't move Junction upward, you haven't really addressed the question Autrijus is asking. We're looking for a simple type name that means none(Junction) for use as the default type of the $x parameter to - $x {...}. Whatever we call it, this type/class/role/subtype has to admit Item and Pair objects but not Junctions. (And if that's the wrong way to think about it, please tell us why.) Sorry, here's the patch: : Code @Array %Hash $Item : | // | with: | TupleRecord | invocant(s) : || :/ \__ ___|_ |: | |\|| | | .Method : Sub Block |Value Inf Undef Junction /|: |\ | | / |: | \Ref[Code]| Rule |: | Macro| |:_/|__/|\___ |: | | | | | | Multi : | ~Str +Num \Ref :Pair /Match/ Now the Junction is nicely constraint with the upper bound Item (less specific) and a lower bound Value (more specific). This also reads nice if you want to (explicitly) allow both: sub ( Value|Junction $val_junc ) What sub ( $any ) should default to, I don't know. My $Item indicates Item, but could also be $Value. Or unspecific $(Item|Value). -- $TSa.greeting := HaloO; # mind the echo!
Re: Inferring (Foo of Int).does(Foo of Any)
HaloO, Autrijus Tang wrote: [..much better explaination of the co/contra prob then mine skipped..] Hence, my proposal is that Perl 6's generics should infer its variancy, based on the signature of its methods, and derive subtyping relationships accordingly. Yes!! That would be great. But I would restrict it to the onboard methods or however we call them. Outside/free methods specialized on the generic type are firstly referential in nature, and as such bind their $.attr, @.array, %.hash and .code referential expressions through the invocant. They form a mediator layer between unrelated code and the code implementing the type's guts. The other alternative is do as Java does, which is assume invariancy by default, then force users to write variancy annotations, but I think that is considerably less attractive. There may be a case for inferring by default, but overridable by the user; if so there needs to be a syntax for that. Well, that pivots around how refs behave. I would opt for them beeing const unless explicitly allowed :rw by the instance owner. Is the syntax for that actually \$x:rw? Or even plain \$x if we assume that every sigil expression *always* means implicit const ref? And thus needs a dereferencer, e.g. $x()? Then $x = $y; # means dispatch to op = $x := $y; # same, but op := requires $x to be writeable \$x = $y; # same as := ? I prefer \$x:rw which might fail # depending on where $x refs to \$x := $y; # ??? Consider $x = [EMAIL PROTECTED]; # assume there's no slot 42, then the array could # hand-out a \.[42]:rw and allow subsequent # assignment # but $x = [EMAIL PROTECTED]; # assume .[23] is filled, then the array returns # a const ref Such an array would be typed Array of ::T^Ref:rw[Undef of ::T] and as such a hot candidate for the default array :) -- $TSa.greeting := HaloO; # mind the echo!
Re: Messing with the type heirarchy
HaloO Michele, you wrote: On Wed, 27 Jul 2005, [ISO-8859-1] TSa wrote: value to carry on a useless imaginary part. And Complex should consistently return undef when compared to other Nums or Complexes. And the Compare role My 0.02+0.01i: in mathematics it is commonly used to write e.g. z3 to mean z is real AND as a real number is less than 3. Which in Perl6 is written as Complex where { .imaginary =:= 0|Undef } does Num; somewhere in the Complex package. This would make your intensions possible by dispatching to infix:{''}:(Num,Num) but still preventing the general case. -- $TSa.greeting := HaloO; # mind the echo!
Re: The meaning of returns
HaloO Autrijus, you wrote: D) Make the return type observe both #2 and #3 at compile time, using type variables: sub id ( (::T) $x ) returns ::T { return($x) } And this is a natural extension to guide the inferencer so it won't be totally giving up on polymorphic functions such as id. C) and D) can be taken together, resulting to a powerful soft typed language. This is my preference. The only known issue with parametric typing is the proliferation of params as soon as you want to stay away from unpecificity. However, if we take the view that type annotation are merely storage allocation hints and runtime coercers, then A) is probably the way to go. Please no. Or at least not exclusively. I see your storage allocation hints as a data environment needed to implement the type. -- $TSa.greeting := HaloO; # mind the echo!
Re: Do slurpy parameters auto-flatten arrays?
Ingo Blechschmidt wrote: Hi, ReHi, are the following assumptions correct? I don't know in general. But see my assumptions below for comparison. They are derived from my type theoretic approach and as such might collide with Perl6's referential semantics. In particular with the auto-ref/deref and how far it follows links. sub foo ([EMAIL PROTECTED]) { @args[0] } say ~foo(a, b, c); # a foo( List of Str ) my @array = a b c d; say ~foo(@array);# a b c d (or a?) foo( Ref of Array ) # @args[0] derefs the array ref # I guess you need @args[0][0] to get a But I don't like this level of reference preservation. E.g. one then needs to know how far out the flat array resides, to use the right number of dereferencers. Here type theory doesn't constrain the definitional freedom because both interpretations are compatible with [EMAIL PROTECTED] Actually that unspecificity could be preserved, see below. say ~foo(@array, z); # a b c d (or a?) foo( Ref of Array, Str ) # @args[0] as above Here typing constrains the interpretation to be the one that needs @args[0][0] to get at a. This is slightly untrue. The problem is actually shifted to the question: How does comma handle a Ref of Array?. say ~foo([EMAIL PROTECTED]); # a foo( List of Str build from Array of Str) say ~foo(*(@array, z));# a sub bar ([EMAIL PROTECTED]) { [EMAIL PROTECTED] } say bar(1,2,3); # 3 say bar(@array); # 1 (or 4?) Type theory actually should come up with any(1|4) :) And yes, any(1|4) is a type literal and any($x,$y) is a parametric type which is fixed whenever $x and $y are. Side node: A nice test for hidden assumptions in code is to replace functions which return Any to behave randomly. A Vogon optimizer OTOH, might blow away a complete planet and return 42 everywhere :) For this very reason the default signature of the ideal sub is of course ::Any -- ::All where All is pure specificity. And---even thow I should start a 'type theory foundations of Perl6' thread, I mention it here---the ideal method is ::All . ::Any -- ::All A multi sub/method is in that view a *metric* dispatcher on the middle ::Any between the selector before the dot and the return type after the arrow. say bar(@array, z);# 2 (or 5?) I opt for 2. say bar([EMAIL PROTECTED]);# 4 Yep. -- TSa (Thomas Sandlaß)
block owner, topic and the referential environment
This is another spin-off from the 'Exposing the Garbage Collector' thread. Here is an enhanced version. I wonder how the generic, lexically scoped invocant/owner is called. I propose to call it $/ (other option is to call it $)and let the former topicalizer become block owners and $_ the block topic that flows into blocks from further outside if not explicitly bound with - like: $topic := Some.new; $_ := $topic; for @objects { .action } # call on $/ from @objects with $_ := $topic # in all loops @objects».action; # same for single action syntax # but for @objects - { .action } # means $/.action($/) because # $_ bound to dynamic block owner; # but usefull for methods that don't # use the topic, in particular accessors # and mutators # same as sub call for @objects - { action } # means action($/) because $_ := $/ # but $/ is there if action is of # type Method # but the $. @. %. and . are bound through $?SELF # in particular for @objects - { .action } # subref curried on invocant This implies that a .action means name lookup of 'action' while .action is an onboard method of $?SELF. This latter case is typically implemented with a vtbl lookup. The only drawback I see is, that the careless method programmer could be caugth in an endless .action loop if .action invokes .action explicitly on $_ where $_ := $/ from the outside. The same endless loop could of course be achieved with a free standing .action but that looks more like intention. With the lurking pitfalls an occasional check of $_ =:= $?SELF and $/ =:= $_ seems advisable and indicates that the invocant wasn't exchanged midway :) Same with other block topicalizers/owners given $x{...} # topic untouched, but $/ := $x given $x - {...} # $_ := $x as well But if $x{...} # $/ and $_ untouched if $x - {...} # $_ := $x (non boolean value) One more interessting thing is that in exception handlers all three variables $!, $/ and $_ are in scope. This might allow to resume where the exception occurred after the cause was fixed e.g. by loading or generating some code, some revamping or other DEEP_MAGIC. Hmm, debug exceptions come to mind... -- TSa (Thomas Sandlaß)
Re: Exposing the Garbage Collector (Iterating the live set)
Luke Palmer wrote: On 7/26/05, TSa (Thomas Sandlaß) [EMAIL PROTECTED] wrote: Piers Cawley wrote: I would like to be able to iterate over all the objects in the live set. My Idea actually is to embedd that into the namespace syntax. The idea is that of looking up non-negativ integer literals with 0 beeing the namespace owner. for ::Namespace - $instance { if +$instance != 0 { reconfigure $instance } } Oh, so a namespace can behave as an array then. Well, to avoid auto-flattening problems in other, more common places, we ought to make that: for *::Namespace - $instance {...} Well, even more huffmanized would be for Namespace - {...; use $_} might be what you expect after my @array = (0,1,2,3); ::Namespace ::= @array; However, this is very huffmanly incorrect. First of all, what you're doing may take a quarter of a second or more for a large program (which isn't a short amount of time by any means). Second, the fact that you're using it means you're doing something evil. Third, only a fraction of 1/omega perl programmers will be using this feature. Therefore, it should probably look like: use introspection; for introspection::ALL_INSTANCES(::Namespace) - $instance {...} This is why I wonder how writeable the namespace is, and when. On some platforms it might actually not even be readable because it was compiled away or stripped from the excecutable ;) All that remains then is the possible behaviour as it is constrained by the types of souls/daemons the creator happened to *choose*. I guess you should re-read $Luke::Bible or watch the $*::Movies::WarnerBrothers::Matrix again :)) If both refs are undef in your namespace, go and bind them! If the above is insulting, feel free to invoke my .apologize with you as topic. You know, I'm the $/ of this $email. And it might even be platform-specific, given the constraints of some of our targets. The platform is yet another restriction on Space::Search::Solution. Interestingly namespace lookup is big endian... -- $Language::Perl6::TSa.greeting (somehow we are all part of it or was that $_?)
Re: Messing with the type heirarchy
HaloO, Ingo Blechschmidt wrote: I've probably misunderstood you, but...: role Complex does Object {...} Num does Complex; # That should work and DWYM, right? My 0.02: Complex should provide e.g. a + that, when called with two Nums, doesn't bother the return value to carry on a useless imaginary part. And Complex should consistently return undef when compared to other Nums or Complexes. And the Compare role shouldn't treat undef == false but as any(true|false). Otherwise funny things can happen (as was observered correctly in another thread about != applied to any Juntions). In code: if $c 3 { die if $c.does(Complex) } This is the Perl6 representation of the following sentence: If Any::$c is less then Int::3 then die if this $c does behave like a Complex. I hope $Larry likes it. BTW, is their a plain english output module planned, that would produce the above automatically? Don't question (Light ::= Particle|Wave) with a double slit! At least not if you want a deterministic answer where it actually passed. tie rant Imagine a Casino that hands out ties to players who don't have one even though the Casino is a tied area. If a Num playing in the Casino likes the imaginary standard tie it can keep it. But among Nums this imaginary tie is no differentiator. Actually other Num methods will say: A tie? I see no tie. Must be an imaginary one. In simple environments the tie might not even be applicable imaginarily. Thus it's stripped off or entrance is denied. Under all cicumstances the Num may decide how to deal with this tieing. fun: d(en)ie(d) == die in the end :) /tie rant The only question is how much effort all this is for (1) the implementor of Complex (2) the implementor of Num (3) the user of either one in isolation (4) when they come together In particular the user in (4) should be able to state his expectations in a form that is checkable by the VM. Which basically means that (1) and (2) have to state their assumptions to the VM in the same form/syntax. -- $TSa.greeting := HaloO; # mind the echo!
Re: execution platform object? gestalt?
Randal L. Schwartz wrote: This is similar to the OS-9's gestalt tables, which got smarter as the operating system had more features, but was a consistent way to ask do we have a color monitor here?. Is something like this already planned? From my bubble in the Perl6 Universe this thing is an unbound symbolic reference $::(to The Type System). Welche Gestalt es bisher angenommen hat weiss ich nicht. But it should be capable to appear in any(@form) to help all(@us) where {any(@us) != ::United::States of America}. :) -- $TSa.greeting := HaloO; # mind the echo!
Re: Elimination of Item|Pair and Any|Junction
HaloO, Larry Wall wrote: Yes. The only thing I don't like about it is that any() isn't an Any. Maybe we should rename Any to Atom. Then maybe swap Item with Atom, since in colloquial English you can say that pair of people are an item. Since we are in type hierachies these days, here's my from ::Any towards ::All version. The bottom part where everything finds together is missing for this installment. ::Any ... | .. ___:_|_:static type : | : | : | | = context : Package: | : Void Bool : | : | :. Module: | ___|___: | | | : | Class Grammar : | |___| : | | : | Role : Object : | : | || | : Code @Array %Hash $Item : | // | with: | TupleRecord | invocant(s) : || :/ \__ __|_ |: | |\ / || | | | .Method : Sub Block | | Inf Undef Match Junction /|: |\ | | / |: | \Ref[Code]| Rule |: | Macro| |:_/|__/|\ |: | | | | | Multi : | ~Str +Num \Ref :Pair ..: | | | |\| | |Int| \ | ___/| | | | Entry[::T where T.does(Hash)] | | | |/|\| *List Pipe =Iterator Enum ?Bit Pos[::T where T.does(Str|Array)] |\___ | | | **Eager Lazy Ref[Array|Hash] any() == lub( all --- any ) == glb( any -- all ) lesser -- greater all() == glb( all --- any ) == lub( any -- all ) Some operators and prefixes are added in to show their relation to the corresponding type. I hope it looks familiar. Here is some pseudo code that describes a bare minimum data layout required to support the respective types. type Item[::T] { has $.value of T; } type Pair[::T] { has $.key; has $.value of T; } type Tuple[::T where T does lub( @.values )] # lub = least upper bound { has @.values of T; has $.value ::= @.values; # auto-enreference for Item subtyping has T $.head ::= @.values[0]; has T $.tail ::= @.values[-1]; } type Record[::T where T does lub( @.values )] { has @.keys; has @.values of Pair[T]; has @.pairs ::= { zip @.keys, @.values }; has $.value ::= @.pairs; } type Code { has %.MY;# lexical scratchpad has .block; has $.value ::= { use %.MY; .block() }; # coderef literal } type Junction[::T where enum any all one none] { has @.values; has Junction $.value ::= { @.values as Junction[T] }; has .evaluate ::= ::JUNCTION_MAGIC; # what's the exact type of this? } -- $TSa.greeting := HaloO; # mind the echo!
Re: Exposing the Garbage Collector (Iterating the live set)
Piers Cawley wrote: I would like to be able to iterate over all the objects in the live set. My Idea actually is to embedd that into the namespace syntax. The idea is that of looking up non-negativ integer literals with 0 beeing the namespace owner. for ::Namespace - $instance { if +$instance != 0 { reconfigure $instance } } Hmm, how would that be written inside the owning class? for :: - $instance {...} # or perhaps ::_ or ::0 H, and the current actor/owner is $/ which gives the expanded method call syntax: .method # really means: $/.method($_) Then we need to distinguish between the owner of a block and the topic of the block. In methods the owner is called invocant, of course. This also nicely unifies rules and methods. But with the drawback that the brawl then shifts from topic versus invocant to rules and method competing for ownership :) ISTM that exposing the Garbage Collector at the Language level is the neatest way of doing this (or coming up with something like Ruby's ObjectSpace, but conceptually I reckon the GC is the right place to hang it). To me the GC is an implementation detail for rendering the illussion of infinite memory :) For example +::Int could return the number of instances in use not the potential Inf many ones. Adding the infix namespace wildcard could allow to retrieve attributes as arrays indexed by object id: @instvalues = ::SomeClass::*::attr; The access control on a level behooves its owner/origin that is ::NameSpace::0. This gives in the end a virtual tree of all static information. As a fallout, structured rule matches can also be queried with :: and as such nicely blend strings into the type system. E.g. after successfull recognition an object could be created by simply reparenting it from the rule to its class/owner. The referential fabric and the call chains are hang-off this structure somehow, as well. Everything else is basically garbage. Too far off the mark? If not, I've ideas for ?? and :: beeing top precedence namespace query ops. Only effect is that the current meaning needs parens like ($condition ?? $value :: $other) for preventing strange tokenization. OTOH would the barebone structure of Perl6 revolve around ?? :: ::= () ; and namespace lookup. -- TSa (Thomas Sandlaß)
Re: Do I need has $.foo; for accessor-only virtual attributes?
Larry Wall wrote: The problem I have with is private is that, while there may very well be a trait of that name that you can interrogate, I really want people to think of the private methods as being in a different namespace so that there's no confusion about the fact that you can have a private method and a public method of the same name. And the reason I want that is because I strongly believe that private methods must be absolutely invisible to the public interface, and confusing the namespaces puts you in a situation where adding a private method can clobber public inheritance of the same name. Even worse, it clobbers your private interface. As soon as you say method foo() is private {...} then you can't call $?SELF.foo() and expect to get the public .foo method. Putting the difference as part of the name forces people to distinguish $?SELF.foo() $?SELF._foo() on the call end. And the _ has the advantage of being *perceived* as part of the name. I start to understand the problem I have with perceiving this. You think of the name ::foo beeing looked up somehow *in* the object you want to call on, while I always assumed that the name ::foo is looked up first. In a method invocation expression this lookup has to yield a method implementation that has got an invocant type that is compatible with the one the caller wants to put in. If ::foo shall not be visible why not arrange for the lookup to fail? Failing *look*up and invisibility are---linguistically spoken---very related concepts, or not? This method-first approach has the added benefit that anyone can place a compatible method into a lexically closer scope than the one they want to overwrite. If the closeness still prevents the call because of lacking specificity a simple temp $object does MyStuff; and a method in scope that is specialized on .does(MyStuff) hardly leaves outsiders a chance to prevent the dispatch! The same thing without temp might be construed as anti-social by whomever gave you $object ;) The otherway round should look more like $?SELFfoo() or SELF::foo(). Hmm, and nullary .foo performs the lookup on $_ or some such. Honestly I don't understand why the vtbl implementation detail of e.g. C++ is taken as template for Perl6 SMD OO. Private methods of an object come into play because the dispatch of a publicly visible method is called. The private method must be in scope there. The only requirement on the name is to not leak out into public namespace. The problem with $?SELF.:foo() is that people see that as a .: operator on the foo method. Which is a *BIG* problem in an Operator Oriented Language! -- TSa (Thomas Sandlaß)
Re: Do I need has $.foo; for accessor-only virtual attributes?
Larry Wall wrote: $x is visible only in the rest of the lexical scope. In contrast, $_y would presumably still be visible if the class were reopened. Which brings me to the question how the name information is told to a prospective user if the source code of the the first definition shall not be disclosed. I mean of course there is the documentation but I thought more of a machine readable form. Some kind of a interface definition of a package. : # or does class scope mean shared by all instances : # and lexically scopes per instance? Class scope is basically package scope. For instance attributes and methods the package contains proxies representing the slots in the actual instance. Sorry, this proxy is the invocant, right? And the type system ensures compatibility to the methods expectations. This is to me the whole point in the method call procedure: to bind the invocant to the variables of the method with respect to the invocant. Since variables in Perl6 code bear one of the four sigils Code, $Item, @Array and %Hash this binding to the invocant is simply indicated by the . twigil and supervised by the type system. Sure, if you want to declare an attribute containing a code reference. But doesn't have much to do with the call syntax in any event, whether you're calling subs or methods. You can declare an attribute as .foo and call it as $.foo without a problem, since it's just $?SELF.foo() either way, and the accessor methods are not associated with sigils. I think $.foo and .foo are synonymous as attributes, except insofar as we can probably deduce that .foo is dealing with a sub ref and not just any old scalar value. Sorry, I meant the sigil as generic Code type markup which includes in particular methods on behalf of the invocant. Actually I see no point in assuming sub ref for . but a ref to a method with the invocant type as specializer. The type information for an object that is blessed into a type comes of course from just the artifact from the blessing, however it is retrieved from the invocant. So with these two things at hand a method invocation can be spawned: 1) the invocant ref 2) a method ref All referential expressions in the code block of the method are bound according to the runtime representation of the object in that moment. : * All roles can write completely private $x attributes that are not : visible outside their lexical scope but are nevertheless : per-instance. : : I understand that correctly, that $x in : :role Foo { has $x = 7; method foo { $x++ } } : : denotes a reference to an Item from the data environment of the object : that foo is invoked on. I don't know what you mean by data environment. The second occurrence of $x denotes the generic proxy declared by the has that represents an eventual slot in the actual instance. This slot presumably has no other obvious name to any other role or to the class that composes this role, though presumably there's an internal way to get back from a particular slot to the slot's metadata, which presumably knows which role supplied the definition. With data environment I mean the stuff reachable through the invocant. The actual type of the invocant and the method's formal invocant type specify what is available through the link as long as the invocation persists. : The type of the $?SELF that Foo is composed into : obviously is a subtype of Foo. What happens with this hidden payload if : the object changes its type such that it is no Foo anymore? E.g. by : undefining the slot .Foo::foo? Um, people who undefine functions that are going to be called later get what they deserve. As for what happens to $x's slot in the absence of the lexical reference from Foo::foo, I expect the metadata would still have pointers to it so it wouldn't necessarily be reclaimed unless you told the object that is undoes Foo. Or to look at it another way, all the objects that do Foo have a closure over that $x proxy, so it's not going to go away until everyone forgets about the Foo role itself. Ups, I hoped that the type system would find out mismatches of the objects actual structure and the methods expectations of it. Essentially rendering the method in question not applicable to the object anymore. BTW, what is the inverse operation of bless? Expel? -- TSa (Thomas Sandlaß)
Re: Referring to package variables in the default namespace in p6
Matthew Hodgson wrote: These rules are all fair enough - but they are then ambiguous for $::Foo. Is that the leaf name variable Foo in your current (innermost) namespace? It is not ambiguous if the sigil rules that expression. I assume that the parameters of a sub are definining innermost names to their body: sub foo ( $param ) { say $::param; # prints argument bound to $param say $param; # same say $OUTER::param; # prints value of result of a lookup # that starts outside of sub foo # but my ::param $x = ::param.new; # look for param type info # The above compiles preliminarily but eventually needs # a type param. If the only name that is in scope is the # formal param then I presume a late compile error occurs. # Well, or the runtime *value* of $param is taken as the # type which essentially renders $x a constant. # and my param $y = param.new; # works only if param pre-declared. # Also say param(); # requires a code type to be in scope say param(); # same with late binding say .param(); # late binding with method sigil } Interesting question is how the last two lines above behave depending on whether param.does(Sub) or param.does(Method) and what light that sheds on the $?SELF.method problem :) Or is it an attempt to dereference the disambiguated type Foo? What is the use of reference to a type? The compiler, dispatcher and class and object composer need type information to do their job, of course. And they might handle this information through refererences. But when this happens the source is already digested. In other words you just can't use a sigiled expression where a type is expected: my $::Foo $x; is just a syntax error. This is why I regard the sigils as type mark-up. That means writing $Foo or $::Foo just tells the compiler that you want to handle the item Foo. Or is it like perl5, shorthand for $*Main::Foo? This is clearly specified as not beeing the case. Is there any reason why $::Foo could not do both, and not start by searching your current namespace for a variable called $Foo... and then start searching your current namespace hierarchy for a type called Foo and try to dereference it (whatever that does)? This is my position if I read the double negation correctly. Sorry if that wasn't clear initially. But I hope the above rants clarify what I mean. Presumably it should behave in precisely the same way that $::('Foo') does for sanity - does that search the current namespace for just types or variables or both? Not for sanity. $::Foo is just syntactic sugar for $::('Foo') because 'Foo' is a compile time constant. But $::( some_calculated_name ) might not in general be evaluateable at compile time and thus forces the compiler to generate symbolic lookup code which 1) calls some_calculated_value 2) starts lookup with the stringified return value Note that because of the $ sigil it looks for something that does the Scalar/Item role! We can consider the sigils as lookup filters. Regards, -- TSa (Thomas Sandlaß)
Re: More on Roles, .does(), and .isa() (was Re: Quick OO .isa question)
chromatic wrote: On Tue, 2005-07-19 at 18:47 +0200, TSa (Thomas Sandlaß) wrote: I strongly agree. They should share the same namespace. Since code objects constitute types they also share this namespace. This means that any two lines of class Foo {...} roleFoo {...} sub Foo {...} method Foo {...} subtype Foo of Any where {...} in the same scope should be a simple redefinition/redeclaration error. I don't understand this. What does a scope have to do with a namespace? I meant a scope of source code, basically everything delimited by braces. And that nesting of braces *is* the namespace, or not? Well, at least the compile time view of it. The Perl6 namespace is available at runtime as well. But it is beyond me how much these differ. But for the specification of the language only the source code aspect is relevant. Why does a code object constitute a type? Is this more a 'how do function types work' question or are you doughting the usefullness of this concept for Perl6? The sort function e.g. takes a parameter of type Comparator which is a code type describing instances that accept two parameters of the type that is to be sorted and return a value of a type that describes the relative order implemented by the comparator. Actually the Comparator is usually a parametric type, that is instanciated with concrete types and thus forming a non-parametric code type. The invokation of such a type are the instances of the type. During a sort run many of these instances are created. I can understand there being separate types, perhaps, for Method, Submethod, MultiSub, MultiMethod, and so on, ... and subtypes thereof. but I don't understand the purpose of sharing a namespace between types and function names, What should 'mysubtype' in the following signature sub blah ( mysubtype sref ) { my Int $x = sref( Str, 23, Foo.new ); } mean if not a constraint of the type of sref? Above it is used as a function that accepts (Str, Int, Object) and returns Int. Depending on the definition of ::mysubtype this usage is erroneous or not. I ask myself---or @Larry---how the same effect could be achieved without the indirection through a name. Perhaps: sub blah( Code[Str, Int, Object -- Int] sref ) {...} The same question arises when ::subtype shall be declared: subtype mysubtype of Code[Str, Int, Object -- Int]; subtype mysubtype of Code:(Str, Int, Object) returns Int; nor of having funcitons declare/define/denote/de-whatever types. Here's an attempt of code joke around foo (ignore at will) class foo { submethod postfix:{'( )'} ( $x ) { say $x } } sub foo( foo ) { say foo } sub bar ( foo $foo, foo foo ) { $_ = foo.new; my foo $f = \foo; my foo f = \foo; my foo @f = foo; say foo(23); say .(42); } -- TSa (Thomas Sandlaß)
Re: MML dispatch
chromatic wrote: Why would a class not also define a type? It does. A class is an instance generator. So all instances share the same property of 'beeing instanciated from SomeClass'. This can be used to type them. Question is where this type is placed in the type lattice and how it compares to the type of structurally/semantically identical objects beeing instanciated from another class. My proposal is to hang the type off the top, most unspecific type Any or actually a bit further down, under Object which excludes Package, Module, Class, Grammar and Role. The name of the class is inserted in the appropriate place into the namespace and is available as type parameter for the Ref[::T] role. It is actually quite interesting that there is no special form for compile time object instantiation with the keyword object. class Point { has Num $.x; has Num $.y; } object center of Point # without of we get classless objects { .x = 23; .y = 42; } object pi of Num = 3.14; our Int object answer = 42; say answer; # prints 42 say center.x # prints 23 # and even more our Array object some_values = (1,2,3,4,5); for some_values { say } Hmm, looks somewhat unperlish :)) -- TSa (Thomas Sandlaß)
Re: Referring to package variables in the default namespace in p6
HaloO Matthew, you wrote: I wasn't getting hung up on whether $::($varname) should somehow be cached to avoid a dynamic lookup based on the current value of $varname every time. And I assume that if $*Main::foo hadn't been created, assigning to $::($varname) would create it as expected (again, without any caching of $varname). Here your expectations might be disappointed, sorry. The non-symbolic form $*Main::foo = 'bar' creates code that makes sure that the lhs results in a proper scalar container. The symbolic form might not be so nice and return undef! Then undef = 'bar' of course let's your program die. Unfortunately I'm unsure how the runtime interface to making dynamic namespace entries looks like. Note that the operator ::= acts at compile time, too. My guess is that the compiler collects all potential data items and arranges for auto-vivification and/or autoloading and even on-the-fly instance composition and such like things. But for symbolics this is your task. My confusion initially stemmed from chat on #perl6 about $::Foo and $::('Foo') being Very Different Things - and the fact that there was ever any confusion over whether $::foo was your 'closest' $foo variable or something else. So to conclude, for reading they amount to the same result but through different paths. But since the symbolic lookup might result in undef the behaviour for writing is indeed a Very Different Thing. @Larry, please correct if I gave wrong advice. -- TSa (Thomas Sandlaß)
Re: Do I need has $.foo; for accessor-only virtual attributes?
Larry Wall wrote: has $x; # private rw, no accessors, not virtual, name lexically scoped has $_x;# private rw, rw _x accessor, not virtual, name class scoped Even if I come across as intellectually handicapped but could someone help me over this mental bridge: What is the difference between these two scopes? class Foo { #class scope starts here has $x; # where does this go if not Foo::x has $_y; # this goes into Foo::_y # both $x and $_y can be used in code from here on # and refer to the same two things respectively, right? # or does class scope mean shared by all instances # and lexically scopes per instance? #class scope ends here } Other thinkings: * Any self method can be called via $.x(@args) syntax, short for $?SELF.x(@args). Isn't the code sigil? * All roles can write completely private $x attributes that are not visible outside their lexical scope but are nevertheless per-instance. I understand that correctly, that $x in role Foo { has $x = 7; method foo { $x++ } } denotes a reference to an Item from the data environment of the object that foo is invoked on. The type of the $?SELF that Foo is composed into obviously is a subtype of Foo. What happens with this hidden payload if the object changes its type such that it is no Foo anymore? E.g. by undefining the slot .Foo::foo? Regards, -- TSa (Thomas Sandlaß)
Re: User-defined behaviour of hashes in list context
HaloO Ingo, you wrote: according to Damian [1]...: my %hash = (a = 1, b = 2); my @array = %hash; say @array[0].isa(Pair); # true How can I override this behaviour? class MyHash is Hash { # Please fill in here # my idea is to overload *infix:= multi method infix:{'='} ( Array @a, MyHash +%h ) { # your stuff here ... # in particular you have access to your private attrs # and methods } } my %hash is MyHash = (a = 1, b = 2); my @array = %hash; # should call my own routine I hope the initialisation in my also calls the overloaded operator. But why shouldn't it? -- TSa (Thomas Sandlaß)
Re: MML dispatch
HaloO Larry, you wrote: Implicit is that role distance is N + the distance to the nearest class that incorporates that role for small values of N. If class Dog does role Bark and also does role Wag, then passing a Dog to multi (Bark $x) multi (Wag $x) should result in ambiguity. The interesting question is whether N should be 0 or 1 (or possibly epsilon). If we have multi (Bark $x) multi (Dog $x) arguably Dog is more specialized than Bark, which says N maybe shouldn't be 0. Whether it should be epsilon or 1 depends on how you think of role composition, and whether you think of roles more like immediate parent classes or generic paste-ins. You can think of them as immediate parent classes, but in that case they're actually closer than a real parent class that would have distance 1, since role methods override parent class methods. That argues for N 1. Sorry, has Perl6 now reverted to setting classes above types? I would think that the programmer specifies what type a class implements by letting it do a set of roles. This implies that by default a class does the very unspecific Any. In your example the type system needs the information if Dog does a supertype or subtype. The syntax could be junctive: class Dog does Bark | Wag {...} # union type (least upper bound) class Dog does Bark Wag {...} # intersection type (greatest lower bound) class Dog does Bark , Wag {...} # same as or typeless composition? If Dog is made a supertype then neither multi (Bark $x) nor multi (Wag $x) is in the applicability set. For the subtype case both are applicable and an ambiguity type error occurs. This needs disambiguation through defining multi (Dog $x). The question is at what time this error occurs and what restrictions allow a compile time detection. Note that the ambiguity doesn't go away with a metric approach because there are no other parameters that could compensate. Regards, -- TSa (Thomas Sandlaß)
Re: How do subroutines check types?
Ingo Blechschmidt wrote: How do I have to annotate the type specification in the declaration of the subroutine to not include the class Foo, but only allow instances of Foo? My understanding is that Foo.does(Foo) is false and sub params are checked with .does(). This automatically excludes class args. That is you have to explicitly order them: sub blarb (Foo|Class[Foo] $foo, $arg) # or with CLASS[Foo] ? { ...; # Do something with instance or class $foo } Foo|Class[Foo] is a supertype of Foo and Class[Foo] and as such allows its subtypes Foo and the Class[Foo] parametric role instanciation. Note that Foo|Class allows calls like blarb( Int, HaHa ). Actually I'm not convinced that class Foo should automatically constitute a (proper) type other than Any. But since .does falls back to .isa it comes out the same since the only way here to get a Foo doer is by instanciating the class Foo. -- TSa (Thomas Sandlaß)
Re: More on Roles, .does(), and .isa() (was Re: Quick OO .isa question)
HaloO chromatic, you wrote: Have I mentioned before that I think you should be able to say: class Foo { method foo { ... } method more_foo { ... } } class Bar does Foo { method foo { ... } } ... probably get a compile-time error that Bar doesn't support more_foo()? We've discussed that when I was ranting about the type lattice and co- and contravariance... I'm not sure what my position back then was but now I agree because I see CLASS as a subtype of ROLE. The only problem is that $Larry said that he doesn't want parametric classes. I see a reason to differentiate between roles and classes on the metalevel, but the argument is not as strong on the user-level. I go further to see little reason to distinguish between role, class, and type names (and what reason there is is for introspective capabilities, not standard user-level type checking). I strongly agree. They should share the same namespace. Since code objects constitute types they also share this namespace. This means that any two lines of class Foo {...} roleFoo {...} sub Foo {...} method Foo {...} subtype Foo of Any where {...} in the same scope should be a simple redefinition/redeclaration error. OK, sub and method can escape from this fate by means of the keyword multi and different sigs. Since sigils somehow define references Foo could mean e.g. a classref while ::Foo could be a Code type. If we then also promote . to a primary sigil for Method... hmm have to think about that! -- TSa (Thomas Sandlaß)
Re: MML dispatch
HaloO Larry, you wrote: On Tue, Jul 12, 2005 at 08:13:22PM +0200, TSa (Thomas Sandlaß) wrote: : Actually it's a pitty, that the multi method call syntax isn't as : rich as the single method call syntax where we have .?method, .+method : and .*method. Something like (Snoopy, Mr_PotatoHead, HopeDiamond).*foo : doesn't exist, right? Or is it foo.*(Snoopy, Mr_PotatoHead, HopeDiamond)? It doesn't seem to make much practical sense. Multimethods are generally written to be exclusive of ancestral methods. Ordinary methods are generally written to be cumulative with ancestral methods. Interesting that we are thinking in orthogonal ways. I was arguing for a syntax that allows the caller to prevent 'no method' and 'method ambiguous' errors with .?() and .+() respectively. And .*() would prevent both. In the ambiguous case all applicable targets would be called in an undefined order. Is there also an answer to the odering versus metric question? Why was the former rejected and the latter choosen? -- TSa (Thomas Sandlaß)
Re: MML dispatch
HaloO Damian, thank you very much for your explaination. I just want to hint the Perl6 community to the fact that there exists a US patent on geometric MMD: http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO2Sect2=HITOFFp=1u=/netahtml/search-bool.htmlr=1f=Gl=50co1=ANDd=ptxts1=ferragina.INZZ.OS=IN/ferraginaRS=IN/ferragina I haven't check the relevance to Perl6 yet. Has someone access to the STOC'99 paper? -- TSa (Thomas Sandlaß)
Re: MML dispatch
Mark Reed wrote: And one more dumb question: why is it that the L[1] metric is superior to the L[2] metric for this purpose? I am also interested in the rational behind the approach to manage MMD my means of a metric instead of a partial order on the types. Metric is a geometric concept which in my eyes doesn't fit type theory. I would join Luke and recommend 'pure' MMD. That is there has to be exactly one target that is most specific on all positions relevant for the dispatch. In particular do I dislike the the property of a metric that several smaller mismatches can be compensated by a good match. -- TSa (Thomas Sandlaß)
Re: MML dispatch
Damian Conway wrote: This is a much less dwimmy solution than Yuval's or Luke's, but it has the advantage that those eight steps reduce to eight words: Unique least-inherited most-specialized match, or default Do I read this correctly as dispatching partly in the class hierarchy and partly in the type hierarchy? Or do you mean with 'least-inherited' most specific non-where type and with 'most-specialized' the strictest where clause? To me these two concepts are the same if you think of the does operator as a predicate: multi sub foo ($x where { $x.does(Num) }) {...} beeing the same as multi sub foo (Num $x) {...} -- TSa (Thomas Sandlaß)
Re: How to write a self.pm (Re: method calls on $self)
Autrijus Tang wrote: The compiler, in turn inspect whether there's an bound $_ in scope with $?SELF set. It is not trivial, because this should work: sub baz (c) { c() } method foo { baz { .bar } } # $_ is free in inner closure But this needs to fail: sub baz (c) { c(1) } method foo { baz { .bar } } # $_ is bound in inner closure I might still not understand topic, $_ or lexical vars in general. But why does the fact that c is called with a parameter in the second case and without one in the first example make a difference? Isn't $_ always coming in out of band? So .bar is always invoked on the invocant of foo if we think that there is an implicit $_ := $?SELF before the call to baz in foo. And I hope the binding of $_ to $?SELF is a read-only binding! -- TSa (Thomas Sandlaß)
Re: MML dispatch
Mark Reed wrote: On 2005-07-12 12:22, TSa (Thomas Sandlaß) [EMAIL PROTECTED] wrote: I am also interested in the rationale behind the approach to manage MMD my means of a metric instead of a partial order on the types. Metric is a geometric concept which in my eyes doesn't fit type theory. The geometric interpretation does bring us into somewhat philosophical territory. Not that that's anything new on this list. :) Let me try a concrete example. Suppose that class Answer has subclasses Animal, Vegetable, and Mineral, with respective subclasses Dog, Potato, and Diamond. There are two methods named foo in scope, neither overriding the other. One is declared to take (Animal, Vegetable, Mineral), the other (Dog, Potato, Answer). Assuming the obvious memberships, which method should foo(Snoopy, Mr_PotatoHead, HopeDiamond) call? And more importantly, why do you feel that is the right answer? According to Damian's metric, we have distances of 0+0+2=2 and 1+1+1=3, so (Dog, Potato, Answer) is closer and would get called. Uhh, both targets are applicable but none is more specific on all positions. I would like this to be an ambiguous dispatch error. Actually it's a pitty, that the multi method call syntax isn't as rich as the single method call syntax where we have .?method, .+method and .*method. Something like (Snoopy, Mr_PotatoHead, HopeDiamond).*foo doesn't exist, right? Or is it foo.*(Snoopy, Mr_PotatoHead, HopeDiamond)? -- TSa (Thomas Sandlaß)
Re: Hackathon notes
Autrijus Tang wrote: * deref is now 0-level; $x = 3; $y = \$x; $y++. # now an exception That is because postfix++:(Ref) doesn't exist, right? * sub foo (?$x, ?$Inf) {} my $y = (x = 3); foo($y); # binds $x my $z = (+Inf = 3); foo($z); # binds $Inf Isn't the lhs of = autoquoted? Why does '+Inf' as key bind $Inf? * Constrained types in MMD position, as well as value-based MMDs, are _not_ resolved in the type-distance phase, but compile into a huge given/when loop that accepts the first alternative. So this: multi sub foo (3) { ... } multi sub foo (2..10) { ... } really means: multi sub foo ($x where { $_ ~~ 3 }) { ... } multi sub foo ($x where { $_ ~~ 2..10 }) { ... } which compiles two different long names: # use introspection to get the constraints fooANONTYPE_1 fooANONTYPE_2 which really means this, which occurs after the type-based MMD tiebreaking phase: given $x { when 3 { fooANONTYPE_1.goto } when 2..10 { fooANONTYPE_2.goto } } in the type-based phase, any duplicates in MMD is rejected as ambiguous; but in the value-based phase, the first conforming one wins. I hope that is a temporary solution. Usually one would expect 3 beeing a more specific type then 2..10 irrespective of definition sequence. The upshot is that these are now errors: sub foo ($x) is rw { $x } my $a; foo($a) = 4;# runtime error - assign to constant I assumed lvalue subs would implicitly return void and an assignment goes to the function slot of the args used in the assignment and subsequent calls with these args return exactly this value. In that respect arrays and hashes are the prime examples of lvalue subs. Other uses are interpolated data, Delauny Triangulation etc. Regards, -- TSa (Thomas Sandlaß)
Re: Hackathon notes
Luke Palmer wrote: Anyway, I think that once we start diving inside expressions to measure their specificity, we've gotten too complex to be predictable. Well, we don't have where clauses, but where closures! The former should be a declarative sublanguge like regexps. They are evaluated at compile time or type instanciation time or however it is called and entered into the type constraint environment where the MMD looks for it. For the latter a warning should be produced and they are *not* considered for MMD other than applicability checking. They are of course called for non-invocant params, in assignments etc. For research on the topic see e.g. http://www.cs.washington.edu/research/projects/cecil/www/Papers/predicate-classes.html -- TSa (Thomas Sandlaß)
Re: Type variables vs type literals
idea breaks down. [..] Okay, you've used ::Type as a type variable--now how do you declare that you simply want Type treated as a forward declaration of Type. I'm not quibbling with the desire to bind types to type variables. It's just we've got a conflict in the definition of what :: means that we'll have to resolve one way or another. I don't want value-like type variables because that would generate a big mess if one wanted to store type refs in value vars: my $typeref = $object.type; my ::$typeref $same_type_object; # do we want this? my $typeref $weird; # or even this?? The only use of type variables is in parametric types. And since you want to restrict that to roles the need for implicit type binding shifts onto the does operator and role instanciation. But how automatic will your example role FooStuff[T] { sub foo (T $x, T $y) { } ... } be instanciable? I guess the explicit forms are: FooStuff[Int]::foo(1,2); strfoo ::= (FooStuff[Str].new)::new; # from Autrijus Hackathon notes Will re-instanciation be prevented when the latter is spelled strfoo := (FooStuff[Str].new)::foo; # or with = Actually this syntax might be wrong usage of ::. But do I get you right that the lazy forms are does FooStuff; # lazy role instanciation into current scope foo(1,2); # FooStuff[Int]::foo:(Int,Int) foo(1,'blahh'); # type error? Regards, -- TSa (Thomas Sandlaß)
Re: Submethods
Stevan Little wrote: The concept of non-inherited infrastructural methods is fairly simple to accomplish in the meta-model, by just giving submethods their own dispatch table inside the metaclass. However where I am somewhat confused is in how and when they get called. I think the question is posed a bit confusingly. Since as you point out, when the invocant is clear, calling the (sub)method is an easy lookup in its vtable with subsequent call. Take this example for instance: class Foo { method bar () { ... } submethod bar () { ... } } Is this an error (Synopsis 12 seems to indicate it is *not* an error)? The only inconvenience I see is that the name Foo::bar is not unique. The sigil doesn't disambiguate because in both cases it is Foo::bar. Furthermore the :() is used only to distinguish different sigs, not the Code subtype behind the name. Hmm, or is this a special cased two-entry MMD table? One entry for bar:(Foo) and one for bar:(MetaClass[Foo])? When I call bar() on an instance of Foo, which is called? The method? or the submethod? Is it somehow dependent upon the calling context? (called from within the class, or from outside the class). Take for instance, this example: class Foo { method bar () { ... } submethod bar () { ... } method baz ($self:) { $self.bar() # which one does this call? } } I think this is pretty clear. There is exactly one class object Foo but many instances. The submethod can only be called on the Foo class object which is available through the .meta method. Thus to call the submethod one needs $self.meta.bar(). I doubt the usefullness of falling back to submethod lookup in the class chain when an object doesn't have the method. There's actually no syntactical distinction possible because of: my $object = new Foo; my $meta = $object.meta; $meta.bar() # calls submethod but looks like method call I guess the type of $meta is Ref of Class or somesuch. Regards, -- TSa (Thomas Sandlaß)
Re: Type variables vs type literals
HaloO Larry, you wrote: Well, there's something to be said for that, but my gut feeling says that we should reserve the explicit generic notation for compile time processing via roles, and then think of run-time lazy type aliasing Could you explain what exactly 'run-time lazy type aliasing' is? I mean what does it achieve and how does it compare to type instanciation and parametric contraint checking? as something a little different. So if you really want to write that sort of thing, I'd rather generalize roles to work as modules containing generic subs: role FooStuff[T] { sub foo (T $x, T $y) { } ... } Otherwise people are tempted to scatter generics all over the place, and it's probably better to encourage them to group similarly parameterized generics in the same spot for sanity. It also encourages people to instantiate their generics in one spot even if they're calling them from all over. [..] I think people should say does FooStuff[Int] and automatically alias all the routines to the Int form so we don't have to scatter :[Int] all over. Or if they just say does FooStuff, they get lazily-bound type parameters. I get that right, FooStuff can be instanciated without a class or object? Something like unary operator does? Into which scope do these role instanciations go? Does does *FooStuff[Int] mean global? : ::T $x := $obj; : my T $y = $x; : : The prime use of that feature is to ensure type homogenity for : temporary and loop vars in a certain scope. But the scope in the : above syntax is not apparent enough---to me at least. Actually, I was holding those up as bad examples of scope visibility, so I'm agreeing with you there. (Which is why I suggested that we require a my context, even if only implied by the formal paramter list.) : Thus I opt for an explicit : :subtype T of $obj.type; # or just $obj perhaps? :T $x := $obj; :my T $y = $x; Yuck. I think that completely obscures the lazy type binding. Plus you've managed to omit the my, so you've created a global subtype T. (Unless, as I'm leaning towards, we make such bare inner types illegal, and require my, our, or *.) The only thing I did was to replace the :: sigil with a subtype declaration. Does subtype always go into global scope? I thought that it requires a *name to go into global and our to go to the innermost module---or was that package? I mean even non-declared auto-vivified vars go into the immediately surrounding scope, or am I horribly mistaken? sub foo() { if (1) { $x = 'from above' } if (2) { say $x } # prints 'from above' even if no outer $x exists? say $x; # prints undef or 'from above' if outer $x } Up til now I assumed that ::T and plain T mean exactly the same if T is pre-declared/defined. The type sigil is only needed to defer the definition/binding. In a certain sense this is a hanging type reference similar to foo beeing a reference to Code. Which brings me to the question how to bind a type reference. I mean we have my fooref := foo which allows fooref() calls, right? How are type references derefed if not by dropping the sigil? ::TypeRef() perhaps? my ::TypeRef; # type variable? sub make ( ::Type, Type $value ) returns Type { if (::TypeRef != ::Type) { ::TypeRef = ::Type; } my Type $x; $x = $value; return $x; } my $i = make(Int, 17); my @a = make(Array, [1,2,3]); # single element array? # or three element array? my $e = make(Int 'string'); # type error in make? With the automatic binding of a ::Type variable to the type of it's argument the definition of make could be shortend to sub make ( ::Type $value ) returns Type { ... } and called like this my $i = make(17); which at least prevents type errors ;) Regards, -- TSa (Thomas Sandlaß)
Re: Time::Local
Juerd wrote: I think the problem one has is much bigger even if a day *number* is ever displayed. Then beginning with 1 because that's where most humans begin counting, is wrong. It's a technical thing, and that should be kept as simple as possible, and as technical as possible, for easier compatibility with existing technical things. As a technical remark I like to point out, that you need 8 time points to define 7 days. Every day is bounded by two such time points---which are of course 24 hours apart. This is necessary to get the arithmetic right! Weekday arithmetic is modulo 7. Or put differently $week.end() - $week.start() == $week.length == 7 days must hold. If e.g. you start your week with Monday than this becomes $Sunday.end() - $Monday.start() == 7 days. The next order of precision in calender arithmetic is the hour *within* the day, then minutes and seconds. The weeks themselfs are subdivisions of years. And the scheme is not completely regular in e.g. the Gregorian calendar---but almost e.g in the Sym454 calendar which only has leap weeks. I think, that this type of integer with remainder arithmetic shows up in Perl6 in other places as well. E.g. chars in strings depending on the Unicode level and index arithmetic of arrays. Some unification of the underlying math would be nice, indeed. And that typically involves starting from 0 and the positive remainder pointing into the day. Regards, -- TSa (Thomas Sandlaß)
Re: Type variables vs type literals
HaloO Larry, you wrote: On Thu, Jun 30, 2005 at 09:25:10AM +0800, Autrijus Tang wrote: : Currently, does this: : : sub foo (::T $x, ::T $y) { } : : and this: : : sub foo (T $x, T $y) { } : : Means the same thing, namely : :a) if the package T is defined in scope, use that as the : type constraint for $x and $y : :b) otherwise, set ::T to be the most immediate common supertype : of $x and $y. : : Is this understanding correct? I'd like to disambiguate the two cases : by making ::T in parameter list to always mean type variable (sense b), : and the bare T always mean type name (sense a)? I think it would be good to distinguish those, but I've been mulling over whether ::T should be the syntax for b. (And also whether b is the correct way to think about it in Perl 6.) The problem with using ::T for autovivify your type from the argument is that ::($x) doesn't mean that, and it looks like it should. I think the point is that using a type variable in the signature of a sub is too subtle for recognizing it as a type function that produces typed subs. Thus---even if it resembles C++ templates---I suggest to put the type parameters onto the sub: sub foo[T] (T $x, T $y) { } which basically constrains $x and $y to have the same type. A call to foo might automatically instanciate appropriate implementations. With MMD and all methods and attributes beeing virtual this could usually be a no-op as far as the code generation is concerned. But the type checker has to know what constraints are in effect. The syntax for explicit selection could be foo:(Int)('3','2') which prevents the interpretation foo:(Str,Str). OTOH, this might overload the :() too much. Could we invent more colon postfix ops? Thus the above were foo:[Int]('3','2'). And while we are at it since () is more call-like and [] lookup-like we could reserve :() for more complicated type literals and use :[] for formal type signatures on subs as it is the case for roles. The :: does imply indirection of some sort in either case, but it's two very different kinds of indirection. ::($x) can't declare a lexical alias for some type, whereas ::T presumably could, though your formulation seems more of a unificational approach that would require ::T everywhere. In other words, if we do type binding like b, we would probably want to generalize it to other binding (and assigning?) contexts to represent the type of the bound or assigned object, and at the same time create a lexical alias for the bare type. So we might want to be able to say ::T $x := $obj; my T $y = $x; The prime use of that feature is to ensure type homogenity for temporary and loop vars in a certain scope. But the scope in the above syntax is not apparent enough---to me at least. Thus I opt for an explicit subtype T of $obj.type; # or just $obj perhaps? T $x := $obj; my T $y = $x; With my proposal from above the short form could be :[T] $x := $obj; my T $y = $x; or the current form with :() :(T) $x := $obj; my T $y = $x; Regards, -- TSa (Thomas Sandlaß)
Re: return() in pointy blocks
Larry Wall wrote: On Wed, Jun 08, 2005 at 12:37:22PM +0200, TSa (Thomas Sandlaß) wrote: : BTW, is - on the 'symbolic unary' precedence level : as its read-only companion \ ?. No, - introduces a term that happens to consist of a formal signature and a block. There are no ordinary expressions involved until you get inside the block. (Or set a default on one of the parameters, to the extent that those are ordinary expressions.) So without a block there is a syntax error? $x = - $y; Or could this be understood as a short form of $x = - { $y } # $y from outer scope I still think the pointy looks really cute as a prefix operator for constructing rw refs. Especially if we use () to evaluate the blockref returned. For plain variable assignment this is not overly usefull because it amounts to the same as $x := $y; but in lists it is quite nice %h = { foo, 'bar', blah, - $y }; or not? %h = { foo = 'bar', blah = - $y }; hmm, can the following be interpreted as spoiling pair notation? %h = { :foobar, :blah - $y }; # would blah- $y parse at all? I think not because this works %h = { :foobar, :blah{- $y} }; Regards, -- TSa (Thomas Sandlaß)
Re: reduce metaoperator on an empty list
Damian Conway wrote: Let's assume that op is overloaded for two completely unrelated types A and B, which are both defining their respective identity elements but !(A.identval =:= B.identval). How should the op multi method object pick the correct one *without* looking at $value's type? Your mistake is in thinking that the identity trait is on the operand type. It isn't; it's on the operator itself. I agree, that the pair of operator and type which determines the identity element can be stored as a trait of the operator implementation. *But* the operator selection from the multi has to use the type of $value. In particular it might not be inferable at compile time. Thus the compiler has to produce MMD code and hook half way into it to perform the selected call with two args: the identity op.identval and $value. Which brings me to the question: is there a syntax to invoke the target selection from a multi? E.g. op.select($value,$value) here? Or is it op:($value,$value)? -- TSa (Thomas Sandla)
Re: Ignoring parameters
Damian Conway wrote: No. That needs to be: method greet(FooClass ::class:) { say Hello!; } (as implied by takes a class as its invocant in S12). ^ Ohh, does that mean that ::class can be used as a type inside the body? E.g. method template ( FooClass ::foo :) { my foo $f; ... # use $f } -- TSa (Thomas Sandla)
Re: MMD vs. anonymous parameter types referencing earlier parameters
Chip Salzenberg wrote: This: multi sub is_equal(Integer $a, Integer where { $_ == $a } $b: ) { 1 } hurts. At least as I've been given to understand it[*], is impossible to implement, because the second parameter's type can't be precalculated in order to prepare for MMD dispatching. Quite interesting that Cecil already has it. The thing is called Predicate Dispatch and there exist efficient implementation strategies. And it is possible to calculate a static supertype of the above, which is is_equal:( Integer, Integer : ). In short, $b has no pre-calculable type. And you can't calculate the MMD potential of a subroutine unless you know the actual types of its MMD-participating parameters. I don't know what 'MMD potential' is. (This also means that the type of is_equal:(...) is impossible to express, unless I greatly misunderstand the foo:() syntax. But it doesn't matter what you call it if you can't call it.) The syntax might just be: is_equal:(Integer $a, Integer where { $_ == $a } :) The only point is that I see no way for the compiler to optimize to anything but a dynamic dispatch. Thus a more declarative style of predicate specification would be helpfull. PS: Of course this example also implies that each parameter's declaration introduces a new lexical scope to its right. Well the colloquial spec of your function is just 'it takes two equal integers'. And the two element list (3,3) is a subtype of it. Regards, -- TSa (Thomas Sandlaß)
Re: MMD vs. anonymous parameter types referencing earlier parameters
Chip Salzenberg wrote: Link link. http://www.cs.washington.edu/research/projects/cecil/www/Papers/gud.html In case it matters, we're trying to support the Perl 6 semantics of both ($a:$b:) and ($a,$b:). The former looks like something that could be implemented with something called predicate dispatch, but the latter I'm not so sure of. I never understood the difference. So if someone were so nice to enlighten me... (This also means that the type of is_equal:(...) is impossible to express, unless I greatly misunderstand the foo:() syntax. But it doesn't matter what you call it if you can't call it.) The syntax might just be: is_equal:(Integer $a, Integer where { $_ == $a } :) It's a new type object every time, so every time you run that code you get a new type object to describe $b, and therefore the type object of the expression will never match up with the one used in the function definition. Hmm, looks like we have very different views of how dispatch works and what the acting entitys are. To me is_equal is an object that knows a set of targets basically indexed by their :() --- let's call that the implementation signature. The call site knows the list of parameters and is_equal. From this information a set of applicable targets is calculated. This is the first time that the where clause comes into play. If it returns false, that target is not considered any further. When it returns true the closure comes into play when the most specific target is determined. The value and type of $a are known and as such constrain the type of $b and produce a more specific match then an unconstrained Integer. In other words the type of $b is a parametric, single value subtype of Integer. Are you suggesting that type equivalence tests include introspection into the semantics of the closure? No. I just think that the closure is called at dispatch time as discribed above and that this is the very moment when the instanciation of the parametric type of $b takes place. If so, what is close enough? If not, how can Parrot ever know that Integer where { $_ == $a } is the same as Integer where { $^foo == $a } but different from Integer where { $_ != $a } It doesn't. The Code object stores the targets and the respective closures. ? Down that path lay madness.[*] MMD becomes MAD ;) s/the compiler/Parrot/, since the specific multi implementation can be introduced after the call is compiled. Yep, but the type system is still there. And you are right, that there is no chance in pre-calculating such dispatches. But that is the expected price to pay for predicate dispatch. And the target selector living inside the MMD object might actually be 'recompiled' during runtime when new instances are added. That is similar to the automata behind regular expressions. Regards, -- TSa (Thomas Sandlaß)
Re: reduce metaoperator on an empty list
Edward Cherlin wrote: That means that we have to straighten out the functions that can return either a Boolean or an item of the argument type. Comparison functions = = = != should return only Booleans, I'm not sure but Perl6 could do better or at least trickier ;) Let's assume that = = when chained return an accumulated boolean and the least or greatest value where the condition was true. E.g. 0 2 3 returns 0 but true 1 2 1 returns 1 but false 4 5 2 returns 2 but false Then the reduce versions [] and [=] naturally come out as min and strict min respectively. Is it correct that [min] won't parse unless min is declared as an infix op, which looks a bit strange? if 3 min 4 { ... } -- TSa (Thomas Sandla)
Re: reduce metaoperator on an empty list
HaloO Larry, you wrote: : Might I add that it should read : : $var = (op.does(identval) ?? : op.identval($value) :: undef) op $value; : : The rational is, that op is subject to MMD, so the .identval method : should be dispatched as well. Actually op.identity($value) reads : quite natural and self documenting if the parameter is required. I don't think there's a double dispatch there. What do you mean with double dispatch? A single MMD on two arguments or two dispatches after each other? I think op just knows it can default its left argument to an existing attribute value if it (somehow) knows it's part of an assignment op. There's not a lot of payback in getting all abstract here, as far as I can see. Let's assume that op is overloaded for two completely unrelated types A and B, which are both defining their respective identity elements but !(A.identval =:= B.identval). How should the op multi method object pick the correct one *without* looking at $value's type? Or does the indentval role force their takers to provide all infix ops with a test for undef args and a fallback to the respective identity value? If that is the case, the test for the role is superfluous. Or is the intent to enforce a unique identity value for each operator like 0 for + and 1 for *? There's actually a second problem. Will the op.does(identval) condition be true or false if the op multi contains some targets with and some without an identval? Finally I don't understand how the knowledge about a pending assignment eases the choice problem for the multi. Note that the choice of assignment operator depends on the return value of the operator and the type of which the lhs is undef. Regards, -- TSa (Thomas Sandlaß)
Re: return() in pointy blocks
Luke Palmer wrote: Says not: Boo Boo Boo ... This is clear, but I would expect the output Boo 42 because the return value of foo is a ref to a block that makes the caller return 42. This is written in my current Perl6 as foo:( : -- Block -- 42) The question is when exactly this call chain is invoked: 1) when it is assigned to $code? Or, 2) when postfix:( ) is invoked on $code? I prefer 2) because it better fits my understanding of referential semantics. About the relationship to the lazy versus eager trade-off I'm unsure. So 1) is also a good choice. With this in mind, I wonder how \ and - are related. Is $x = 3; $rw = - $x; valid syntax? And does it mean that $rw = 7; say $x; # prints 7 This can be construed as the eager version of $x = 3; $rw = - { $x }; $rw = 7; say $x; # means: say $x(); A block in a chain of references is a stop mark in a chain of refs. $x = 3; $r = - $x; $rr = - $r; say $rr(); # prints 3, because say $r; also prints 3 $rr = 7; say $r; # prints 7 say $x; # prints 3 Looks like we have found a candidate for the transparent ref creator! And I hope Juerd likes it. After all it looks *pointy* :) PS: A chain of refs can thus be reduced to the leaf lvalue with ([()] $rr) = 23; which stores a new value in $x. This might even warrant the special case of ([] $rr) = 23; -- TSa (Thomas Sandlaß)
Re: reduce metaoperator on an empty list
Damian Conway wrote: So, to clarify again, if $var is undefined, then the assignment: $var op= $value; is equivalent to: $var = (op.does(identval) ?? op.identval() :: undef) op $value; Correct? Might I add that it should read $var = (op.does(identval) ?? op.identval($value) :: undef) op $value; The rational is, that op is subject to MMD, so the .identval method should be dispatched as well. Actually op.identity($value) reads quite natural and self documenting if the parameter is required. Hmm, the MMD form identity( op, $value ) looks even better. This folds the identity value selection problem back into type-space and it's runtime agent MMD. -- TSa (Thomas Sandlaß)
Re: return() in pointy blocks
Well, does using - as blockref creator also give anonymous scalars? $y = - $x { $x = 3; $x }; # $y:(Ref of Block of Int) BTW, is - on the 'symbolic unary' precedence level as its read-only companion \ ?. Are they pure macros? -- TSa (Thomas Sandlaß)
Re: return() in pointy blocks
Piers Cawley wrote: My preference is for: Boo Boo Can't dereferene literal numeric literal 42 as a coderef. How do you reach the second 'Boo'? Iff - does not create a Sub but a Block instance then Luke's code can be interpreted as a much smarter version of sub foo() { enter: 42; if $?RETURN_LABEL { goto $?RETURN_LABEL } return; } say Boo!; say goto foo::enter; # goto sets up $?RETURN_LABEL say after goto; which of course prints Boo 42 after goto The smartness is in the value that prefix:{'-'} returns while in the snippet above it is explicitly coded. Or do I completely misunderstand the distinction between blocks and closures? -- TSa (Thomas Sandlaß)
Re: return() in pointy blocks
Piers Cawley wrote: TSa (Thomas Sandlaß) [EMAIL PROTECTED] writes: Piers Cawley wrote: My preference is for: Boo Boo Can't dereferene literal numeric literal 42 as a coderef. How do you reach the second 'Boo'? Iff - does not create a Sub but a Block instance then Luke's code can be interpreted as a much smarter version of I really wish you'd quote in more detail, it makes it a real PITA to go back and find the explanatory code. Sorry, but I try to quote only the text that I'm really referring to, not the transitive closure of the thread at that point. If I cut too much here, I apologize. sub foo () { return - { return 42 } } What I do not understand right now is, how the first return is handled. As Luke pointed out, the inner return inevitably makes the current invocation of foo return. But you argue, that - suspends the current invocation of foo and returns it as continuation. How does that fit the pointy sub of a for loop? Is the surrounding sub suspended as well? And then one could continue right there? sub forfoo () { for 0..9 - $x { return $x; } } my $y = forfoo(); # suspends forfoo in first loop? say $y; # prints 0, and suspends forfoo in second loop say **$y; # prints the remaining invocations of forfoo? I figure that the implementation is actually straight forward. The pointy sub catches the return exception and handles it by suspending forfoo and returning the resulting continuation. my $code = foo(); # ^--- continuations points to the RHS of the assignment say Boo!; $code(); So, this is what happens. 1. foo() returns a coderef to the RHS of the assignment. 2. The coderef gets assigned to $code. 3. say Boo! 4. We invoke the coderef, which returns 14 to continuation which was current when it was created. 5. That means 42 gets returned to the RHS of the assignment 6. say Boo! 7. Try to invoke the literal 42. Hmm, I see in both cases an MMD to postfix:( ) with the then current value of $code as invocant. In the first run the target is postfix:( ):( Ref of Block :) and in the second case it's postfix:( ):( Int :). If the latter is defined to die, so be it. I opt for just returning the value. Which produces the fallout that $y = 42(); Is first of all valid syntax, and dispatches at runtime unless the compiler can proof at compile time that there can't possibly be an implementation at runtime. Thus one could write: multi sub *postfix:( ) ( 42 ) # or ( Int $x where $x eq '42' ) { return 66; # == hex 42 } A pragma like 'use hexliterals' might actually implement a general version of this idea. -- TSa (Thomas Sandlaß)
Re: return() in pointy blocks
Piers Cawley wrote: [..] then I think it means we can write: sub call-with-current-continuation(Code $code) { my $cc = - $retval { return $retval } For the records: the return here is the essential ingredient, right? Without it the block would be evaluated or optimized away to an undef or some such. $code($cc); } Which I personally think is rather cute. Me too! Even if I can't quite bring myself to believe it's that simple... I have convinced myself. How can I be of assistance on your side? -- TSa (Thomas Sandlaß)
Re: Transparent / Opaque references
Juerd wrote: $y() = 7; No, sorry, that looks to me as if $y is a reference to an lvalue sub, not like any form of referencing of scalars. I think it will come naturally to the C++ and Java folks. There the accessor kind of functions is either mapped into the name get_y() and set_y(value), or operator () is overloaded. In the latter idiom assignment actually becomes $y(7). Which might be a bit far out for Perlkind. But OTOH it looks like a function call... This idiom looks better with scalar attributes of objects: $obj.attr() = 7; # parser supports to drop the .() and $obj.attr(7); # beware, attr becomes 7 if the class of $obj works as such And it nicely gives: $y = \$obj.attr; $y() = 7; # dereffed assignment $y = 13; # detaches from $obj.attr say $obj.attr; # prints 7 I'm not sure but in Perl5 the equivalent to the second line above is $y- = 7; # postfix - is now spelled () isn't it? -- TSa (Thomas Sandlaß)
Re: (multi)subroutine names
Rod Adams wrote: It used to be fooArray,Int fooHash,Int And has become foo:(Array,Int) foo:(Hash,Int) The return type arrow -- inside the :() type spec is not yet approved by @Larry. In my mind, the more interesting question is what does foo without the specifiers return when foo is multi? I see the following three options: 1) undef/error, since there's no single sub called foo, and multi's need a postfix . This applies only if you want to by-pass actual dispatch by selecting a sub yourself. Otherwise foo is an instance of the class/type MultiMethod which is a subtype of Sub and Method, which in turn are subtypes of Code. 2) the name 'foo', and then performs in effect call by name when deferenced, using the dereferencing scope to determine which flavors of foo are available at this time, and dispatching accordingly. I'm unsure how much the Perl6 semantics depend on name lookup when no explicit symbolic expression ::('foo') is used. But that aside I think the type is enough information to handle a value. So foo is typed foo:(MultiMethod) or foo:(Ref of MultiMethod). This latter thing is another open question on my end: the referential semantics. E.g. are *all* plain sigil expressions :(Ref of ...) and need an implicit or explicit dereferencer? 3) a dispatch table of all the foo's currently in scope at the time the reference is made. Yes, that's it. But note that it's not a passive table that the caller needs to handle correctly. MMD is about basing the decision which implementation of a signature to call on the runtime types in the argument list. Without multi this degenerates to a mere type compatibility check for subs. A direct extension of the above is that the type system might be able to dynamically instanciate parametric types to fill 'gaps' dynamically. Something like 'compilation on demand' if that is the only way to actually instanciate a template---but I'm not sure if Perl6's parametric types are actually called templates. I hope that helps. -- TSa (Thomas Sandlaß)
Re: comprehensive list of perl6 rule tokens
Patrick R. Michaud wrote: Of course, there are other implicit parameters that are given to a rule -- the target string to be matched and an initial starting position. But I think some of those details are still being worked out. Wasn't it said that rules have the current match object/state as invocant? I would assume that everything else can be found through it? Actually the mnemonics that $/ is the match and methods on $?SELF are called with ./method fits. The only remaining thing is to define the method set of the Match class. -- TSa (Thomas Sandlaß)
Re: Empty hash
Luke Palmer wrote: Should {} be an empty hash rather than an empty code? Does it matter? More interesting is the question what it returns or evaluates to if it's a block. Actually with my idea of List beeing a subtype of Code the parse time recognition of blocks as List of Pair has no implication for the semantics! It falls into the category of optimizations that can be performed if the involved types can be determined at compile time. Thus assigning that to a plain % sigiled variable expression would kick out the previous content and store a freshly created undef under a key calculated from the incoming undef. Which in my eyes is pretty useless. In particular if the outcome is that +%hash == 1 instead of defining that %hash = {}; clears the content of the hash and that +%hash == 0. But the fans of extra levels of indirection in the @array case might like to get a default key like '' or 0 beeing used, such that the particular undef from the {} of the rhs of the assignment can be retrieved with %hash00. For an arbitrary undef any non-existing index suffices :) Why did we change { %hash } from making a shallow copy of a hash to the code that returns %hash? Sorry, I don't understand this question. Do you want 'shallow copy' to mean 'take a ref'? Or Parrot/Pugs level COW? Are you alluding to the referential semantics discussion? -- TSa (Thomas Sandlaß)
Re: Transparent / Opaque references
Luke Palmer wrote: When we heard that Larry didn't acutally want $$foo to infinitely dereference, some of us were overjoyed, and others severely disappointed. Both transparent dereferencing (infinite $$foo) and opaque dereferencing (one-level $$foo) have their uses, but they are definitely distinct. I guess a syntax like the reduce meta operator [$]$ref = whatever(); doesn't work for the $ sigil because it firstly is no operator and secondly unary. So I join the single $-single-steps-party. Might it be applicable to use .() as the dereferencer of scalar variables that derefs to the next none(Ref) type and if that is a Code it dispatches to it as expected? This nicely gives: $x = 3 $y = \$x; $y() = 7; say $x; # prints 7 $y = 23; # detaches from $x say $x; # still prints 7 One detail is that lvalue subs without params must be taken care of. But they'll have a proxy anyway to handle assignment. Another general thing is of course that explicitly constant Refs shall not be applicable as a lhs of assignment. This applies to chains of prefixed $ as well. -- TSa (Thomas Sandlaß)