Re: One-pass parsing and forward type references
Larry Wall wrote: > But also note that there are several other ways to predeclare > types implicitly. The 'use', 'require', and 'need' declarations > all introduce a module name that is assumed to be a type name. Just to clarify: it's possible to define a module within a file, rather than as a file; and in fact the usual means of defining classes and roles is an example of this, since they are specialized kinds of modules. Correct? So if I' understanding this correctly, you should be able to say something like: use Foo; class Bar { ... has Foo $x ... } class Foo { ... } ...where the dots are stand-ins for irrelevant code. In effect, "use" tells the compiler that Foo is a noun, so that the parser knows the proper way to handle it. It also looks for the definition of Foo; but will it start screaming bloody murder if it can't find the definition right away? Have I failed to correctly tell it where to look for the definition? (i.e., do I need to say something like "use ::Foo" to let the parser know that the definition is in this file?) -- Jonathan "Dataweaver" Lang
Re: One-pass parsing and forward type references
On Tue, Feb 02, 2010 at 12:23:50AM +0100, Carl Mäsak wrote: : Another thing I started thinking about: if Perl 6 professes to be able : to put on the hat -- syntactically and semantically -- of most any : other programming language out there, through the use of a simple 'use : Language::Java' or 'use Language::Ruby' -- how will Perl 6 compensate : for the fact that its parser is one-pass whereas most other languages : do two passes or more? Specifically, will some programs in those other : languages fail to compile under a Perl 6 language module due to the : fact that a type keyword was referred to before it was declared? If : multiple passes introduce linguistic race conditions, what about : outright linguistic infelicities due to the Perl 6 limitation of : one-pass parsing? The one-pass ideal is only for standard Perl 6 and other languages that make that commitment. Once you switch to another language, you should use whatever kind of recognizer you need for that language. Since Perl is Turing complete, it can (in theory) emulate any atomaton in the right column in the table at the end of: http://en.wikipedia.org/wiki/Unrestricted_grammar In short, it's "simple" only from the standpoint of the *user* of the module. Module creators, on the other hand, should be acquainted with the concept of vicarious suffering before they begin. Larry
Re: One-pass parsing and forward type references
Larry (>): > [Long exposition on the philosophy of predeclaration] > > Hope this helps, or I just wasted a lot of time. :-) It did help. Thanks. A comment on one part, though: > But I also think that type recursion is likelier to indicate a design > error than function recursion [...] I do too. A month or so ago I would have considered type recursion to always indicate a design error. That was before I started trying to port type cycles in a program making sensible use of them. :) As far as I can see, the two cases of type recursion in PGE I outlined do not indicate a design error. I'd be happy to chat with anyone who has an idea about how they could be simplified away and replaced by something non-ugly. Another thing I started thinking about: if Perl 6 professes to be able to put on the hat -- syntactically and semantically -- of most any other programming language out there, through the use of a simple 'use Language::Java' or 'use Language::Ruby' -- how will Perl 6 compensate for the fact that its parser is one-pass whereas most other languages do two passes or more? Specifically, will some programs in those other languages fail to compile under a Perl 6 language module due to the fact that a type keyword was referred to before it was declared? If multiple passes introduce linguistic race conditions, what about outright linguistic infelicities due to the Perl 6 limitation of one-pass parsing? // Carl
Re: One-pass parsing and forward type references
On Mon, Feb 01, 2010 at 03:55:15PM -0500, Solomon Foster wrote: : On Mon, Feb 1, 2010 at 3:46 PM, Patrick R. Michaud wrote: : > On Mon, Feb 01, 2010 at 05:55:47PM +0100, Carl Mäsak wrote: : >> Is it allowed to do 'class B { ... }' several times in different files : >> before finally declaring the real B? If so, then I'd consider it : >> equivalent to my proposed keyword, and thus there'd be no need for the : >> latter. : > : > Yes. And "declaring the real B" doesn't have to be "final", nor : > does it have to occur at all (as long as none of the features needed : > from B are ever needed). : : And just to finish it off... are you allowed to do 'class B { ... }' : even after "declaring the real B"? STD does not currently allow it because you have to install the name immediately in case of references in the traits, even before the block. The block is too late to say "whoops, didn't mean it really." Pretty much the same reason we changed "is also" to "augment". We want to look up the name right now and know whether it should exist without doing lookahead. Larry
Re: One-pass parsing and forward type references
On Mon, Feb 01, 2010 at 05:56:09PM +0100, Jan Ingvoldstad wrote: > On Mon, Feb 1, 2010 at 17:46, Patrick R. Michaud wrote: > > There's a third way: > > > >class B { ... }# introduce B as a class name without definition > > class A { sub foo { B::bar } } > > > >class B { sub bar { A::foo } } > > It seems to me that this doesn't really solve the problems that will occur > when people start making packages independently of eachother. > > Of course it can be solved by submitting patches to the other developer's > code, but it seems inelegant. I see it as not being much different that what already happens now in most languages I deal with. Assume the above lines of code are in different files -- one for A and one for B. Presumably A has a reason for saying "class B { ... }" instead of the more likely "use B;" -- i.e., the author of A knows that it is using B, and that B is likely to refer back to A. And in the above example, I'd expect the file containing the definition of B to likewise have either a "use A;" or "class A { ... }" declaration. It ultimately comes down to the fact that Perl expects each module to declare class names before they get used, unless the class names are part of CORE. Pm
Re: One-pass parsing and forward type references
On Mon, Feb 1, 2010 at 3:46 PM, Patrick R. Michaud wrote: > On Mon, Feb 01, 2010 at 05:55:47PM +0100, Carl Mäsak wrote: >> Is it allowed to do 'class B { ... }' several times in different files >> before finally declaring the real B? If so, then I'd consider it >> equivalent to my proposed keyword, and thus there'd be no need for the >> latter. > > Yes. And "declaring the real B" doesn't have to be "final", nor > does it have to occur at all (as long as none of the features needed > from B are ever needed). And just to finish it off... are you allowed to do 'class B { ... }' even after "declaring the real B"? -- Solomon Foster: colo...@gmail.com HarmonyWare, Inc: http://www.harmonyware.com
Re: One-pass parsing and forward type references
On Mon, Feb 01, 2010 at 05:55:47PM +0100, Carl Mäsak wrote: > Is it allowed to do 'class B { ... }' several times in different files > before finally declaring the real B? If so, then I'd consider it > equivalent to my proposed keyword, and thus there'd be no need for the > latter. Yes. And "declaring the real B" doesn't have to be "final", nor does it have to occur at all (as long as none of the features needed from B are ever needed). Pm
r29605 - docs/Perl6/Spec
Author: lwall Date: 2010-02-01 21:33:47 +0100 (Mon, 01 Feb 2010) New Revision: 29605 Modified: docs/Perl6/Spec/S02-bits.pod docs/Perl6/Spec/S03-operators.pod docs/Perl6/Spec/S04-control.pod Log: [S02,S03,S04] more @@ removal; some s/Capture/Parcel/ cleanup Modified: docs/Perl6/Spec/S02-bits.pod === --- docs/Perl6/Spec/S02-bits.pod2010-02-01 20:14:16 UTC (rev 29604) +++ docs/Perl6/Spec/S02-bits.pod2010-02-01 20:33:47 UTC (rev 29605) @@ -1600,7 +1600,6 @@ % unordered hash (associative array) & code/rule/token/regex :: package/module/class/role/subset/enum/type/grammar -@@ slice view of @ Within a declaration, the C<&> sigil also declares the visibility of the subroutine name without the sigil within the scope of the declaration: @@ -2124,7 +2123,7 @@ operators: print $( foo() )# foo called in item context -print @@( foo() ) # foo called in slice context +print %( foo() ) # foo called in hash context In declarative constructs bare sigils may be used as placeholders for anonymous variables: Modified: docs/Perl6/Spec/S03-operators.pod === --- docs/Perl6/Spec/S03-operators.pod 2010-02-01 20:14:16 UTC (rev 29604) +++ docs/Perl6/Spec/S03-operators.pod 2010-02-01 20:33:47 UTC (rev 29605) @@ -15,8 +15,8 @@ Created: 8 Mar 2004 -Last Modified: 30 Jan 2010 -Version: 188 +Last Modified: 1 Feb 2010 +Version: 189 =head1 Overview @@ -205,7 +205,6 @@ %z $^a $?FILE -@@slice &func &div:(Int, Int --> Int) @@ -217,7 +216,6 @@ @() %() &() -@@() =item * @@ -919,11 +917,10 @@ @list xx $count Evaluates the left argument in list context, replicates the resulting -C value the number of times specified by the right argument and -returns the result in a context dependent fashion. If the operator -is being evaluated in ordinary list context, the operator returns a -flattened list. In slice (C<@@>) context, the operator converts each C -to a separate sublist and returns the list of those sublists. +C value the number of times specified by the right argument +and returns the result as a list of C (which will behave +differently depending on whether it's bound into a flat context or +a slice context). If the count is less than 1, returns the empty list, C<()>. If the count is C<*>, returns an infinite list (lazily, since lists @@ -1703,11 +1700,11 @@ ('a', '1'), ('a', '2'), ('b', '1'), ('b', '2') -This becomes a flat list in C<@> context and a list of arrays in C<@@> context: +This becomes a flat list in flat context and a list of arrays in slice context: -say @( X <1 2>) +say flat( X <1 2>) 'a', '1', 'a', '2', 'b', '1', 'b', '2' -say @@( X <1 2>) +say slice( X <1 2>) ['a', '1'], ['a', '2'], ['b', '1'], ['b', '2'] The operator is list associative, so @@ -2358,7 +2355,7 @@ The forms with the double angle append rather than clobber the sink's todo list. The C<<< ==>> >>> form always looks ahead for an appropriate target to append to, either the final sink in the chain, or the next -filter stage with an explicit C<@(*)> or C<@@(*)> target. This means +filter stage with an explicit C<@(*)> or C<@(**)> target. This means you can stack multiple feeds onto one filter command: source1() ==>> @@ -4655,7 +4652,7 @@ turn into subarrays, and each element would then have to be unpacked by the signature: -for @@(zip(@names; @codes)) -> [$name, $zip] { +for slice(zip(@names; @codes)) -> [$name, $zip] { print "Name: $name; Zip code: $zip\n"; } Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2010-02-01 20:14:16 UTC (rev 29604) +++ docs/Perl6/Spec/S04-control.pod 2010-02-01 20:33:47 UTC (rev 29605) @@ -352,9 +352,9 @@ iteration. Iterations that return a null list (such as by calling C with no extra return arguments) interpolate no values in the resulting list. (This list is actually a two-dimensional list of -Cs (a "slice") with dimensional boundaries at each iteration. +Cs (a "slice") with dimensional boundaries at each iteration. Normal list context ignores these boundaries and flattens the list. -Slice context turns the captures into subarrays, so an iteration +Slice context turns the parcels into sublists, so an iteration returning a null list does show up as a null subarray when viewed as a slice.) @@ -688,16 +688,18 @@ the statement or block in sink (void) context; its return value is instead specified by calling the C list prefix operator one or more times within the dynamic scope of the C. The C function's -signature is like that of C; it merely captures the C +signature is like that of C; it merely wraps up a C of its arguments withou
r29604 - docs/Perl6/Spec
Author: lwall Date: 2010-02-01 21:14:16 +0100 (Mon, 01 Feb 2010) New Revision: 29604 Modified: docs/Perl6/Spec/S02-bits.pod docs/Perl6/Spec/S06-routines.pod Log: [S02,S06] continue de-confusing flat and eager Modified: docs/Perl6/Spec/S02-bits.pod === --- docs/Perl6/Spec/S02-bits.pod2010-01-31 22:21:10 UTC (rev 29603) +++ docs/Perl6/Spec/S02-bits.pod2010-02-01 20:14:16 UTC (rev 29604) @@ -13,8 +13,8 @@ Created: 10 Aug 2004 -Last Modified: 30 Jan 2009 -Version: 197 +Last Modified: 1 Feb 2009 +Version: 198 This document summarizes Apocalypse 2, which covers small-scale lexical items and typological issues. (These Synopses also contain @@ -3993,8 +3993,9 @@ =item * -To force non-lazy list flattening, use the C list operator. -List assignment is also implicitly eager. +To force non-lazy list processing, use the C list operator. +List assignment is also implicitly eager. (Actually, when we say +"eager" we usually mean "mostly eager" as defined in L). eager $filehandle.lines;# read all remaining lines @@ -4008,6 +4009,9 @@ and calls the iterator as it needs more elements. (Counting the elements in the array will also force eager completion.) +This operator is agnostic towards flattening or slicing. In merely changes +the work-ahead policy for the value generator. + =item * A variant of C is the C list operator, which declares @@ -4020,6 +4024,9 @@ as the results come in, such that some keys can be seen even before the hyper is done. Thinking about Map-Reduce algorithms here...) +This operator is agnostic towards flattening or slicing. It merely changes +the work-ahead policy for the value generator. + =item * Signatures on non-multi subs can be checked at compile time, whereas Modified: docs/Perl6/Spec/S06-routines.pod === --- docs/Perl6/Spec/S06-routines.pod2010-01-31 22:21:10 UTC (rev 29603) +++ docs/Perl6/Spec/S06-routines.pod2010-02-01 20:14:16 UTC (rev 29604) @@ -16,8 +16,8 @@ Created: 21 Mar 2003 -Last Modified: 19 Nov 2009 -Version: 125 +Last Modified: 1 Feb 2010 +Version: 126 This document summarizes Apocalypse 6, which covers subroutines and the new type system. @@ -970,10 +970,11 @@ The C<|> operator flattens lazily -- the array is flattened only if flattening is actually required within the subroutine. To flatten before -the list is even passed into the subroutine, use the C list +the list is even passed into the subroutine, use the C list operator: -foo(|eager @onetothree); # array flattened before &foo called +foo(|flat 1,2,3 Z 4,5,6);# zip list flattened before interpolation +foo |(1,2,3 Z 4,5,6).flat# same thing =head2 Multidimensional argument list binding
Re: One-pass parsing and forward type references
On Mon, Feb 01, 2010 at 10:10:11AM -0800, yary wrote: : A slight digression on a point of fact- : : On Mon, Feb 1, 2010 at 9:32 AM, Larry Wall wrote: : ... : > You are correct that the one-pass parsing is non-negotiable; this is : > how humans think, even when dealing with unknown names. : : It's common for people to read a passage twice when encountering : something unfamiliar. That's on the large level. And even on the small : level of reading for the first time, people don't read completely : linearly, "skilled readers make regressions back to material already : read about 15 percent of the time." - : http://en.wikipedia.org/wiki/Eye_movement_in_language_reading (and I : read about that elsewhere years ago, wikipedia happens to be the most : convenient reference.) : : I'm not arguing against 1-pass parsing for Perl6, just reminding that : humans are complicated. And Larry's quote is "how humans think" : whereas the research on eye jumps is about "how humans read" which are : not exactly the same... True enough; I was thinking primarily about the parsing of spoken speech, where one generally doesn't have the option to replay beyond what you can remember. And Perl 6 is arguably more textual than aural. Larry
Re: One-pass parsing and forward type references
A slight digression on a point of fact- On Mon, Feb 1, 2010 at 9:32 AM, Larry Wall wrote: ... > You are correct that the one-pass parsing is non-negotiable; this is > how humans think, even when dealing with unknown names. It's common for people to read a passage twice when encountering something unfamiliar. That's on the large level. And even on the small level of reading for the first time, people don't read completely linearly, "skilled readers make regressions back to material already read about 15 percent of the time." - http://en.wikipedia.org/wiki/Eye_movement_in_language_reading (and I read about that elsewhere years ago, wikipedia happens to be the most convenient reference.) I'm not arguing against 1-pass parsing for Perl6, just reminding that humans are complicated. And Larry's quote is "how humans think" whereas the research on eye jumps is about "how humans read" which are not exactly the same... -y
Re: One-pass parsing and forward type references
On Mon, Feb 1, 2010 at 9:32 AM, Larry Wall wrote: > But I also think that type recursion is likelier to indicate a design > error than function recursion, so I'm not sure how far down this road > we want to go. We could, for instance, create a new type name every I was going to say "I use self-referential and cyclical type definitions in Sprixel's (stage0) C# source..." (because I did at one point), but then I realized I stopped doing that; it worked, but it was a tad too tricksy to maintain. So, point taken.
Re: One-pass parsing and forward type references
Please don't assume that rakudo's idiosyncracies and design fossils are canonical. STD does better namespace management in some respects, particularly in accepting the approved predeclaration form: class Foo {...} (and rakudo might now accept this too). You don't want to use augment for this, because augment is only for *cheating*, and will eventually require a 'use MONKEY_TYPING;' before it. You are correct that the one-pass parsing is non-negotiable; this is how humans think, even when dealing with unknown names. However, human language has ways of telling the listener whether a new word is a noun or a verb, and we generally choose not to require articles or verb markers in Perl 6, so class names (nouns) are officially ambiguous with function names (verbs). We could, as has been suggested before, have an optional noun marker for undeclared classes, but this tends to insidiously creep into lots of places, when a single predeclaration would be clearer and more efficient. The other reason we'll stick with one-pass parsing is that you can only do multiple pass parsing if you know exactly which language you're parsing all the time. This works against extensibility. Multiple passes introduce linguistic race conditions any time you're not sure what language you're in; see source filters for a good bad example of why you don't want to do multi-pass parsing. Because type names are nouns in Perl 6, we want to parse them like other nouns, such as variables and constants, not like verbs. Know whether something is a noun or a verb is very important in maintaining the two-terms-in-a-row prohibition, which is the primary way in which Perl 6 expressions are self-clocking. Break that clock and your error messages will turn to mush. Some of the smartest error messages that STD emits are actually the two-terms message transmogrified into something more specific by context. Therefore, a word that is declared as a sigilless noun must change the parsing from there on down so that we know to expect an infix after it, not a term, which a verb functioning as a listop would expect. constant Int pi = 3; pi 'foo'; # syntax error (Notice how the fact that Int is predeclared also allows us to correctly parse the constant declaration, since allows us to distinguish the existing type from the name to be declared.) Now that we have basic philosophy out of the way, on to other arguments. You might take the predeclaration policy as subtle encouragement to use the late binding provided by method calls, which don't require predeclaration. But Perl 6 is not religiosly OO to the exclusion of FP, so that's a weak argument, and we're not trying to discourage people from doing cross-module function calls. You make an analogy between type recursion and functional recursion, which is true up to a point, but types and other unsigilled names tend to be rarer than function names, so it makes sense, if we see an unknown name, to assume (if we choose to assume) that it is a postdeclared verb rather than a postdeclared noun. We don't want to break function recursion in order to support type recursion. We can't guess it both ways since we wouldn't know what to expect next. Perl 5 did lookahead and tried to guess in some cases, but this generally turned out to be a mistake. It was difficult to document and only inspired mistrust in the parser. Plus it degrades the two-term rule. But also note that there are several other ways to predeclare types implicitly. The 'use', 'require', and 'need' declarations all introduce a module name that is assumed to be a type name. We can also deduce that any use of Foo::Bar::baz to mean there exists a Foo::Bar type. STD does this already, though perhaps only as a lexically scope name at the moment. We might assume it to (at least potentially) be global. A 'use' also predeclares any types in its own space and makes the public ones available as predeclaration. From the standpoint of a typical midsized application that are spread across multiple files, most of the predeclarations should arrive like this, and not require a yadayada predeclaration. And in Perl 6 you shouldn't generally be using types without a 'use' of the definitions of those types, or you might not import some desirable multi into your lexical scope. Of course, we have to deal with 'use' cycles. Perl 5 simply assumes that it doesn't need to load a module that it knows is already being loaded, even if that loading is not complete or would result in something not being defined that ought to be. We could take the same agnostic approach and require the user to break use cycles explicitly with yada. Or we could detect that exact situation and relax the rules slightly to do a bit of dwimmery on type names that *start* with the partially compiled module. In that case, it might be reasonable, if we've got a suspended 'use Foo', to assume: Foo::Bar::baz # likely a function Foo::Bar::Baz # likely
Announce: Rakudo Perl 6 Development Release #25 ("Minneapolis")
[This notice is going out a bit late; the release was indeed produced on time, but I was delayed in sending out this notice. With apologies for the delay... --Pm] On behalf of the Rakudo development team, I'm pleased to announce the January 2010 development release of Rakudo Perl #25 "Minneapolis". Rakudo is an implementation of Perl 6 on the Parrot Virtual Machine (see http://www.parrot.org). The tarball for the January 2010 release is available from http://github.com/rakudo/rakudo/downloads . Rakudo Perl follows a monthly release cycle, with each release code named after a Perl Mongers group. The January 2010 release is code named "Minneapolis" for Minneapolis.pm, hosts of the annual Frozen Perl Workshop [1]. In 2009 the Frozen Perl Workshop featured a one-day hackathon for Perl 6 and Rakudo development, which ultimately informed the design and implementation of the current build system. (The 2010 Frozen Perl Workshop will be on February 6, 2010, for those interested in attending.) Shortly after the October 2009 (#22) release, the Rakudo team began a new branch of Rakudo development ("ng") that refactors the grammar to much more closely align with STD.pm as well as update some core features that have been difficult to achieve in the master branch [2, 3]. We had planned for this release to be created from the new branch, but holiday vacations and other factors conspired against us. This is absolutely the final release from the old development branch; we expect to make the new branch the official "master" branch shortly after this release. This release of Rakudo requires Parrot 2.0.0. One must still perform "make install" in the Rakudo directory before the "perl6" executable will run anywhere other than the Rakudo build directory. For the latest information on building and using Rakudo Perl, see the README file section titled "Building and invoking Rakudo". Some of the specific changes and improvements occuring with this release include: * Rakudo is now passing 31,957 spectests, or 85.7% of the available test suite. This is roughly the same level as the December 2009 release (because most effort has taken place in the "ng" branch as described above). * Rakudo's calling conventions have been updated to match changes in Parrot 2.0.0's calling and context structures. The Perl 6 language specification is still in flux. Please take note of the following changes, which might affect your existing programs. In the next release of Rakudo, the deprecated features will likely be gone. * The root of the object hierarchy has been changed from 'Object' to 'Mu'. The type 'Object' goes away. * The term 'undef' is gone. You can replace it with other constructs, depending on context: - 'Nil' is undefined in item context, and the empty list in list context - 'Mu' is the most general undefined value which does not flatten in list context - as a smart matching target, you can replace '$obj ~~ undef' by '$obj ~~ *.notdef' * Builtin classes will derive from 'Cool' (which itself derives from 'Any'). Most of the builtin methods on these classes will be defined in the 'Cool' class instead of 'Any'. See Synopsis 2 for more details. * Starting with the next release, we will likely switch to using ".MM" instead of "-MM" (dot instead of hyphen) as release identifiers. This is intended to simplify building and packaging for other distribution systems. The development team thanks all of our contributors and sponsors for making Rakudo Perl possible. If you would like to contribute, see http://rakudo.org/how-to-help , ask on the perl6-compi...@perl.org mailing list, or ask on IRC #perl6 on freenode. The next release of Rakudo (#26) is scheduled for February 18, 2010. A list of the other planned release dates and codenames for 2010 is available in the "docs/release_guide.pod" file. In general, Rakudo development releases are scheduled to occur two days after each Parrot monthly release. Parrot releases the third Tuesday of each month. Have fun! [1] http://www.frozen-perl.org/ [2] http://use.perl.org/~pmichaud/journal/39779 [3] http://use.perl.org/~pmichaud/journal/39874
Re: One-pass parsing and forward type references
On Mon, Feb 1, 2010 at 17:46, Patrick R. Michaud wrote: > There's a third way: > >class B { ... }# introduce B as a class name without definition > class A { sub foo { B::bar } } > >class B { sub bar { A::foo } } > > The first line is a literal "..." in the body of the class -- it > indicates that we're only declaring the name as being a type, > and that something else will fill in the details later. > It seems to me that this doesn't really solve the problems that will occur when people start making packages independently of eachother. Of course it can be solved by submitting patches to the other developer's code, but it seems inelegant. -- Jan
Re: One-pass parsing and forward type references
Patrick (>), Carl (>>): >> I found two ways. Either one uses C (the language construct >> formerly known as C): >> >> class B {} >> class A { sub foo { B::bar } } >> augment class B { sub bar { A::foo } } >> >> ...or one may use the C<::> notation to index a type using a string value: >> >> class A { sub foo { ::<&B::bar>() } } >> class B { sub bar { A::foo } } > > There's a third way: > > class B { ... } # introduce B as a class name without definition > class A { sub foo { B::bar } } > > class B { sub bar { A::foo } } > > The first line is a literal "..." in the body of the class -- it > indicates that we're only declaring the name as being a type, > and that something else will fill in the details later. That's nice. Seems like a decent way to avoid 'use MONKEY_TYPING'. Is it allowed to do 'class B { ... }' several times in different files before finally declaring the real B? If so, then I'd consider it equivalent to my proposed keyword, and thus there'd be no need for the latter. // Carl
Re: One-pass parsing and forward type references
On Sun, Jan 31, 2010 at 06:35:14PM +0100, Carl Mäsak wrote: > I found two ways. Either one uses C (the language construct > formerly known as C): > > class B {} > class A { sub foo { B::bar } } > augment class B { sub bar { A::foo } } > > ...or one may use the C<::> notation to index a type using a string value: > > class A { sub foo { ::<&B::bar>() } } > class B { sub bar { A::foo } } There's a third way: class B { ... }# introduce B as a class name without definition class A { sub foo { B::bar } } class B { sub bar { A::foo } } The first line is a literal "..." in the body of the class -- it indicates that we're only declaring the name as being a type, and that something else will fill in the details later. Pm
Re: One-pass parsing and forward type references
Moritz (>), Carl (>>): >> But on another level, the level of types, Perl 6 makes it fairly >> *un*natural that the type C refers to the type C, which in >> turn refers to the type C. > > True, and that has also been bothering me quite a bit. > > The "solution" is to always write ::Typename instead of Typename > except when it isn't a solution. > > First of all in signatures ::T means actually "type capture", secondly I > guess that some constructs really want to resolve type names at compile > time -- for example the multi dispatcher needs to know the inheritance > structure of a type in order to its pre-sorting of signatures. > > The first problem could be solved by introducing another syntax for type > captures (perhaps :>foo or so?), of the second I know too little to > really comment on it. I had half an idea about the second one as I wrote the first mail. It may or may not be useful, but here goes: Some keyword, on the level of 'is' and 'does', which allows one to use a not-yet-defined typename within another type. It wouldn't solve the core problem -- the one about having to think about circularities -- but it would allow one to create cycles. So this would work: class A precedes-but-refers-to B { ... B ... } class B { ... A ... } Just an idea. // Carl
Re: One-pass parsing and forward type references
Carl Mäsak wrote: > But on another level, the level of types, Perl 6 makes it fairly > *un*natural that the type C refers to the type C, which in > turn refers to the type C. True, and that has also been bothering me quite a bit. The "solution" is to always write ::Typename instead of Typename except when it isn't a solution. First of all in signatures ::T means actually "type capture", secondly I guess that some constructs really want to resolve type names at compile time -- for example the multi dispatcher needs to know the inheritance structure of a type in order to its pre-sorting of signatures. The first problem could be solved by introducing another syntax for type captures (perhaps :>foo or so?), of the second I know too little to really comment on it. Cheers, Moritz