Re: r25182 - docs/Perl6/Spec
Em Qua, 2009-02-04 às 16:45 +, Aaron Crane escreveu: pugs-comm...@feather.perl6.nl writes: +=item method Int read($buf is rw, int $length) I'm not sure that using a native int is the right thing here. If whatever the implementation uses as int is narrower than size_t, that forces the programmer to use an Int and do the necessary loop. native int can't be undefined, failures are undefined. The use of Int here is to support it returning unthrown exceptions. +=head2 IO::POSIX + +Indicates that this object can perform standard posix IO operations. I don't like that wording, but getting it right seems tricky. The problem is that I don't think you mean for IO::POSIX to contain methods corresponding to POSIX-ish read(2), write(2), given that methods of those names exist in other roles. But those are precisely what I'd think of as most obviously falling into the category of standard POSIX I/O operations. That actually surprised me, for some reason I did think read and write were standard C, not POSIX (that's what happens when you don't have experience in non-unix OSs). And maybe you're indeed right, since you can change the way you access a file in POSIX, it would be strange to de-compose a Writeable role if you change the way you access the io. but having separated roles for read and write would make it easier to implement application level io objects (not backed by operating system file descriptors). That probably means IO::POSIX does IO::Readable does IO::Writeable. +=item method Bool flock(:$r,:$w) I realise this part of the specification still seems to be at the stub stage, but I'll note that: Yes, it was meant purely as an example, a more carefull planning of that would be needed. daniel
Re: r25172 - docs/Perl6/Spec
Em Ter, 2009-02-03 às 10:34 +0300, Richard Hainsworth escreveu: f) radical suggestion: if the syntax '=$filehandle' lazily takes something from the file handle, then $filehandle = output; should send something to it. Problem is that this meeses up with assignment, which is an operation in the container, not on the value, but... $output == =$input works just fine (sending one line of $input to $output), as well as $input == $output which would connect those filehandles We would also have $filehandle = map { s/ html_entities / %html_entities/ } @lines; as a filtering idiom. Still using feed operators $output == map { s/ html_entities / %html_entities/ }, @lines; daniel
Re: r25172 - docs/Perl6/Spec
Em Seg, 2009-02-02 às 09:37 -0800, Larry Wall escreveu: It's also not clear how this should interact with buffering systems like stdio. But in any case, speaking directly to the IO stack is likelier to give consistent results than playing mix-n-match with various calls on the IO stack that make various assumptions. The question here is, will Perl 6 IO use stdio.h or re-implement its features? My first shot at it would be... role IO { has $.fd; } role IO::Blocking { has Bool $.blocking; } role IO::Closeable { method close {...} } role IO::Readable { # no buffer method int read($buf is rw, int $count) {...} } role IO::Writeable { # no buffer method int write($buf, int $count) {...} } role IO::Buffered { # buffer has Bool $.autoflush is rw; method flush {...} } role IO::Char does IO::Buffered { method getc {...} method fread {...} ... }
Re: r25172 - docs/Perl6/Spec
Em Seg, 2009-02-02 às 13:51 +0100, Leon Timmermans escreveu: On Mon, Feb 2, 2009 at 1:05 PM, pugs-comm...@feather.perl6.nl wrote: -the latter case C$! is set). +the latter case C$! is set). The C:async flag lets the call +return an undefined value if no character is immediately available. IMHO it would be better to call that non-blocking IO instead of asynchronous IO, but I'm POSIX-biased. Agreed, it would be async if that was a request for a character that would be replied using some other call, in that case it is non-blocking read. But I should argue that it should be a property of the IO object, not of every individual method call.. daniel
Re: r25172 - docs/Perl6/Spec
Em Seg, 2009-02-02 às 15:12 -0800, Larry Wall escreveu: Roles are good, but what is this Char thing of which you speak? It seems good neither for Unicode characters nor for keystroke sequences. :) I meant exactly in the sense of providing one of those abstractions, let me rephrase it: role IO::Unicode { method getc {...} method readline {...} } role IO::Term { method get_keystroke {...} } On this non-blocking keystroke thing, I see a P6ish solution more like: get_keystrokes() == my @available; # time passes if @available { ... } That is, use the async capabilities already built into the language. (That's assuming the boolean value of @available doesn't block on the state of the feed. If it does, we need some other way of expressing that test. @available.now or some such.) while the syntax solution is cool, it doesn't actually solve anything, because in the end it needs to be resolved to some method call in some object. But I see what you mean... The problem is that iterators are not about beign async or blocking, they're just about measuring how much you consume of the stream, which means that an Iterator still needs to be async for look-aheads and do blocking IO if it fells short of data. That actually remembers me of the idea of auto-threading IO and making it async. Let me try to make some example code of a HTTP handler: my $io = Net::TCP.listen(:hostlocalhost, :port(1234)); $io does IO::Async[EV]; $io.accepts: - $conn { my %headers; my $data; my $waiting_headers = 1; for =$conn - $line { if ($line $waiting_headers) { my ($name, $val) = split(/\s*:\s*/, $line); $headers{$name} = $val; } elsif ($line) { $data ~= $line; } else { $waiting_headers = 0; } } $conn.write(200 OK\n\nSucessfull request\n); }; EV.loop; This could autothread the code received by accepts, using async IO. About one and a half years ago you sent me a paper about something like that in haskell. daniel
Re: Writing to an iterator
Em Qui, 2009-01-08 às 13:42 +1100, Timothy S. Nelson escreveu: On Wed, 7 Jan 2009, Jon Lang wrote: How would I define the method for writing to an iterator? I guess I'd assumed that writing to an iterator wouldn't be possible, as there are kinds of iterators where writing to them makes no sense; I'd assumed that if you wanted to write to something you'd use a list. Other than as an interesting exercise, I don't see the point of using an iterator for this purpose (there may *be* uses, but I don't see them). There is at least one use: Some databases (berkeley db comes to my mind) allow you to perform inserts using a cursor (which would be an iterator in this case). The Java API also provides a insert mechanism... Although in some cases, the update API will be specific to the object you're dealing with, it can just be a regular object which happens to implement the Iterator role... daniel
Re: returning one or several values from a routine
Em Seg, 2009-01-05 às 20:32 +0100, Moritz Lenz escreveu: Daniel Ruoso wrote: would force item context in the capture, and here is the problem, as a capture in item context was supposed to return the invocant. Maybe we could have a different rule for captures in scalar contexts that don't have an invocant? I've just realized we were missing some spots, so remaking the list of possibilities my $a = sub s1 { return a = 1 } my $b = sub s2 { return a = 1, b = 2 } my $c = sub s3 { return 1, 2, 3, a = 1, b = 2 } my $d = sub s4 { return 1 } my $e = sub s5 { return 1, 2, 3 } my $f = sub s6 { return 1: # it doesnt matter } my $g = sub s7 { return } But while writing this email, I've realized that a Capture object is supposed to implement both .[] and .{}, so maybe we can just simplify... $g is an undefined Object $f is 1 $d is 1 $a is a Pair everything else is the Capture itself daniel
Re: returning one or several values from a routine
Em Ter, 2009-01-06 às 11:28 -0800, Jon Lang escreveu: Of course, that's only a third of the problem. What should people expect with each of these: Hmm... I think that takes the discussion to another level, and the question is: what does a capture returns when coerced to a context it doesn't provide a value for? The easy answer would be undef, empty array and empty hash, but that doesn't DWIM at all. The hard answer is DWIM, and that can be: 1) in item context, without an invocant a) if only one positional argument, return it b) if only one named argument, return it as a pair c) if several positional args, but no named args, return an array d) if several named args, but no positional args, return a hash e) if no args at all, return undefined Object f) return itself otherwise 2) in list context, without positional arguments a) if one or more named arguments, return a list of pairs b) return an empty list otherwise 3) in hash context, without named arguments a) if there are positional arguments, return a hash taking key,value. if an odd number of positional arguments, last key has an undef Object as the value and issue a warning. c) return an empty hash otherwise daniel
Re: rfc: The values of a junction
Em Seg, 2009-01-05 às 07:57 -0800, Dave Whipp escreveu: my $ace = 1 | 11; my $seven = 7; my @hand = $ace xx 3, $seven; my $junc_value = [+] @hand; ## any( 10, 20, 30, 40 ) There are a bunch of possible values in the junction. The one we care about is the largest that is not greater than 21. Using Perl6 as it stands today, the way to extract this value is brute force: my $concrete_value = max (0..21).grep: { $^score == $junc_value }; Well, that considering we don't have any introspection into junctions, but I think it should be quite straight-forward to make junctions behave as a list of its members... my $ace = 1 | 11; my $seven = 7; my @hand = $ace xx 3, $seven; my $junc_value = [+] @hand; my $concrete_value = max $junc_value.grep: { $^scope 21 }; daniel
Re: use semantics
Em Dom, 2009-01-04 às 14:53 +0100, Carl Mäsak escreveu: $ parrot languages/perl6/perl6.pbc --target=pir --output=B.pir B.pm $ parrot languages/perl6/perl6.pbc --target=pir --output=A.pir A.pm Remember, remember, the fifth of November current instr.: 'die' pc 14950 (src/builtins/control.pir:204) [...] I might be wrong, but it looks like the consequence of the reasoning I made in the other post, the problem is that, in order to import B in A, B needs to be initialized, and as B init fails, the compiling of A fails. This is not simply a rakudo bug, but rather a conceptual problem in the way BEGIN, INIT and use are related. daniel
Re: Coroutines in Perl 6 (Was: Re: Converting a Perl 5 pseudo-continuation to Perl 6)
Em Sex, 2009-01-02 às 08:34 -0300, Daniel Ruoso escreveu: token routine_def:coro {...} Actually, I was just looking at STD, and the correct token would be token routine_declarator:coro { sym routine_def } I was also looking at the spec files, and I realized that DRAFT S17 mentions coroutines, but its definition is a bit different then the one I suggested, and the example poses a good reason: coro dbl { yield $_ * 2; yield $_; }; (1..4).map:{ dbl($_) } # should result in 2 2 6 4 This example suggests that it will not install an alias in the caller scope, but the code object itself stores its state. The other difference is that falling out of a coro makes it restart immediatly without returning any value (this one is a bit weird, I'd expect it to return the last statement on the routine as well). But one way or another yield (yes, I wrote it wrong in the previous post) is still implemented as a control exception that is caught by the implicit CONTROL block of the coro. daniel
Coroutines in Perl 6 (Was: Re: Converting a Perl 5 pseudo-continuation to Perl 6)
Em Qui, 2009-01-01 às 12:34 -0800, Geoffrey Broadwell escreveu: In the below Perl 5 code, I refactored to pull the two halves of the PID file handling out of init_server(), but to do so, I had to return a sub from pid_file_handler() that acted as a continuation. The syntax is a bit ugly, though. Is there a cleaner way to this in Perl 6? Well, If the STD Perl 6 doesn't support that, you can always declare a sub-grammar that implements a token routine_def:coro {...} then you have something in the lines of: coro pid_file_handler { ... # first half yeld $something; ... # second half } It's even easy to implement how it should work. Basically, yeld throws a resumable control exception, the implicit CONTROL block of the routine will then contain the code to handle that exception by aliasing the coro in that state in the caller lexical scope, overriding the current definition. And once the routine is called again, and returns or leaves, you simply re-binds to the original routine. The above solution assumes a coro state is only available in the same lexical scope as the first call, which may be a good idea to avoid action-at-a-distance. But maybe we even convince larry to push that into STD... since it's such a nice feature... daniel
Proposal: receiving arguments without enforcing context
Hi, Captures are sensitive things, they can only be used as-is inside a scalar, otherwise you have to enforce a context and it is no longer a capture, but one of the views of its content. for instance... sub foo { ... return @thingy, :named($value); } sub bar($capture) { my $named := |$capture; my @things := |$capture; ... } bar(foo()); The problem with the above code, is that the :($capture) signature, already enforces item context, and therefore the two statements in sub bar will simply fail. That being said, I'd like to suggest a new syntax: sub bar(\$capture) { ... } This syntax will mean that you want that positional argument without forcing any context. This is something different from sub bar(|$capture) { ... } which takes the entire capture sent to that invocation and store in the variable, the proposed syntax would allow: sub foo { return 1,2,3; } sub bar(\$capture, $other) { ...; } bar(foo(), somethingelse); This need came out because of method postcircumfix:( )($capture) we need to receive the positional argument for .() without forcing the context. I understand this method used to have a (|$capture) signature, and it was changed by a request I made, but I'd like to remember that (| $capture) and (\$capture) are completely different things, and SMOP already takes advantage on that, the current signature for .() in SMOP is: method postcircumfix:( )(\$capture, :$cc) where $cc is there to support call with current contination (currently used in exception handling). The other method that requires such concept is method dispatch($object, $identifier, \$capture) {...} in ClassHOW, which will actually call postcircumfix:( ) in the end, so it needs the capture as-is. Aditionally to this syntax, one point requires attention. If foo((a = 1)); makes the pair a positional argument, it's natural that foo((|$capture)); makes the capture a positional argument, instead of expanding it into the argument list, and thus closing the loop in how to use a capture object ;) daniel
Re: use semantics
Em Dom, 2008-12-28 às 00:31 -0500, Jeff Horwitz escreveu: the modules it uses assume they're embedded in an apache process, dlfunc'ing a bunch of apache API functions. I think that means the 'dlfunc' calls need to be in INIT and not in BEGIN. right now it is impossible to compile such a module to bytecode, which i like to do for startup performance. This is actually something I've been thinking for a long time. The thing is that in Perl 6, besides all the efforts, the difference between compile time and run time is not that clear. The thing is that the usual aliasing of symbols from outer modules to this module can be understood as static linking, which can raise issues with modules that cannot be statically linked. In a dynamic linking, the foreign module only need to declare which symbols it will provide (i.e. a '.h' file) at compile time, and the compiled object simply contains a reference this symbol belongs to X. Then, at run-time, you will load the used module and resolve the symbols that you linked in this code. I think this means we need to have two compiling modes, one to generate the header file and other to generate the executable file, or at least we need a way to extract the headers from the executable file without actually loading it. The problem is that use calls EXPORTALL on the package being loaded, and there the barrier between compile-time and run-time becomes very much blurred, because to run EXPORT on the given module, it must be entirely loaded, and I presume the call to EXPORT can only happen after INIT has already been called in that module. I think that's a deadlock. daniel
returning one or several values from a routine
Hi, As smop and mildew now support ControlExceptionReturn (see v6/mildew/t/return_function.t), an important question raised: sub plural { return 1,2 } sub singular { return 1 } my @a = plural(); my $b = plural(); my @c = singular(); my $d = singular(); What should @a, $b, @c and $d contain? Note that the spec says explicitly that a Capture should be returned, delaying the context at which the value will be used, this allows sub named { return :x1 } my $x := |(named); So, this also means that assigning my @a = plural(); my @c = singular(); forces list context in the capture, which should return all positional parameters, as expected. But my $b = plural(); my $d = singular(); would force item context in the capture, and here is the problem, as a capture in item context was supposed to return the invocant. I think this means we should change this bit of the spec, so that a capture in item context return the first positional argument if there is only one positional argument or a list coerced to item of all the named arguments. This would mean that $b in the above code would contain [1,2] while $d would contain simply 1. It's important to realize that this is different from p5 because the argument list to return is not flattened, this means that return @a will always return a list, even if @a has only one element, because as @a is not flattened, it is still a list inside the capture, and when that capture is used in item context, it will assign that list in item context. The same way that return 1,; is always always a list, because you have more than one positional argument. What do you think? daniel
Build and Installation of modules should be implementation specific (Was: Re: 6PAN Spec question)
Em Seg, 2008-12-22 às 15:06 +1100, Timothy S. Nelson escreveu: On Sat, 20 Dec 2008, Mark Overmeer wrote: For ???B. In the current set-up, you use CPAN.pm to download, and then install. The 'cpan' script is a wrapper around CPAN.pm. CPAN.pm starts the install tool. A more convient structure would be to have an user application (maybe the same 'cpan' script), which calls some download backend to retreive the distribution and then calls the right install tool per distribution. I would say: ???B is cpan-NG That would be one way of labelling it. I prefer to leave that labelling up to the people who will actually be writing the software. For all I know, they might prefer to begin with a direct port of CPANPLUS, and work from there. While I agree that ???B plays the role that CPAN.pm does today, I do think we should leave that to be implementation specific, being the implementation responsability to provide a minimal set of features in its package manager so you can install standard Perl modules. This is important because Parrot compiles its code to bytecode, SMOP might even always run from source code (since separating compile-time from run-time may be tricky). Mix together the different Operating Systems where the module should be installed and you get something that is not really spec-able. This also makes it really cool for distribution maintainers, since they know that they can make a custom package manager to create distro-specific packages for every Perl 6 implementation. daniel
Re: 6PAN idea
Em Qui, 2008-12-18 às 11:38 +0100, Mark Overmeer escreveu: In the current state of affairs, CPAN is limited to Perl5 and strongely entangled by Perl5 install tools. Do we want to have people install Perl5 on their (maybe small) machine before they can install Perl6 stuff? Rpm-tools and deb-tools are simply alternatives to CPAN.pm I presume the release of (whichever implementation of) Perl 6 should have deployed a minimal set of features of this package management, so you can install new modules (which could include build-depends). I even think each implementation might have its own package manager, optimized to its needs, and eventually, a distro might want to deploy a customized version of that package manager (that would build the deb or rpm and install it integrated with the rest of the system-wide package management). In summary, I think CPAN6/6PAN should deal with the content, and not how the content is built/installed. That is specific to each Perl 6 implementation and each OS, and that is the reasoning behind the exclusive use of metadata, instead of an embedded build system. One trap of S22 is to say: let's try to do our best for ... (Debian), I agree that doing the best for Debian is a bad idea, but I don't think that's the intended in S22 or in the notes I wrote. But some concepts indeed come from the experience Debian has in managing such a diverse universe. Do realize that getting things installed on a system can be quite hard. Even much harder to express in an abstract meta-data language. So, for CPAN6 I decided to strictly seperate the distribution of releases from the actual content of those releases. That's why I believe the meta-data should describe what the content *is*, and not how it is installed. Deciding how it is installed is completely implementation/OS dependent, and I think should be delegated to the implementation/OS. This will probably mean that we will have some standard way of querying for files included in some distribution, so we make sure the decision of where to store the files is completely up to the implementation and OS. daniel
Re: 6PAN Spec question
Em Qui, 2008-12-18 às 13:08 +1100, Timothy S. Nelson escreveu: My question is, what sort of information actually belongs in a final version of the 6PAN spec? I'm assuming it will at least include 6PAN Package format (layout, metadata, etc), and I'd suggest that it also include the layout of packages on the 6PAN server. I think we have 1) How is the layout of Perl 6 related content (source package format) 2) How source packages are uploaded, indexed, mirrored, searched, downloaded etc (6PAN/CPAN6) 3) How source packages are built 4) How binary packages are installed I think 1 and 2 should be subject of two different specs, I also think 3 and 4 should be implementation and OS specific. daniel
Re: 6PAN idea
Em Qua, 2008-12-17 às 15:00 +1100, Timothy S. Nelson escreveu: My basic assumption is that there's going to be some kind of packaging system written around 6PAN. Please take a look in some notes I've written some time ago: http://www.perlfoundation.org/perl6/index.cgi?DistributionFormat daniel
Re: 6PAN idea
Em Qua, 2008-12-17 às 23:35 +1100, Timothy S. Nelson escreveu: On Wed, 17 Dec 2008, Daniel Ruoso wrote: Em Qua, 2008-12-17 às 15:00 +1100, Timothy S. Nelson escreveu: My basic assumption is that there's going to be some kind of packaging system written around 6PAN. Please take a look in some notes I've written some time ago: http://www.perlfoundation.org/perl6/index.cgi?DistributionFormat I guess I should also say that I'm assuming everyone has at least a vague familiarity with this: http://svn.pugscode.org/pugs/docs/Perl6/Spec/S22-cpan.pod In particular, I'm not sure that Daniel's ideas align with the Draft S22; I'm hoping Daniel will take a moment to see if they align. Indeed, for some reason I missed that document. But it's not entirely unaligned. The major difference seems to be having different packages for source and binary (or source and installable, as in S22). S22 mentions the difference, but doesn't split them in different packages. The most important argument, IMHO, to have them as different packages is to allow a binary/installable distribution without the need to recompile every module when installing. This should help when you have a target OS that is installed in several machines, then you can re-use the binary/installable package repository for that specific OS/version. It also allows one source package to generate different binary packages (for instance, having scripts, libs and docs splitted), and makes it easier to do an uninstall, because a binary/installable package would have a fixed list of files. One thing that is mostly aligned, is the idea that the building of the package is external to it, no more Makefile.PL or Build.PL. The package only lists metadata of which type of things it has, and the running system should realize how to build and install them. Althought, in my notes, I expanded the meaning of it a bit more. In summary, I think inheriting most of the concepts from Debian is something almost consensual, and there's much alignment in both documents in that respect. It would probably make sense to refactor S22 into a more spec-like document. daniel
Proposal: Make @a and @@a different variables
Hi, One of the hardest features in Perl 6 is the slice context. It is undoubtfully usefull, since it provides semantics to acces each iteration of a map, for instance. But there's one thing in the spec that makes not only slices, but the lists themselves considerably harder to implement, and that is the idea that a slice is a view of a list. my @@a = map { $^a == 2 ?? 1,2,3 !! () }, 1, 2, 3; say @a[0]; # this should print 1. say @@a[0]; # this should print (). say @a[1]; # this should print 2. say @@a[1;0]; # this should print 1. That happens because '@a' and '@@a' are the same variable, just different views of that variable. That being said, we should note that this example looks simple because we have almost no lazyness implied (since there's an assignment in the first line), every list access requires the evaluation of the flatenning of the list. my @@a = ((),(1,2,3),()); # the following will require a flatenning to get the actual index say @a[3]; This looks much more complicated when you have a lazy list... my @a == map { $^a == 2 ?? 1,2,3 !! () }, 1, 2, 3; # the line below will require two map iterations to get a value, # and at that time, there will be three values available say @a[0]; # having to support a slice view here will require the lazy list # to always be a lazy slice, and each access will require a flatenning # of the values already obtained to only then decide if it has to # obtain more items say @a[2]; This all makes me think that it would be much easier if the slice existed on its own, which would mean: # this will provide only a flatenned view my @a == map { $^a == 2 ?? 1,2,3 !! () }, 1, 2, 3; # and this will provide a slice view my @@a == map { $^a == 2 ?? 1,2,3 !! () }, 1, 2, 3; # but @a and @@a are different values @a =!= @@a :test; # and trying to get the slice on @a will fail say @a[0;1]; # fail # and you still can flatten the slice if you want to... # and it can preserve the lazyness my @b == @@a; # or enforce a mostly eager level my @c = @@a; So, what do you think? daniel
Re: Proposal: Make @a and @@a different variables
Em Ter, 2008-12-16 às 18:47 +0100, TSa escreveu: # the following will require a flatenning to get the actual index say @a[3]; Could we not shift the problem into a more complicated form of the size of the array? Here it has size 0+3+0 but each of the summands could be lazy and hence infinite or at least finite with unknown value. The number of summands might be also unknown. i.e.: map. when you have my @a == map { ... } == something() you can't really know how many elements you have in the first dimension... In any case the flat view @a has to step at most the first iterator in the array I'm not sure I see what you mean, but I presume you mean the first iteration. In that case, if that iteration returns an empty capture, it will continue iterating until it returns at least one item. But that iteration can then return several items which need to be stored in the lazy list. whereas @@a can look beyond that when indexed with a slice, that is something with semicolon in it. Or the iterations of map and grep... An out of bounds access like @a[3] can be answered without flattening, right? I consider counting the number of items in the inner dimension to be (a simplified) flattening, think of: my @@a == map { $^a == 2 ?? map { $^b == 2 ?? map { $^c == 2 $b == 2 $a == 2 ?? (1,2,3) !! () }, 1, 2, 3 !! () }, 1, 2, 3 !! () }, 1, 2, 3; That would result in (();(();(1,2,3);());()) Which is considerably more complex than the first example and have the following example slice accesses: @@a[1]; # returns (();(1,2,3);()) @@a[1;1]; # returns (1,2,3) @@a[1;1;0] # returns 1 Trying to access @a[0] would result in a recursive flattening until it gets to the element that would otherwise be accessed by the slice @@a[1;1;0] So it's not just a matter of counting 0-3-0, because to get the first 0, you need to recursively flatten the inner dimmension until you realize it's really empty. If we allow that to be flattened at the beginning, it will simply consume the iterator until it gets an element. In general I'm in favor of making @a and @@a distinct because otherwise the first @ in @@a feels like an operator instead like a twigil that belongs to the variable like $ belongs to $a which is also distinct from @a. That's an important point. I think it would be consistent that '@@a' should be the variable name, just as '@a', '$a' or any other. Specially since '@@' is not a sigil and a twigil, but a sigil of two characters. Since one could also go with a shaped @a I think the choice of @@a versus @a is a bit like the choice between a @a and an anonymous array in a $ var ala $a = [] which can be handled through $a almost like @a. I'm not sure I understood that, but I think you're saying that slice context could be seen just as a regular context, as scalar and list context, which is something that I agree. @a =!= @@a :test; BTW, what does the :test mean there? This is the proposed syntax for integration of test-driven-development in the language built-ins. daniel
Re: Where does Foo::Bar.EXPORTALL comes from?
Em Sex, 2008-12-12 às 18:40 -0600, Patrick R. Michaud escreveu: On Fri, Dec 12, 2008 at 08:42:05PM -0300, Daniel Ruoso wrote: [...] While all the default exportation is done by the population of the EXPORT inner package, that doesn't happen from the outside, S11 implies that it happens by the calling of the EXPORTALL routine, it doesn't really make it clear where it comes from. ...this was also briefly discussed (without definite resolution) on #perl6 back in October: http://irclog.perlgeek.de/perl6/2008-10-11#i_617227 I'm simply providing the reference here -- I haven't looked to see if there was any further resolution on the issue (in either IRC or the Synopses) after that discussion. Er... it doesn't really provides a resolution on the issue (besides TimToady saying that I think sideways), the part that says: so Foo::Bar.method is more like $x.method than like @x.method Would imply that EXPORTALL is a method of Object, which is rather weird... The idea of DESTROYALL being a method of Package would be sane, but I'm pretty sure it would require a different syntax, maybe Foo::Bar::.DESTROYALL. daniel
Where does Foo::Bar.EXPORTALL comes from?
Hi, I've been thinking about how I would implement module loading in SMOP and reached some points that I think need some clarification. The most important of them being about the EXPORTALL routine. While all the default exportation is done by the population of the EXPORT inner package, that doesn't happen from the outside, S11 implies that it happens by the calling of the EXPORTALL routine, it doesn't really make it clear where it comes from. If it was Foo::Bar.EXPORTALL it would mean that this is a method from Object, but I think this is a reminiscence of the old method-to-sub-dispatch-fallback, which would mean that EXPORTALL is a subroutine instead, being called on the package. But does that mean that there's a default EXPORTALL that is installed in every package? Does that mean that in the absense of a custom EXPORTALL, some specific code is called? daniel
Re: [perl #61126] return should apply to the lexically enclosing routine, map is no exception
Em Dom, 2008-12-07 às 18:10 +0100, Carl Mäsak escreveu: The above reasoning raises the following question for me: how do I return from a sub or a method from within a map block? I suppose what you want can be achieved with last, it probably should work in map as well, since map and for are synonims... daniel
Re: [perl #61126] return should apply to the lexically enclosing routine, map is no exception
Em Seg, 2008-12-08 às 12:08 +0100, Carl Mäsak escreveu: Daniel (), Carl (): That is all good and well for exiting the map itself; but what I want to achieve is to exit the surrounding sub or method block. Example: Er... I mean actually the opposite... it should always return from the surrounding sub or method, never only from map, if you want to end the map loop, you should use last... meaning... sub foo { map { last; }, 1, 2, 3; # executes the block only once map { return; }, 1, 2, 3; # returns from foo; } daniel
Re: how to write literals of some Perl 6 types?
Em Seg, 2008-12-01 às 18:21 -0800, Darren Duncan escreveu: I'm wondering how to write anonymous value literals of some Perl 6 basic types, and I didn't see mention of this in synopsis 2. Getting away from your question entirely, I think the issue here is that while Perl 6 has support for strong typing, it is not really expected that you approach your code with such strong typing... Let me try to rephrase that... a Bit is something that .^does(Bit), therefore 0 and 1 can certainly be a Bit, while they can also certainly be an Int... But most importantly, they are probably going to be something implemented in low-level that can be used as a Bit, as a Num or as an Int. I'm not sure this is an aspect that everybody got, but there isn't really a way to tell the actual implementation type of an Object in Perl 6, you can introspect the object as long as you wish, but you'll be always asking something to that object, and the object itself is the one giving the answers, therefore it can lie about itself, and that's fine. There are even rumors that $obj.WHAT should return a canonical type, even if its implemented by some low-level optimized version... So, how to write anonymous value literals of that values? Well, you won't need to do that... daniel
Re: Iterators and Laziness
Timothy S. Nelson wrote: Should laziness/eagerness be a property of the operator? I'm inclined to believe that the level of lazyness or eagerness is determined by the operators in question, at least that had worked for assignment and feeds, I can't think of a case where something else determines the lazyness You write The iterator role represents the lazy access to a list. Why only lazy access? It's not *only* lazy access, but it's how you do lazy access... You write: my $item = =$foo; Does that get one item from the iterator object? It depends on the iterator in question, but it certainly gets something (unless the iterator is over, of course), I'm thinking on the following: my $iterator = @list.Iterator(); my $capture = =$iterator; # this returns the capture for that iteration; but my $iterator == @list; my $item = =$iterator; # this returns one, and only one, item This is important because my @@slice == @list; Will keep the dimensionality between iterations and items, for instance: my @@slice == map { $_ == 2 ?? ( 1, 2, 3 ) !! () }, 1, 2, 3; the slice would contain ( () ; ( 1,2,3 ); () ) And this is possible because the actual Iterator returned by the list returns capture-by-capture on each iteration. you specify that the .Iterator() object on something that does List will return the appropriate iterator. I changed it to be .iterator() (so that it's lowercase like all the other List.whatever() functions); what's the function signature? The Uppercase is used to indicate a type coercion, the standard way of coercing something to some other type is by calling a method of the name of the type in that object, that's why you have .Iterator on list, and usually this method has no parameters. daniel
Re: Iterators and Laziness
Sex, 2008-11-28 às 14:23 -0300, Daniel Ruoso escreveu: You write: my $item = =$foo; Does that get one item from the iterator object? It depends on the iterator in question, but it certainly gets something (unless the iterator is over, of course), I'm thinking on the following: I thought it would be helpful to have a complete implementation of how an Iterator would work, in this case the proposed implementation for the map operator in mildew (yes, the amount of indirection in SMOP kinda requires us to write it in a high-level-language): That code doesn't use any of the implied lazyness/eagerness of any operator, it uses the API directly, much of the effort in that code is going to be simplified to the user by the use of the feed operator... The code is in the pugs repo: http://svn.pugscode.org/pugs/v6/mildew/Map.pm daniel
Re: Files, Directories, Resources, Operating Systems
Hi, First of all, sorry for breaking the thread, but I had some trouble with my mail provider, and couldn't hit the reply button. To the point... I think there are some things that are simply not solved by abstraction. Some problems are concrete problems that need concrete solutions, filesystem access is one of them, IMNSHO. I pretty much think if ($*OS ~~ POSIX) { ... } elsif ($*OS ~~ Win32) { ... } is much saner than trying to deal with an enormous API that would be the result of the attempt to get a sane abstraction of all the different possible scenarios, and that would end up having backward-incompatible changes after a while because of some use case scenario that wasn't adrressed. On the other hand, we really could think on having chmod, chown etc in the POSIX module, and have the POSIX module imported (where chmod would be in the default exports) by the prelude when in a posix machine, the same for the Win32 or whatever counterpart. Of course it would be very much interesting to have the open implemented by the POSIX module with the same API as the open implemented by the Win32 module. But I'm pretty much sure that's not the case for chown and chmod, and I don't think an abstract API is worth the trouble for 99% of the cases. But note that this doesn't stop the people in the 1% case to write the abstraction API, I just think it doesn't need to be the only way to access the features, and it certainly doesn't need to be loaded in the prelude. daniel
XPath grammars (Was: Re: globs and trees in Perl6)
Qui, 2008-10-02 às 12:55 +0100, Tim Bunce escreveu: Like applying XPath to an XML DOM, only more general and taken further. By more general and taken further I'm thinking of the same kind of evoltion from simple regular expressions in perl5 to grammars in perl6. An XPath query is like a perl5 regular expression. During YAPC::EU::2007 (yeah... some time ago...) we had this discussion motivated by the need to have something easier to transform parse trees... In that case, we were thinking about programming-language-translators that would take the parse tree of one language, make some modifications in the tree before emitting the other language (i.e.: turning specific language dialects, for instance some uses of map and grep in perl5, to a language that doesn't support map and grep, then turning that into a different p5 construct that could be effectively translated to the target language). One thing we realized at that time is that XPath is good enough, even if it seems to be adressing XML specifically, it has the concept of dimension that can be extended to represent arbitrary aspects of objects. When we then take XQuery into account, we might have all the tools to build an coherent tree-oriented Rule system. xgrammar Foo { xtoken bar { 'some XPath expression' subtoken { make 'some XQuery expression' } } xtoken subtoken { 'some other Xpath expression' { make 'yet another xquery expression' } } } Of course we still need to think how to compose different xpath expressions and how to make captures of it, but maybe XQuery already solves that problem... daniel
Re: Should $.foo attributes without is rw be writable from within the class
Sex, 2008-09-19 às 10:25 -0700, Jon Lang escreveu: Daniel Ruoso wrote: In SMOP, it is handled based on the package of the Class, the private storage inside the object is something like $obj.^!private_storageA::$!bar and $ojb.^!private_storageB::$!bar Note that this ought only be true of class inheritance; with role composition, there should only be one $!bar in the class, no matter how many roles define it. er... what does that mean exactly? role B { has $!a; } role C { has $!a; } class A does B, C { method foo() { say $!a; } } I think in this case $!B::a and $!C::a won't ever be visible, while the reference to $!a in class A will be a compile time error. OTOH... role B { has $.a; } role C { has $.a; } class A does B, C { method foo() { say $.a; } method bar() { say $!a; } } In that case, both B and C declare a *method* a which happens to be visible in class A (and probably a composition error), but $!a in method bar is still a compile time error, because there's no $!a declared in class A. Or does that mean that class A does B, C {...} actually makes the declarations in B and C as if it were declared in the class A? daniel
Re: Should $.foo attributes without is rw be writable from within the class
Qui, 2008-09-18 às 18:11 +0200, TSa escreveu: Shouldn't there be a warning in B that $!B::bar overwrites $!A::bar without an accessor? Actually, $!B::bar doesn't overwrite $!A::bar... the problem is simply that $!A::bar is not visible from inside B, and therefore, there's nothing to be overriden... daniel
Re: Should $.foo attributes without is rw be writable from within the class
Sex, 2008-09-19 às 17:49 +0200, TSa escreveu: Daniel Ruoso wrote: Qui, 2008-09-18 às 18:11 +0200, TSa escreveu: Shouldn't there be a warning in B that $!B::bar overwrites $!A::bar without an accessor? Actually, $!B::bar doesn't overwrite $!A::bar... the problem is simply that $!A::bar is not visible from inside B, and therefore, there's nothing to be overriden... May I pose three more questions? 1. I guess that even using $!A::bar in methods of B is an access violation, right? I.e. A needs to trust B for that to be allowed. Yes 2. The object has to carry $!A::bar and $!B::bar separately, right? Yes 3. How are attribute storage locations handled in multiple inheritance? Are all base classes virtual and hence their slots appear only once in the object's storage? In SMOP, it is handled based on the package of the Class, the private storage inside the object is something like $obj.^!private_storageA::$!bar and $ojb.^!private_storageB::$!bar daniel
Re: {SPAM} Re: Should $.foo attributes without is rw be writable from within the class
Sex, 2008-09-19 às 17:49 +0200, TSa escreveu: Daniel Ruoso wrote: Qui, 2008-09-18 às 18:11 +0200, TSa escreveu: Shouldn't there be a warning in B that $!B::bar overwrites $!A::bar without an accessor? Actually, $!B::bar doesn't overwrite $!A::bar... the problem is simply that $!A::bar is not visible from inside B, and therefore, there's nothing to be overriden... May I pose three more questions? 1. I guess that even using $!A::bar in methods of B is an access violation, right? I.e. A needs to trust B for that to be allowed. Yes 2. The object has to carry $!A::bar and $!B::bar separately, right? Yes 3. How are attribute storage locations handled in multiple inheritance? Are all base classes virtual and hence their slots appear only once in the object's storage? In SMOP, it is handled based on the package of the Class, the private storage inside the object is something like $obj.^!private_storageA::$!bar and $ojb.^!private_storageB::$!bar daniel
Re: {SPAM} Re: How to define a new value type?
Ter, 2008-09-16 às 18:04 +0200, TSa escreveu: I think that mutating methods of immutable value types just have to modify the identity. The problem is how that relates to references. Take e.g. the Str type I really think we are looking at this problem from the wrong perspective. For an Object to be a value, it means that if you build an object with the same value, it will be seen as the same value that some other object with this value. A sane requirement for this to happen is that value objects are read-only, which is something pretty straight-forward. The thing is that, for a value object, there isn't any difference in saying: my $a := 3; or my $a := 3.clone(); Because the number '3' is a value, and you usually doesn't expect a value to change its value at a distance, that's why Int is Immutable. daniel
Re: Iterator semantics
Qui, 2008-09-11 às 12:13 -0700, Larry Wall escreveu: And I guess the fundamental underlying constraint is that a list cannot be considered immutable unless its feeds can be considered immutable, at least in some kind of idempotent sense. This conflicts with the whole point of reactive programming, which is that you have to react because don't know what's coming. This is actually something I was talking in the IRC this week. The amount of polymorphism Perl 6 supports makes it quite impossible to detect if the feeds can be considered immutable or not (in terms of concept, I mean, runtime tips could allow optimizations). But one thing needs to be clear, List is immutable as a type, meaning that the API for List only allows you to read from it, not write to it, but it doesn't necessarily means that it is immutable as an instance, because the List might have a live backend. Since List is not a native type, the interpreter doesn't really have any control on what it does to provide its values, and that's what I mean by saying that we can't infer if the feeds can or cannot be considered immutables. This seems like it's close to the fundamental difficulty we're trying to solve here. And maybe the solution is much like the value/object distinction, where lists get to *decide* for themselves where they switch from easy eager immutable semantics to hard lazy reactive semantics. And if we're pretty clear about the boundary between those, it could work out much like the boundary between DFAable regexes and side-effectful regexes as defined in S05. And maybe it's even the same boundary in some theoretical sense. The problem is that this concept should apply to the entire chain, this means that it can only be considered easy if all the feeds on the chain are easy, and it is too easy for it to be considered hard... for instance, is a 'map' considered easy or hard? In the end, that means that most of the time easy feeds will be made dirty by hard feeds and all the chain will be made lazy, so we have little gain. In SMOP, I'm probably going to presume that everything needs to be lazy, then even: my @o = grep { /\d+/ } =$*IN; my @a = (1,2,(3,4,@o)); my @b = (1,2,(3,4,@a)); Will still allow @b to be seen in slice context, where you would see @a also in slice context, because @a was not eagerly evaluated when composing @b, and eventually @o might never be evaluated. I think this is consistent with the spec that says somewhere that the only operators that imply eager evaluation are the short-circuit boolean operators (besides the 'eager' operator, of course, and the use of lazy values in void context). Of course the spec only says that it should be lazy with the feed operators, but in SMOP I tend to think that all this evaluation will be lazy. daniel
Re: Iterator semantics
Ter, 2008-09-09 às 10:10 -0500, Patrick R. Michaud escreveu: I think my question can be best understood by example -- what does the following produce? my @a = 1,2,3,4,5; for @a { .say; @a = (); } The problem actually becomes more evident with my @a = 1,2,3,4,5; for @a { .say; @a[5] = 'five' } because the first code actually replaces the content of the variable @a, while the second will call .postcircumfix(5), which itself returns a container which is then STOREd with 'five'. The basic difference is that in for @a {...} we take an iterator that point to the array that is stored at that moment in @a. If we replace the array stored in the variable @a, that iterator would still point to the original array. The second example actually modifies the object stored in the variable '@a'. And that is a different issue. daniel
Re: Type of literals
Qui, 2008-06-26 às 16:03 +0200, Moritz Lenz escreveu: In the test suite there are some tests like this: is(1.WHAT, 'Int', '1 as a literal is an Int); This seems to imply that we guarantee the direct type of literals. But do we? Actually I see no need for that. All my programs work fine if the literal 1 is of type Foo, and Foo isa Int. What's our policy on that? Will a 1.WHAT always return Int? do we guarantee (1..4).WHAT always to be 'Range'? This is something I've been thinking about for some time. $a.WHAT is the way to test for type identity, but allowing the user to expect a literal to be from a specific given type is probably a bad idea, because (1..4).WHAT should probably be ImplementationSpecificConstantCompactIntRange or something like that. But I really think it's a matter of user expectations, if we define that the effective type of the literals are undetermined, the implementations will be free to use optimized types. I think we should promote (1..4) ~~ Range test, instead of (1..4).WHAT === Range or even (1..4).WHAT eq 'Range' daniel
Re: fallback semantics of list methods
Sáb, 2008-06-14 às 09:20 -0700, Larry Wall escreveu: On Sat, Jun 14, 2008 at 01:46:10PM +0200, Moritz Lenz wrote: : Fallback semantics in S12 suggest that since no matching multi method is : found, subs are tried - that is, the expression is interpreted as :join('str', 'other_str') : yielding 'other_str'. t/spec/S29-list/join.t disagrees, and wants the : result to be 'str'. I want the result to be 'str'. Just a sanity check here... Are we really going to change the order of the parameters of 'join' from p5? Are we aware that this is going to be a PITA for most p5 developers? Do we realise that this is only necessary to support $nonlist.join($separator) Which, as moritz pointed out on IRC is a very specific corner case, which only makes sense on something like: my $a = $cond ?? ( 1 ) !! ( 2, 3, 4 ); $a.join(','); Which would have the desired effect if used with the proper sigil: my @a = $cond ?? 1 !! (2,3,4); @a.join(','); If we choose to avoid supporting $nonlist.listmethod (which sounds lame anyway), we can keep the order of parameters in join join $separator, @list; join ', ', 1, 2, 3, 4; Which is considerably saner than: join 1, 2, 3, 4, ', '; Moritz convinced me that there's actually no real reason to support $nonlist.listmethod 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. daniel
S12 Patch for metacalls, Representation API (Was: Re: Foo.HOW.metamethod vs Foo.^metamethod)
Seg, 2008-06-09 às 17:51 -0700, Larry Wall escreveu: On Sat, Jun 07, 2008 at 09:49:03PM +0100, Daniel Ruoso wrote: : 2) Assume the capture-translation and define that : $foo.HOW.can($foo,'bar') keeps the $how as the invocant and must receive : the referring object as first argument. I prefer this approach, I think. I took the liberty to write a patch to S12 with this new context. The extended format $foo.HOW.methods($foo) becomes a little awkward, specially for Class based OO. Maybe there should be a more extended modification to promote the .^methods syntax, since $foo.HOW is then more usefull for prototype-based OO, where $foo.HOW might be, for instance, Prototype::Delegation::C3 or Prototype::Concatenation. This actually brings me to another issue, which is how much do we expect for this prototype-based meta implementations to be exchangeable between Perl 6 implementations? The point is that they *must* be representation independent, so that you can use it with whatever low-level object metainstance (in the Moose jargon) you like, and for that to be possible, we need a representation API. SMOP is already pointing in that direction, take a look at: * http://www.perlfoundation.org/perl6/index.cgi?smop_oo_api * http://svn.pugscode.org/pugs/v6/smop/src-s1p/P6Meta.pm daniel __DATA__ Index: S12.pod === --- S12.pod (revision 14546) +++ S12.pod (working copy) @@ -123,11 +123,15 @@ CHOW method. A class object is just considered an empty instance in Perl 6, more properly called a prototype object, or just protoobject. -The actual class object is the metaclass object pointed to by the -CHOW syntax. So when you say CDog, you're referring to both a -package and a protoobject, that latter of which points to the -actual object representing the class via CHOW. The protoobject -differs from an instance object not by having a different + +In a class-based OO implementation, the actual class object is the +metaclass object pointed to by the CHOW syntax. So when you say +CDog, you're referring to both a package and a protoobject, that +latter of which points to the actual object representing the class via +CHOW. In a prototype-based OO implementation, on the other hand, the +metaclass object is probably going to be shared by several types and +the methods are most likely going to be stored in the prototypes. The +protoobject differs from an instance object not by having a different type but rather in the extent to which it is defined. Some objects may tell you that they are defined, while others may tell you that they are undefined. That's up to the object, and depends on how the @@ -1892,23 +1896,29 @@ $x === $y $obj.bless(%args) -Every class has a CHOW function/method that lets you get at the -class's metaobject, which lets you get at all the metadata properties -for the class (or other metaobject protocol) implementing the objects -of the class: +Every object, defined or not, has a CHOW function/method that lets +you get at the metaobject, which lets you get at all the metadata +properties for the type (or other metaobject protocol) implementing +the objects of the type: -MyClass.methods() # call MyClass's .methods method (error?) -MyClass.HOW.methods() # get the method list of MyClass +MyClass.methods()# call MyClass's .methods method (error?) +MyClass.HOW.methods(MyClass) # get the method list of MyClass The C^ metasyntax is equivalent to C.HOW: -MyClass.HOW.methods() # get the method list of MyClass -^MyClass.methods() # get the method list of MyClass -MyClass.^methods() # get the method list of MyClass +MyClass.HOW.methods(MyClass) # get the method list of MyClass +^MyClass.methods(MyClass) -Each object of the class also has a C.HOW or C.^ method: +When using the C^ metasyntax in the method invocation, it also +implies a translation in the capture, passing the invocant as first +argument: -$obj.HOW.methods(); +MyClass.HOW.methods(MyClass) # get the method list of MyClass +MyClass.^methods() # equivalent shorter syntax + +Each object of the type also has a C.HOW or C.^ method: + +$obj.HOW.methods($obj); $obj.^methods(); Class traits may include: @@ -1964,9 +1974,9 @@ Strictly speaking, metamethods like C.isa(), C.does(), and C.can() should be called through the meta object: -$obj.HOW.can(bark) -$obj.HOW.does(Dog) -$obj.HOW.isa(Mammal) +$obj.HOW.can($obj, bark) +$obj.HOW.does($obj, Dog) +$obj.HOW.isa($obj, Mammal) or @@ -1992,7 +2002,7 @@ actually calls: -$obj.HOW.does(Dog) +$obj.HOW.does($obj, Dog) which is true if C$obj either does or isa CDog (or isa something that does CDog). If CDog is a subset, any additional
Re: Google index and subsets (two topics for the price of one!)
Seg, 2008-06-09 às 23:36 +0100, Ovid escreveu: --- Jonathan Worthington [EMAIL PROTECTED] wrote: By default, block parameters (including $_) are readonly, I hope that is a deep readonly? In other words, if $_.position returns an array reference, can I mutate a value in that reference and the state of $_ is thereby changed? Even having said that in the other mail in this thread, I'd like to stress the fact that *it's not possible to avoid side-effects of a method call*, if that method call have a side effect (even if a inside effect). And again, some neat things will only be possible because of that. daniel
Foo.HOW.metamethod vs Foo.^metamethod
Hi, When implementing prototype OO, the HOW for objects with different behaviours will be shared. This issue is not new, but before we thought that it would be possible to solve that by forcing $foo.HOW to be a proxy object that would rewrite the call putting $foo as the invocant. Me and nothingmuch, during PPW in Braga, got more into that issue, and we came to the realisation that this is not really possible, as it might be actually desirable to have a real meta object, storing meta-information that would be part of that metaobject implementation. The HOW might be implementing some kind of RPC, for instance, and that way, it might need to store some meta-meta-information, like the address of the RPC endpoint. This makes the idea of the proxy object inviable because the user might need to talk to the HOW as a real object. That way, $foo.^can('bar') cannot be the same as $foo.HOW.can('bar'), because the first has both $foo and $foo.HOW implied, while, in the last, $foo cannot be taken from anywhere. Therefore I suggest making $foo.^method format the only way to get metamethods related to this object, while $foo.HOW would have a behaviour which would be implementation dependent (at least until it's standartized) SMOP will have $foo.^can('bar') actually translated to $foo.HOW.can($foo, 'bar'), which will keep $foo.HOW as the invocant, and prepend the referring object as the first positional argument (following the example of the sub-dispatch fallback). In that case, we might either: 1) remove all references of $foo.HOW.can('bar') and say that this is implementation specific (since Class-based OO can implement it that way) 2) Assume the capture-translation and define that $foo.HOW.can($foo,'bar') keeps the $how as the invocant and must receive the referring object as first argument. daniel
Re: yada yada yada in regex
Sáb, 2008-06-07 às 16:01 +0200, Stéphane Payrard escreveu: what is the equivalent convention for yadayadayada in regex. Cuz ... is alread meaningful in regex. Should I use ... or {...} ? Should the first be predefined? If I understand correctly, {...} should already be parsed as a yada yada yada closure, since ... is 'like' a statement. I might be missing something, but ... would be a rule with the '...' name which, I think, is parseable, and could even be implemented daniel
Re: First look: Advanced Polymorphism whitepaper
Sex, 2008-05-02 às 14:38 +0200, TSa escreveu: Ovid wrote: However, the CGI/CGI::Simple example I posted earlier doesn't fulfill this. CGI::Simple offers a subset of CGI.pm's functionality and it's guaranteed to be identical Then, since classes are open, the programmer can easily say CGI does CGI::Simple; and let go CGI instances wherever a CGI::Simple is expected. As added value you can get a compiler check with Not really... 'does' will try to compose the CGI::Simple methods to the CGI class (although I think your example was supposed to be CGI::Simple does CGI, but anyway). You don't want to change the class implementation, you just want to annotate an additional 'interface' on the given implementation. I'm actually not sure that you can have 'CGI does CGI::Simple', since CGI::Simple is not a role... daniel
Re: treatment of isa and inheritance
Qua, 2008-04-30 às 12:53 -0400, Brandon S. Allbery KF8NH escreveu: It occurs to me that this shouldn't be new keywords, but adverbs, i.e. ``is :strict Dog''. I don't really see what this is :strict means in the runtime environment. Perl 6 takes OO so deeply that even the type checking is implemented as a cal to the object. There isn't really a way of asking are you trully really a Dog?, there's only do you 'Dog'?. P.S.: Of course optimizations may be more static, but it should be also able to pessimize when dealing with an unknown object implementation. daniel
Re: First look: Advanced Polymorphism whitepaper
Sex, 2008-05-02 às 18:55 +0200, TSa escreveu: For me, too. But note that we should keep does the ultimate type checker that first checks the declared presence of a role, then falls back to a declared class inheritance and then falls back to a declared emulation. What else should be in this check sequence? You're taking it backwards, it's not the type checker that is aware of that, but each object's metamodel. The metamodel protocol is just the do you 'Dog'? thing. daniel
Re: First look: Advanced Polymorphism whitepaper
Sex, 2008-05-02 às 21:49 +0200, TSa escreveu: Daniel Ruoso wrote: In fact, it simply means that it's up to that object's metaobject to answer that, and not to a supra-meta-model to be able to answer to all of the possible metamodel implementations. Since all three forms are derived from a programmer's declaration involving names the problem is simple lookup, indeed. The fact that N objects share one meta object is just for reducing the memory footprint. You could make every object carry the full meta info around. And more importantly, the fact is that they *can* carry the full meta info around, and even more importantly, they might even build completely different set of features. You can do that as shortcuts and optimizations that are indeed needed in order to actually bootstrap the system, but that's not what the type system is. Would you be so kind to enlighten me what the type system is, if not a type calculation overlaid over a value calculation? I think that migth be the key point to understand our disagreement. There's no such thing as *the* Perl 6 type system, there's *a default* type system declared in the spec, but what Perl 6 has is a *meta object protocol* that allows you to deal with several type systems at once. daniel
Re: First look: Advanced Polymorphism whitepaper
Sex, 2008-05-02 às 09:08 -0500, John M. Dlugosz escreveu: A syntax is needed for this express concept: accept B as a substitute for A, without changing A. Which I'm advocating as class CGI::Simple realises CGI { ... } or CGI::Simple is also { realises CGI } or even... $cgi_simple realises CGI; daniel
Re: First look: Advanced Polymorphism whitepaper
Sex, 2008-05-02 às 21:22 +0200, TSa escreveu: Or do you mean backwards in the sense that the priority is with the object somehow? In fact, it simply means that it's up to that object's metaobject to answer that, and not to a supra-meta-model to be able to answer to all of the possible metamodel implementations. I understand that you implement Perl 6 with a fully OO system. But the all objects are equal doesn't work out. You need some Orwellians which are more equal. The type-checker is one of these. Of course there can be more than one checker but in a scope there's exactly one in charge at any given point in time. Other Orwellians are the compiler, the namespace manager, the grammar engine, the dispatcher etc. You can do that as shortcuts and optimizations that are indeed needed in order to actually bootstrap the system, but that's not what the type system is. daniel
Pragma for type matching alternative implementations (Was: Re: treatment of isa and inheritance)
Ter, 2008-04-29 às 21:03 -0500, John M. Dlugosz escreveu: In response to questions on my whitepaper, I made this companion to bring people up to speed on the issue. http://www.dlugosz.com/Perl6/web/isa-inheritance.html Very interesting reading... :) It actually made me think that it would be possible to implement it as a pragma. class A { has $.a }; class B { has $.b }; sub foo { A $a } { ... } { foo(B.new()); # FAIL use typematch 'like'; foo(B.new()); # OK use typematch 'does'; foo(B.new()); # FAIL } This could be achieved simply by scope-redefining infix:~~(Object,Object) to use another implementation. (Note that I'm trying at all costs to avoid adding that as a signature trait, because that would complicate the dispatching ;) daniel
Re: treatment of isa and inheritance
Qua, 2008-04-30 às 15:55 +0200, TSa escreveu: But the type system is part of the language core. As such 'isa' and 'like' or assignment and binding semantics need a definition. Actually, this is one of the hardest parts of implementing Perl 6, because even 'isa', 'like', assignment and binding are dependent on the representation of the given objects, so even such basic operations are polymorphic. This makes the bootstrap of the type system harder, but not impossible. What happens is that, as it is polymorphic, I can provide known low-level implementation of higher-level types that will interoperate transparently with them. By doing that I can bootstrap by special-casing the low-level implementations and getting out of the water that way. This also allows some other interesting features, like the fact that I may have a constant identifier that interoperates with Str while I still can compare to of them simply by comparing their pointer addresses, or by providing a shadow object that points to the inner data structure of other object in order to expose the expected API. In fact, that is the exact point that makes it possible for Perl 6 to have a *fully* boostrapped type system. What defines native types in Perl 6 is not that they have a incompatible lowlevel structure (because they don't, unless optimized), but that they are the only types that the interpreter may expect to know how they look like. Everything else should be opaque to the interpreter (but eventually the optimizer may have a catalog to inspect the internals directly). Take a look at http://www.perlfoundation.org/perl6/index.cgi?smop_p6opaque_implementation and at http://www.perlfoundation.org/perl6/index.cgi?smop_oo_api To see how that's being implemented in SMOP. daniel
Re: First look: Advanced Polymorphism whitepaper
Qua, 2008-04-30 às 08:56 -0700, Ovid escreveu: I had initially thought this, but think about the case where someone wants to rewrite something to be compliant to another interface. If I pass a CGI::Simple object to a method expecting a CGI object, there's an excellent chance that it will *just work*, even though there's no relation between the two. In this case, a role really doesn't work. This makes me think that 'realises' has a considerably more common usage than I thought... Every time you implement something like CGI::Simple, you would like to say 'CGI::Simple realises CGI'. Of course that, in an ideal OO world, CGI would be an abstract role that both the default CGI implementation and CGI::Simple would 'do'. But that seems to javaish to me (read that as something I hate;), and having how to 'lie' about who you are seems more like a Perl thing to do... daniel
Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)
Ter, 2008-04-29 às 09:28 +0200, TSa escreveu: The thing is the .^does traverses the meta information to find the *named* concept Point. The FoxPoint in John's example doesn't have that and thus nominally fails the Point test. The idea is now to also have .^does *might* traverse the information as well as simply return true if the object says so. The point here is whom to delegate the association between FoxPoint and Point... If we are to define an operator to declare that some arbitrary object conforms to some API, I would think the following as saner... sub foo(Point $p) {...}; FoxPoint $fp = ...; $fp realises Point; foo($fp); This way, the dispatching mechanism is still the same (and still typed), but the object now also answers true to .^does(Point). Which means that the typed code remains typed and the feature is implemented as a trait that can be used to any object, thus leaving the fragile type inference to the code calling the method and not to the method that wants a stronger typing... daniel
Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)
Ter, 2008-04-29 às 11:54 +0200, TSa escreveu: If we are to define an operator to declare that some arbitrary object conforms to some API, I would think the following as saner... sub foo(Point $p) {...}; FoxPoint $fp = ...; $fp realises Point; foo($fp); Here the spec is quite clear that 'realises' is spelled 'does'. This is the infix operator that composes a role into an object's class at runtime. Not really... 'does' is a composition operation, 'realises' would be just a type annotation that doesn't change the actual composition. This way, the dispatching mechanism is still the same (and still typed), but the object now also answers true to .^does(Point). But note that FoxPoint $fp = ...; $y = $fp; $y === $fp; # obviously true $fp does Point; $y === $fp; # false because of different HOW? Wrong. $fp is still the same object and $y would also answer true to .^does(Point). it's an in-place change, not a copy. you would need to do $y = $fp.clone(); to keep the non-typed version. Unfortunately S03 doesn't say if === checks for the same WHAT or the same HOW as precondition to checking the WHICH. It doesn't. By definition. === only checks WHICH. Generally WHAT is also quite underspecced. WHAT is implementation specific, it's underspecced for that reason. Which means that the typed code remains typed and the feature is implemented as a trait that can be used to any object, thus leaving the fragile type inference to the code calling the method and not to the method that wants a stronger typing... I don't understand what you want to say here. I mean, the code that is calling the method would be the one doing the untyped-typed mapping, not the calling sub signature (which would make the dispatch much slower). daniel
Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)
[ I'm using this message to reply, because I didn't receive your reply... I'm taking it from the list history... There really seems to be something wrong with this list... ] TSa wrote: BTW, is WHICH globally unique? Or is that also an implementation detail? This is not specced apparently to leave room for decision in the implementation. But there's an important question to be answered before that... what is the type returned by WHICH? I haven't implemented that in SMOP yet (because I have the constant identifiers that allow me to make simple pointer comparison), but I think in the low-level it will end-up being something like a native binary blob. Which means that every non-native type will, in the end, have to be reduced to native types in the WHICH call to provide a proper value for comparison. TSa wrote: So, even though the WHICH stays the eqv check has to change: $a = A.new( a = 0); # your class A $b = A.new( a = 0); $a === $b; # False, but $a eqv $b; # True because of snapshot semantic $b does Point; $a eqv $b; # False because HOW or WHAT is different But it's important to keep in mind that eqv behaviour might also be overriden by the object, that might give a canonical representation that matches the other object. An implementation of the 'realises' trait could make its canonical representation unchanged. As I said earlier, 'does' is an composition operator, it will change the class composition, therefore making it a different object. On the other hand, a 'realises' trait could change the object in order that it would still match with both 'eqv' and '===', while still '~~' to an additional type. This would be done simply by creating an anonymous class that isa the original class while overriding .^does, WHICH and eqv to shadow to the original class, and then re-blessing the object to this anonymous class. TSa wrote: But I would like to reserve infix:like for a type check without subsequent canonical value comparison. That is continuing from above $b.inc; $a like $b; # still true even though $a.a != $b.a It doesn't need to be part of the spec, it's a simple module that traverses .^methods to check if $a implements all methods described by $b. You might want to implement it already in other to reserve the name ;). daniel
Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)
Ter, 2008-04-29 às 14:21 +0200, TSa escreveu: Daniel Ruoso wrote: Not really... 'does' is a composition operation, 'realises' would be just a type annotation that doesn't change the actual composition. OK, but that is not in the spec yet. To me that is like the proposed 'like' operator but with the programmer taking full responsibility. Like reinterpret_cast in C++. It doesn't need to be. New traits can be implemented later. First of all assignment has copy semantics. That is after $y = $fp, $y =:= $fp is false. I agree that It will copy the scalar, which means that later change in the value cell won't propagate to the other variable. But both cells point to the same value. $a = $b; $a === $b; # TRUE $a =:= $b; # FALSE $b = $c; $a === $b; # FALSE As opposed to $a := $b; $a === $b; # TRUE $a =:= $b; # TRUE $b = $c; $a === $b; # TRUE In the later, the scalar itself is copied, which means that both variables *are* the same scalar, and changing the cell value in one is the same as changing the cell value in the other. So... class A { has $.a; method inc { $.a++ } }; $a = A.new( a = 0); $b = $a; $b.inc(); $a.inc(); say $a.a; # 2 say $b.a; # 2 Will work as expected. But either the HOW, the WHAT or both of $fp have to change That is true which implies that $y === $fp can't remain true after $fp does Point Not really... see below... BTW, an interesting question is if a typed binding could become invalid: subset AntiPoint of Any where {not .^does(Point)} my AntiPoint $ap := $fp; # fine for now $fp does Point; # now $ap is bound to a Point which # violates the AntiPoint constraint This is a composition error that generates an exception. It even provides enough information for a compile-time error. It doesn't. By definition. === only checks WHICH. Then we must read different versions of S03. Mine has the sentence Two values are never equivalent unless they are of exactly the same type. *Value types*!!! Which is not the case here, we are talking about *Object types*, also in S03: for two mutable types (object types), checks whether they have the same identity value. (For most such types the identity is simply the reference itself.) Which means that (continuing the code starting with class A)... $a = A.new(a = 0); $b = $a; $a === $b; # TRUE $b.inc; $a === $b; # TRUE daniel
Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)
Seg, 2008-04-28 às 10:15 -0700, Jon Lang escreveu: Ah; that clears things up considerably. If I understand you correctly, John is using '£' to mean use Duck Typing here. _That_, I can definitely see uses for. hrmm... I might just be overlooking something... but... sub foo (Point $p) {...} means... $signature ~~ $capture means... Point $p := $capture[0] means... $capture[0] ~~ Point means... $capture[0].^does(Point) which is implementation specific, but as for what it's worth, might be abasolutely anything that says true to that call, even if it's just a reference to a pointer in a low-level binding of some library... The point I'm trying to make is that Perl 6 already accepts anything that does Point, even if it isn't a Point, that happens basically because Perl 6 have polymorphic representation. That actually means that you *never* can count on knowing how the object is implemented (except for native types, of course). So there's actually no need for the like idiom, because there's no true isa in Perl 6. In Perl 6 one object isa something as long as it says true to isa something. The only exceptions are the native types, see http://www.perlfoundation.org/perl6/index.cgi?smop_native_types for a little longer reasoning on that. daniel