Re: S26 - The Next Generation
Smylers wrote: Jon Lang writes: FWIW, the current proposal for aliasing blocks of ambient text is functional; it just feels a bit kludgey, Why? To me it seems the opposite: what could be more natural for delimiting a block of code than braces? Because sometimes you'll want to capture only part of a block of code, or a little bit more than a block of code. In short, what you want for documentation purposes won't always align with the conceptual structure of the ambient code. I don't like the idea of being required to break the code up into blocks whose only purpose is documentation: if you're breaking the ambient code up into chunks for documentation purposes, it should _look_ like the code is being broken up into chunks for documentation purposes. Using Pod tricks for denoting the start and end of aliased ambient text does that; using a Perl block doesn't. and I'm a bit bothered by the fact that you can't alias any ambient text other than a code block. Can't is a bit strong: it's more that if you want to quote an arbitrary portion of code then you need to add some braces around it. But those braces are unlikely to harm the program. The exception is if you want to quote an 'unbalanced' portion of code, for example the start of a loop but not the entire loop. Do you consider that to be likely? Actually, yes; I do. how about saying that an ambient code alias is normally terminated by the next blank line or Pod directive (as per =for) Braces are more robust than blank lines; if aliasing a brace-delimited block I may unthinkingly edit it to have a blank line in the middle of it, on the basis that the blank line isn't significant to perl. And =begin blocks are more robust than =for blocks in the same way. Perl may not care about blank lines; but Pod does. And the author of a file with both Perl and Pod in it is being remiss in his duties if he doesn't consider both paradigms. Incidently, note that declarator blocks already behave this way in Pod: the presence or absence of a blank line determines the code to which it gets attached. (Whereas if I edit the braces then I've changed the program as well as its docs.) Right. If the braces weren't part of the ambient code, and were there merely to delineate the aliased text, I'd have less of a problem with them. In fact, my main problem with them at that point would be how much they look like a code block without being one, and the confusion that's sure to arise. Let's see what others think. OK. I like the braces. I suggest initially only providing for braces, but with the possibility of later adding options to indicate other termination points if in practice there turn out to be many situations where the braces don't work well. I like the idea of using the braces if they're there, and using something else if they're not. Again, my concern is is being forced to alias an entire code block, never anything more or less; I'm not opposed to being _able_ to alias an entire code block, and I'm especially not opposed to being able to do so in a simple and intuitive manner. But let me propose something for the absence of braces case: introduce a new kind of delimiter into Perl - something that works like an embedded comment, except that it doesn't actually comment anything out. In the absence of a curly brace at the start of the next line of code, a code alias will bind to the first document tag that it finds, that isn't already claimed by another =alias directive. For example: =alias loop #:[[ =alias loop-head loop #:[($i = 1; $i $j; $i *= 2)] =alias loop-body { DoSomething($i); } ]] In this example, I'm using #:[...] as a stand-in for the documentation tag syntax. As such, loop is aliased to: loop ($i = 1; $i $j; $i *= 2) { DoSomething($i); } loop-head is aliased to: ($i = 1; $i $j; $i *= 2) And loop-body is aliased to: { DoSomething($i); } I'm not fond of the document tag syntax used in the above example; it looks a little bit too much like a comment. But whatever does get used, it should be brief and distinct. And since we're talking about connecting code and documentation, it's possible that we might want to have this kind of alias be a special case of the declaration block rather than a stand-alone directive, using similar rules to determine what to alias (but focused on code blocks and doc tags rather than declarators). I've got to run right now; but I've more thoughts that just got triggered by this. I'll get back to you as soon as I can. -- Jonathan Dataweaver Lang
Re: $*CWD and chdir()
Martin D Kealey wrote: I wonder if this is becoming the new Perl mantra use lexically scoped pragmata. Larry said it much more succinctly: all's fair if you predeclare. -- Jonathan Dataweaver Lang
Re: [perl #64566] @a[1..*] adds trailing undef value
On Wed, Aug 19, 2009 at 5:37 AM, Jan Ingvoldstadfrett...@gmail.com wrote: On Wed, Aug 19, 2009 at 1:54 PM, Moritz Lenz via RT perl6-bugs-follo...@perl.org wrote: Since the discussion came up on #perl6 if this is really the expected behaviour, S09 says: As the end-point of a range, a lone whatever means to the maximum specified index (if fixed indices were defined): say @calendar[5..*]; # Same as: say @calendar[5..11] say @calendar{Jun..*}; # Same as: say @calendar{Jun..Dec} or to the largest allocated index (if there are no fixed indices): say @data[1..*]; # Same as: say @results[1..5] It doesn't mention how the postcifcumfix:[ ] is supposed to introspect those to find out if the WhateverCode object constructed by 1..* needs to receive self.elems or self.elems-1 as an argument. Which is why I CC: p6l to get some ideas or clarification, and if we want to maintain this DWIMmy but not very consistent behaviour. Given that it's relatively easy to say 1..^*, I wouldn't mind standardizing this so that '*' always refers to the element just past the last one, at least when dealing with the standard index. That said, when dealing with a custom index, there generally isn't an easily identified one element past the end position that can be referenced; so I'd be inclined to standardize everything there such that '*' always refers to the last element. And if we're going to do that, why not do the same for standard indexing? e.g., '*' is always the last element; '*-1' is always one in from the last element; etc. I like it the way S09 says it. But there is a problem with sparse arrays, isn't there? There shouldn't be, because there shouldn't be sparse arrays - at least, not in standard indexing. One of the reasons for the introduction of custom indices was the idea that sparseness would take place in them, so that the standard index could be relied upon yo provide ordinal access to the elements: @a[0] should _always_ be the first element; @a[1] should always be the second element, and so on. And you should always be able to reach the next item by adding one to the current item's index. That is, the standard index will always be '0..^$number-of-items'. If we're not going to follow this rule, then I see no reason why we shouldn't just have the custom indexing mechanism _replace_ standard indexing, rather than exist side by side with it. If the standard index can't be depended on for standardized behavior, it's useless. That said, a case could be made that the custom indexing model is too strict as written: it forces you to pre-establish a one-to-one relationship between the standard and custom indices, which largely negates its usefulness in implementing the concept of sparse arrays. I recommend loosening up the restrictions on custom indexing and putting a note in the spec to clarify the intended purpose and features of the standard index. S32/Containers (S32-array) says this about elems: our Int method elems (@array: ) is export Returns the length of the array counted in elements. (Sparse array types should return the actual number of elements, not the distance between the maximum and minimum elements.) This is exactly what the division between standard and custom indexing was supposed to avoid. When using standard indexing, the distance between the minimum (i.e., [0]) and maximum (i.e., [*-1]) elements should always be the actual number of elements; so no such special note should be needed. -- Jonathan Dataweaver Lang
Re: S26 - The Next Generation
Damian Conway wrote: When using the code block alias, are the outermost curly braces considered to be part of the ambient code? Yes. All ambient code is actual code. OK. Let me propose an alternative (which I expect will be immediately shot down): Allow '=begin alias', '=end alias', and '=for alias' as special cases: the Perl parser makes an exception for them and doesn't treat them as the start or end of POD Blocks, merely as single-line directives; but the Pod parser treats them as normal Pod Blocks, with the contents being attached to the alias. Net result: said contents count both as ambient code and as aliased text. Benefits: you can alias any ambient code that you want, as long as it consists of one or more full lines; and your method for delimiting the alias is one that Pod writers will be quite use to. Drawback: the Perl parser will need to look forward a bit further before deciding how much ambient commentary there is. -- Jonathan Dataweaver Lang
Re: S26 - The Next Generation
FWIW, the current proposal for aliasing blocks of ambient text is functional; it just feels a bit kludgey, and I'm a bit bothered by the fact that you can't alias any ambient text other than a code block. On Wed, Aug 19, 2009 at 11:29 AM, Damian Conwaydam...@conway.org wrote: Jonathan Dataweaver Lang proposed: OK. Let me propose an alternative (which I expect will be immediately shot down): BANG! ;-) D'oh! Allow '=begin alias', '=end alias', and '=for alias' as special cases: the Perl parser makes an exception for them and doesn't treat them as the start or end of POD Blocks, merely as single-line directives; but the Pod parser treats them as normal Pod Blocks, with the contents being attached to the alias. Well, clearly I'm not going to be in favour of introducing exceptions to the general syntax. However, I had originally thought that we should have =alias and =dealias directives to delimit code extractions. In the end I liked the use of the code's own delimiters better, but I guess if people preferred to have two directives as delimiters, we could consider that instead. What I liked the most about my proposal was that it allowed for a blank line termination form as well as an explicit directive termination form. On review, '=for alias' would have been redundant with '=alias' (although I don't think that redundancy hurts). And again, the Pod coder would be able to think in the same terms that he does for ordinary blocks. But assuming for the moment that the pseudo-block idea is off the table, how about saying that an ambient code alias is normally terminated by the next blank line or Pod directive (as per =for) unless you give it a :begin adverb, in which case it terminates with an appropriately nested =alias name :end directive: =alias outer :begin while (...) { =alias inner blah blah blah } =alias outer :end Unless there's some reason why adverbs don't work for =alias directives, that's fully consistent with normal syntax. OTOH, that's exactly what the problem would be, isn't it? '=alias outer :begin' would be parsed as an inline alias, where outer is equated with :begin. So how about borrowing from your earlier example of numbered items, and identifying explicitly terminated blocks with a + or - immediately following the '=alias': =alias+ outer while (...) { =alias inner blah blah blah } =alias- outer I'm also considering a more radical possibility whereas the ambient code has a means of tagging portions of itself for Pod inclusion. I'll think it through some more and then offer a proposal. Still, I think that treating =alias as a block when it has only one argument, and as a directive when it has none or two, would be more user-friendly (though admittedly more hostile to the guy coding the Pod Parser) than any of these alternatives. Let's see what others think. OK. -- Jonathan Dataweaver Lang
Re: [perl #64566] @a[1..*] adds trailing undef value
David Green wrote: Jon Lang wrote: Given that it's relatively easy to say 1..^*, I wouldn't mind standardizing this so that '*' always refers to the element just past the last one, at least when dealing with the standard index. I like the DWIMmery, but the more I think about it, for such a little difference, it seems more worthwhile to be consistent than to be DWIMy. So, yes, either * always means last+1, and use 1..^*, or make * mean the last index, and use [*+1] to append. ...and if addressed properly, it can be DWIMmy too. In many ways, saying that * is just off the end of the index range is counterintuitive; it's more reasonable to people who haven't been trained to think in terms of Perl 5's negative indices to think of 0 as being the first element and * as being the last element. And again, there are fewer problems with custom indexing if you go this route. But there is a problem with sparse arrays, isn't there? Sparseness is an implementation detail. Arrays all look the same to the user; sparseness just means perl is smart enough to do @foo[1]=$bar without trying to suck up a zillobyte of RAM. To the extent that that is true, @foo.elems should equal 10001. -- Jonathan Dataweaver Lang
Re: directories of interest, a multiplicity alternative to CWD
'home' should be spelled '~'. -- Jonathan Dataweaver Lang
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 7:03 PM, Mark J. Reedmarkjr...@gmail.com wrote: The OS-level chdir() and getcwd() are not thread-safe. The usual advice is to ignore them completely in multithreaded programs, in favor of absolute paths (or relative paths from a fixed location, never calling chdir()). This is part of the a reason that Apache2 recommends fastcgi for non-prefork MPMs (since the CGI spec requires cgi scripts to start with getcwd() set to the directory containing them). I like Timothy's suggestion: do not associate $*CWD with chdir at all, but tie $*CWD in with every standard routine that makes use of the current working directory concept. Keep chdir around, but add a note saying that its use should be avoided in favor of assigning to $*CWD. Ditto with getcwd and reading the value of $*CWD. The only thing that gets clobbered by this is the inability to use relative paths when changing the current working directory. Personally, I have no problem with the idea that $*CWD is a magical Path that resolves itself into an absolute Path when you assign a relative Path to it (that is, $*CWD = ($path.relative ?? $*CWD ~ $path :: $path).resolvepath, or something to that effect) - and thus is always an absolute Path; but I can understand that others have a problem with this. On a similar note, I wouldn't mind a bit of magic that has $*CWD test for the existence of the new value before actually making the change, and throwing an exception if the target is not a directory; that way, you're guaranteed that $*CWD is always a valid Path. With this magic in place, I would never be tempted to use chdir or getcwd. Alternatively, $*CWD should be readonly and have a chdir method that implements the above behavior, emulating the features of the OS's chdir in a thread-safe manner. Or just warn people _not_ to alter $*CWD directly, and change chdir and getcwd so that they alter and read $*CWD appropriately by default, and only perform their OS equivalents if you explicitly ask them to. -- Jonathan Dataweaver Lang
Re: Filename literals
Timothy S. Nelson wrote: David Green wrote: Jon Lang wrote: If so, could you give some examples of how such a distinction could be beneficial, or of how the lack of such a distinction is problematic? Well, my main thought in this context is that the stuff that can be done to the inside of a file can also be done to other streams -- TCP sockets for example (I know, there are differences, but the two are a lot the same), whereas metadata makes less sense in the context of TCP sockets; I guess this was one of the thoughts that led me to want separate things here. Ah. I can see that. Well, I definitely think there needs to be a class that combines the inside and the outside, or the data and the metadata. Certainly the separate parts will exist separately for purposes of implementation, but there needs to be a user-friendlier view wrapped around that. Or maybe there are (sort of) three levels, low, medium, and high; that is, the basic implementation level (=P6 direct access to OS- and FS- system calls); the combined level, where an IO or File object encompasses IO::FSnode and IO::FSdata, etc.; and a gloss-over-the-details level with lots of sugar on top (at the expense of losing control over some details). Hmm. With the quoting idea, I don't see the need for a both type of object. I mean, I'd see the code happening something like this: if (path{/path/to/file}.e) { �...@lines = slurp(path{/path/to/file}); } Or... if (path{/path/to/file}.e) { $handle = open(path{/path/to/file}); } (I'm using one of David's suggested syntaxes above, but I'm not closely attached to it). For the record, the above syntax was my suggestion. I guess what I'm saying here is that I think we can do the things without people having to worry about the objects being separate unless they care. So, separate objects, but hide it as much as possible. Is that something you're fine with? It looks good to me. In fact, having q, Q, or qq involved at all strikes me as wrong, since those three are specifically for generating strings. Pathnames still are strings, so that's fine. In fact, there are different Hmm. I'm not so sure; maybe I'm just being picky, but I want to clarify things in case it's important (in other words, I'm thinking out loud here to see if it helps). First, Q and friends don't generate strings, they generate string-like objects, which could be Str, or Match, or whatever. Think of quoting constructs as a way of temporarily switching to a different sublanguage (cf. regex), and you'll have the idea that I have in mind. As for pathnames being strings, you may be right FSVO string. But I'd say that, while they may be strings, they're not Str, but they do Str, as in role IO::FSNode does Str {...} (FSNode may not be the right name here, but is used for illustrative purposes). I'd go one step further. Consider the Windows path 'C:\Program Files\'. Is the string what's really important, or is it the directory to which the string refers? I ask because, for legacy reasons, the following points to the same directory: 'C:\PROGRA~1\'. Then there's the matter of absolute and relative paths: if the current working directory is 'C:\Program Files\', then the path 'thisfile' actually refers to 'C:\Program Files\thisfile'. And because of parent directory and self-reference links, things like '/bin/../etc/.' is just an overcomplicated way of pointing to '/etc'. I'd like Perl 6's treatment of filenames to be smart enough that smart-matching any of these pairs of alternative spellings would result in a successful match. So while I'll agree that filenames are string-like, I really don't want them to _be_ strings. things going on here; one is to have a way of conveniently quoting strings that contain a lot of backslashes. Just as Perl lets you pick different quotation marks, to make it easier to quote strings that have a lot of or ' characters, so it should have a way to make it easy to quote strings with a lot of backslashes. (The most obvious example being Windows paths; but there are other possibilities, such as needing to eval some code that already has a lot of backslashes in it.) Now, you can already turn backwhacking on or off via Q's :backslash adverb; Q:qq includes :b (and Q:q recognises a few limited escape sequences like \\). So you could say Q[C:\some\path], and you could add scalar interpolation to say Q:s[C:\some\path\$filename]. But there's no way to have all of: literal backslashes + interpolation + escaped sigils. Perhaps instead of a simple :b toggle, we could have an :escapeStr adverb that defaults to :escape\? Then you could have Q:scalar:escape(^)[C:\path\with\literal^$\$filename]. Maybe a global variable? It's an interesting idea, and I'll see how others feel :). I'm leery of global variables, per se; but I _do_ like the idea
Re: Filename literals
Troels Liebe Bentsen wrote: Hey, Just joined the list, and I too have been thinking about a good path literal for Perl 6. Nice to see so many other people are thinking the same :). Welcome to the list! Not knowing where to start in this long thread, I will instead try to show how I would like a path literal to work. A well-considered proposal, and one with which I mostly agree. Some thoughts: The default p{} should only allow / as separator and should not allow characters that won't work on modern Windows and Unix like \ / ? % * : | , etc. The reason for this is that portable Path's should be the default and if you really need platform specific behavior it should be shown in the code. I note that you explicitly included * and ? in the list of forbidden characters; I take it, then, that you're not in favor of Path as a glob-based pattern-matching utility? E.g.: my Path $path; ... unless $path ~~ pastro* { say the file doesn't begin with 'astro'. } Admittedly, this particular example _could_ be accomplished through the use of a regex; but there _are_ cases where the use of wildcard characters would be easier than the series of equivalent tests that Perl would otherwise have to perform in order to achieve the same result. Hmm... maybe we need something analogous to q vs. qq; that is: pastro* #`{ syntax error: '*' is not a valid filename character. } ppastro* #`{ returns an object that is used for Path pattern-matching; perhaps Pathglob or somesuch? } We should allow windows style paths so converting and maintaining code on this platform is not a pain. : For Unix specific behavior we should have a p:unix{} literal, here the only limit are what is defined by locale. : And for people where this is a problem p:bin{} can be used as no checking is done here. : Old style Mac paths could also be supported where the : is used as separator. : Or old dos paths where 8 char limits and all the old dos stuff apply. Hear, hear. Note that these are all mutually exclusive, which suggests that the proper format ought to be something like: my Path $path = p:formatwin{C:\Program Files} However, I have no problem with the idea that :win is short for :formatwin; the feature here is brevity. Urls could also be support with: my Path $path = p:url{file:///home/test.file} I would be very careful here, in that I wouldn't want to open the can of worms inherent in non-file protocols (e.g., ftp, http, gopher, mail), or even in file protocols with hosts other than localhost. ** Path Object like File::Spec, etc. just nicer ** : ** Comparing Paths should do the right thing ** Agreed on all counts. ** Utility functions ** Path in itself knows nothing about the filesystem and files but might have a peek in $*CWD to do some path logic. Except for that a number of File related functions might be available to make it easy to open and slurp a file a Path points to. my File $file = p{/etc/passwd}.open; if($file.type ~~ 'text/plain') { say looks like a password file; } my @passwd = p{/etc/passwd}.lines; if(p{/etc/passwd}.exists) { say passwd file exists; } As soon as you allow methods such as .exists, it undermines your claim that Path knows nothing about the filesystem or files. IMHO, you should still include such methods. -- Jonathan Dataweaver Lang
Re: S26 - The Next Generation
On Sun, Aug 16, 2009 at 1:26 PM, Damian Conwaydam...@conway.org wrote: * This means Pod can be indented; the = is no longer tied to the first column. The indentation preceding the opening = (using the ($?TABSTOP // 8) rule, as for heredocs) now specifies the zeroth column of the Pod block. Will ther be any ambiguity between Pod and wraparound operators that begin with =? e.g., my Dog $spot = new Dog; # Pod, or Perl assignment? if really_long_expression == value { ... } # Pod, or equality operator? * In addition to delimited, paragraphed, and abbreviated Pod blocks, documentation can now be specified in a fourth form: my $declared_thing; #= Pod here until end of line sub declared_thing () { #=[ Pod here until matching closing bracket ] ... } Note the recent revisions to how Perl comments work - in particular, an embedded comment is now spelled #`[ ... ]. Should embedded attached Pod be spelled as #=`[ ... ]? My preference would be to simply say that if the very first character within a comment is an =, then it becomes a Pod attachment. That is, we're not dealing with a variation of the Pod Comment syntax (i.e., s/#/#=/); rather, we're dealing with a special use of a normal comment. Thus, an embedded Pod attachment would be written as #`[=...]. The main benefit of this would be that if any further refinements occur to Perl's comment syntax, Pod will adapt to those changes seamlessly[1]. As well, this would help with any effort that might be made to integrate the use of Pod into other languages: e.g., Javascript-with-Pod would handle a Pod attachment as /*=...*/ or //=... (for embedded and end-of-line comments, respectively). -- Jonathan Dataweaver Lang [1] Not to derail the conversation, but I would consider this to be another argument in favor of the proposed '(#...)' syntax for embedded comments: with this syntax, an embedded Pod attachment would be spelled '(#=...)'. Much more aesthetically pleasing.
Re: S26 - The Next Generation
Could we also get =numbered and =term directives that are equivalent to =item :numbered and =item :term, respectively, for use with abbreviated blocks? E.g.: =numbered First Item =numbered Second Item =numbered Third Item =term First Name Definition =term Second Name Definition Within tables, you should probably replace whitespace with multiple whitespace as a column delimiter; otherwise, the space between two words in an identifier would trigger a new column: column 1 column 2 ^^ ^ ^^ ^ (Each group of ^'s would be a separate column.) When using the code block alias, are the outermost curly braces considered to be part of the ambient code? Why is =END a block, and not a directive? -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
On Tue, Aug 11, 2009 at 12:42 PM, Jon Langdatawea...@gmail.com wrote: jerry gay wrote: for the latest spec changes regarding this item, see http://perlcabal.org/svn/pugs/revision/?rev=27959. is everyone equally miserable now? ;) Already seen it. My latest points still stand, though: #`(...) is still vulnerable to ambiguity relative to #..., whereas `#(...), `#...#`, or (#...) don't share the same vulnerability. With the latest S26 proposal (and its new declarator blocks) in mind, I think that I would be happiest if embedded comments used the (#...) syntax. Reason: you still get the flexibility of choosing your own delimiters (unlike `#...#`), and you don't have to worry about where the = goes (unlike #`(...): is it #=`(...), #=(...), or #`(=...)? Likewise for `#(...)). -- Jonathan Dataweaver Lang
Re: Filename literals
On Sat, Aug 15, 2009 at 7:17 AM, Timothy S. Nelsonwayl...@wayland.id.au wrote: On Sat, 15 Aug 2009, Austin Hastings wrote: This whole thread seems oriented around two points: 1. Strings should not carry the burden of umpty-ump filesystem checking methods. 2. It should be possible to specify a filesystem entity using something nearly indistinguishable from standard string syntax. I agree with the first, but the relentless pursuit of the second seems to have gone beyond the point of useful speculation. What's wrong with File('C:\Windows') or Path() or Dir() or SpecialDevice()? Not to get all Cozens-y or anything, but chasing after ways to jam some cute string-like overloading into the syntax so that we can pull out the other overloading (which at least had the virtue of simplicity) seems pointless. The File::* functionality is probably going to be one of the very early p6 modules, and it is probably going to be in core. If that's true, why not allocate some really short names, ideally with 0 colons in them, and use them to spell out what's being done? S32/IO already specifies all these things as living in the IO namespace. That could be changed, of course. Neither q:io:qq:{.} nor qq:io{.} really stand out at excellent ways to say q:io{.} would be the normal case, unless you want variable interpolation or the like. And it would be possible to come up with shorter versions (someone suggested qf). this is a path, or directory, or file, or whatever. If it's plug-in-able, I'd take qq:file{.} or qq:dir{.} or qq:path{.}, but I'd rather see C File q{.} . I'm not particularly attached to :io if we can think of something better. These things often have a short name and a long name. I'm against file because the IO::File object models what is inside the file (ie. open/read/write/close/etc), whereas the IO::FSNode/IO::FileNode/IO::DirectoryNode/IO::LinkNode objects model stuff on the outside of the file. It's things of this second type that I'm recommending that we return here. We could change the names of the objects of course, but I'm keen on keeping the class that does stuff to the inside of the file separate from the class that does stuff to the outside of the file. Path might be a good alternative in my mind. IOW, your outside the file stuff is whatever can be done without having to open the file, and your inside the file is whatever only makes sense once the file has been opened. Correct? If so, could you give some examples of how such a distinction could be beneficial, or of how the lack of such a distinction is problematic? Anyway, back to the :io name. An alternative might be to have the short name be :p and the long name be :path. That would mean that we could do: q:p{.} Isn't there something in the spec that indicates that qq is merely shorthand for q:qq? That is, it's possible to bundle a bunch of quote adverbs together under a special quote name. If so, you might say that q:path and q:p are longhand for path: path{.} # same as q:p{.} And yes, 'path' is longer that 'q:p' - but only by one character; and it's considerably more legible. As well, this is more in keeping with what's really going on here: path{.} would be no more a string than m{.} or rx{.} are. In fact, having q, Q, or qq involved at all strikes me as wrong, since those three are specifically for generating strings. Also note the following: string # same as qq[string] 'string' # same as q[string] /pattern/ # same as m[pattern]? The ultimate in path literals would be to establish a similar default delimiter. For example, what if the backtick were pressed into service for this purpose? (No, I'm not actually suggesting this; at the very least, there would be p5 false-compatibility issues involved. This is strictly illustrative.) `path` # same as path[path] `path`.e # does that filename exist? Returns boolean. `path`.size # how big is the file? Returns number. `path`.open # Returns new file handle. That's a fair bit shorter than Path(q{.}). Hmm. Let's compare some code samples: if (q:p'/path/to/file' ~~ :r) { say Readable\n; } if (Path('/path/to/file') ~~ :r) { say Readable\n; } if (path'/path/to/file'.r) { say Readable; } if (`/path/to/file`.r) { say Readable; } $fobj = new IO::File(FSNode = q:p'/path/to/file'); $fobj = new IO::File(FSNode = Path('/path/to/file')); $fobj = path[/path/to/file].open; $fobj = `/path/to/file`.open; I used single quotes for the Path() things because I think that's what people would probably do. Now, say we want to use backslashes. if (Q :p {C:\Windows\file} ~~ :r) { say Readable\n; } if (Path(Q {C:\Windows\file}) ~~ :r) { say Readable\n; } if (path:win[C:\Windows\file].r) { say Readable; } Anyway, we have possibilities. Further thoughts anyone? As illustrated above, I think
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
Ben Morrow wrote: However, I would much rather see a general syntax like (# ... ) {# ... } [# ... ] with no whitespace allowed between the opening bracket and the #: this doesn't seem to conflict with anything. Allowing # ... in rules would also be nice. That's rather elegant. It's no longer than the current embedded comment syntax, and avoids the start-of-line issue. The only complication arises when you prepend the brackets with a quote or pseudo-quote character: say q(# is this a string or a comment?); # DWIM - string. -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
smuj wrote: Jon Lang wrote: smuj wrote: Jon Lang wrote: Here's a radical notion: use something other than '#' to initiate an inline comment. [snippage] Or maybe just don't allow embedded comments unless they are actually embedded, i.e. if a line starts with a # (ignoring leading whitespace) then it's _always_ a line-end comment, no matter what follows the #, e.g. That has the advantage of preserving a three-character embedded comment. It has the disadvantage that you get differing behavior depending on where the comment is on the line. As I see it, the whole point of this exercise is to get rid of the gotchas, and not just to shift them around - thus my ':#' proposal. I think whatever the solution is, it must begin with a # -- anything else will likely create even more gotchas. When inline comments begin with a '#', the main gotcha arises when you go to comment out a series of lines by prepending a # to each, and one of those lines begins with the proper series of characters to create an inline comment instead. If you add the condition that a line beginning with a '#' is automatically a full-line comment (or, as currently specced, simply complains about the ambiguity), you replace this gotcha with one where someone types in what he intends to be an inline comment, but forgets to indent it. Adding a secondary character after the '#' reduces the likelihood of this happening, but doesn't eliminate it. When inline comments begin with something other than '#', none of the above gotchas exist. Instead, the main gotcha occurs when you go to create an end-of-line comment at the end of a line that ends with whatever the first character of an inline comment is. A programmer who forgets to put whitespace between that character and the '#' will get an inline comment instead. IMHO, this is no different than any other case where the programmer mistakenly allows two different tokens to run together. As well, when programmers add comments to the ends of a series of lines, they generally lead off with whitespace intended to align said comments with each other; so existing habits would not cause difficulties as they currently do for commenting out lines. Also, we have to realize that no matter what sequence we choose for embedded comments, there will _always_ be a chance of a gotcha, so all we can do is minimize the likelihood, as well as making the gotcha easy to spot, whilst not making embedded comments too difficult to use for those who like them. My argument is that starting an inline comment with something other than a '#' minimizes the likelihood of gotchas, makes gotchas easy to spot, and doesn't make embedded comments too difficult to use for those who like them. Is there anything that my argument missed? My current personal favourite would be to keep things as they are with regards to bracketing, but to introduce a + between the # and the brackets. This reduces the likelihood of ambiguity cropping up between an embedded comment and an end-of-line comment; but it doesn't eliminate the possibility. Reversing the order to '+#' _would_ eliminate any possibility of ambiguity at the start of a line; and the only thing you'd have to watch out for would be someone deciding to start an end-of-line comment immediately after a '+', with no intervening whitespace. As well, '+#' is just as easy to type as '#+'. Heck, while I like the bracketing idea, you could even say that any comment that begins with '+#' followed immediately by a non-bracketing character is an inline comment that will be terminated by the first '#+' sequence it finds: #end-of-line comment #(end-of-line) comment #+end-of-line comment #+(end-of-line) comment +# embedded comment #+ +#(embedded comment) I'm not picky as to the choice of the additional character; but if you're going to add it in, add it in where it will cause the least amount of trouble: just before the '#'. I'd also change the terminology from embedded comments to extended comments. toMAYto, toMAHto. -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
Ben Morrow wrote: This appears to be leading to a :comment modifier on quotables, with some suitable shortcut. Perhaps 'q#'? Or are we not allowed mixed alpha and symbols? It's probably a bad practice, if possible. (I really want to suggest £, just to teach USAnians '#' isn't called 'pound'... :) ) In all seriousness, there's another use to which I'd like to put '£'. -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
jerry gay wrote: for the latest spec changes regarding this item, see http://perlcabal.org/svn/pugs/revision/?rev=27959. is everyone equally miserable now? ;) Already seen it. My latest points still stand, though: #`(...) is still vulnerable to ambiguity relative to #..., whereas `#(...), `#...#`, or (#...) don't share the same vulnerability. -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
On Mon, Aug 10, 2009 at 12:25 PM, Patrick R. Michaudpmich...@pobox.com wrote: I'd be fine with the ##(embedded comment solution) approach (doubling the #'s), but it's much less visually appealing to me. I think I'd prefer to see a doubling of the bracketing chars instead of doubling the #'s -- the # is visually a heavy glyph and I'd prefer something a bit lighter. #((embedded comment)) #{{embedded comment}} I could definitely go with this. The only question lies in how often you're likely to find a doubled open-bracket at the start of a line. However, let me toss out some other possibilities for consideration: If you want lightweight, another possibility would be to insist that an inline comment must be preceded by horizontal whitespace; so #{ comment } would be an end-of-line comment, whereas #{ comment } would be an inline comment. This is in keeping with the current spec's use of whitespace to distinguish between a start-of-line comment and an inline comment. Then again, perhaps that's a bit _too_ lightweight. And it adds to another problem that I have with Perl 6, namely the variety of mandatory/forbidden whitespace rules. They are, IMHO, a necessary evil, and should be kept to a minimum. Plus, when I typed the latter one out in this message, the composition window wrapped the line between the start of the quote and the #. One of the lesser purposes of an inline comment is when you're passing code through channels that might insert word-wraps into the code: an end-of-line comment has the possibility of breaking, whereas the inline comment handles it without complaint. Another possibility: instead of ## for an inline comment, how about some other two-character pair that starts with a '#', where the second character is a non-bracketing character that's unlikely to be found at the start of a line? E.g., '#:' - the colon is visible, lightweight, and is almost always tacked onto the end of something else. In this approach, the minimum number of characters needed for an inline comment will be four: the '#:' pair, an open-bracket, and a close-bracket. (Compare to '#{{ ... }}', which requires a minimum of five characters.) It also avoids the question of how much repetition of the '#' is permitted. So: #line comment #:line comment #(line comment) #:(inline comment) OTOH, :( ... ) is the Perl syntax for a signature; and it wouldn't be unreasonable to find a signature at the beginning of a line. Far less common than the current situation of finding an open-bracket there; but perhaps too common to ignore. I'd recommend '#='; but if that isn't already being used by pod, it should be reserved for use by pod (and it's visually heavy). What other symbols are reasonably easy to type, are visually lightweight, and are unlikely to be found at the start of a line and immediately followed by an open bracket? Hmm... how about '#.'? #line comment #.line comment #(line comment) #.(inline comment) -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
On Mon, Aug 10, 2009 at 2:16 PM, Mark J. Reedmarkjr...@gmail.com wrote: I still like the double-bracket idea. I don't much mind the extra character; 5 characters total still beats the 7 of HTML/XML. Agreed. As I said, the biggest potential stumbling block for this would be the existence of a double-bracket that sees frequent use at the start of a line. Query: does '' count as a double bracket, or as a single bracket (since it's equivalent to '«')? If the former, then there's a respectable chance of seeing a line that begins with '' which would comment out as an inline comment rather than an end-of-line comment. If the latter, lines beginning with '' would still comment out as end-of-line comments. Off the top of my head, I can't think of any other bracketing characters that are commonly doubled up. -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
On Mon, Aug 10, 2009 at 3:36 PM, Darren Duncandar...@darrenduncan.net wrote: Personally, I think that comments should have trailing # as well as leading ones, so they are more like strings in that the same character is used to mark both ends. You mean like the following? q[quoted text] qq(interpolated quote) spattern = string rx(pattern) The leading # in an inline comment is akin to the q|qq|s|tr etc. of the various pseudo-quote structures: it identifies to what purpose the brackets are being used. A trailing # would be superfluous. Note that my proposal is orthogonal to other issues like double-leading # or whatever bracketing chars are used. Also note that if the # are treated more like delimiters, then potentially we could also have \# to escape literal #, same as we have \' or \ etc. Ugh. One of the reasons for the likes of q ... , etc. is to provide an alternative to having to escape the delimiter by allowing you to select a delimiter that won't clash. By making '#' a delimiter, you remove that ability. -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
smuj wrote: smuj wrote: Jon Lang wrote: ... the biggest potential stumbling block for this would be the existence of a double-bracket that sees frequent use at the start of a line. Query: does '' count as a double bracket, or as a single bracket (since it's equivalent to '«')? If the former, then there's a respectable chance of seeing a line that begins with '' which would comment out as an inline comment rather than an end-of-line comment. If the latter, lines beginning with '' would still comment out as end-of-line comments. Off the top of my head, I can't think of any other bracketing characters that are commonly doubled up. [S02] {Note however that bare circumfix or postcircumfix ... is not a user-selected bracket, but the ASCII variant of the «...» interpolating word list. Only # and the q-style quoters (including m, s, tr, and rx) enable subsequent user-selected brackets.} Just to clarify on that quote from S02, what I was trying to say (if I understand the synopsis correctly) is that counts as either single or double depending on context. If you stick a # on the front, then will count as a double bracket. Thanks for the clarification. Either we change this so that '' counts as a single bracket for inline comment purposes, or we live with the risk of start-of-line inline comments '# ... ' when prepending #'s to comment out sections of code. Or we leave it as is. Is it really _that_ big of a problem to retrain yourself to type # instead of # when commenting out lines? Here's a radical notion: use something other than '#' to initiate an inline comment. I suggested before the possibility of '#:' as the inline comment identifier; what if we reverse this, and require ':#' instead? This would completely remove the risk of a start-of-line comment being confused with an inline comment. It would be visially lightweight. It would be short (four characters minimum). It wouldn't require you to double up on anything. And the only danger would be if you try to insert a comment immediately after a colon, with no intervening whitespace - which strikes me as an _extremely_ bad practice which should be discouraged regardless. So: # line comment #(line comment) :# syntax error (missing brackets) :#(inline comment) -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
Darren Duncan wrote: Still, I like the idea of #...# also being supported from the point of symmetry with '...' and ... also being supported, not that this is necessary. This is mutually exclusive with the practice of commenting out a bunch of lines by prepending them with '#'. -- Jonathan Dataweaver Lang
Re: Embedded comments: two proposed solutions to the comment-whole-lines problem
smuj wrote: Jon Lang wrote: Here's a radical notion: use something other than '#' to initiate an inline comment. [snippage] Or maybe just don't allow embedded comments unless they are actually embedded, i.e. if a line starts with a # (ignoring leading whitespace) then it's _always_ a line-end comment, no matter what follows the #, e.g. That has the advantage of preserving a three-character embedded comment. It has the disadvantage that you get differing behavior depending on where the comment is on the line. As I see it, the whole point of this exercise is to get rid of the gotchas, and not just to shift them around - thus my ':#' proposal. OTOH, you just (inadvertently?) pointed out that ':#...' is very much like adverbial syntax; this could be quite useful if we ever find a need for the parser to associate comments directly with code, in that anything that can take an adverb could theoretically have a comment associated with it. But that's a can of worms that doesn't need to be opened yet, if ever. We could always have a Q form in place of #'s to achieve the above effect from S02, more like a funny heredoc, e.g. Q :# # embedded sub foo # comment { # extends ... # to } # (wait for it) # here! Maybe call it a theredoc! :-) We can already do this using POD sections: =begin comment sub foo { ... } =end comment I don't see much need for a #-based multi-line comment beyond this. But it _would_ be nice to be able to indent POD Sections in the same way that you can indent heredocs. Especially if the former is intended to be the standard means of commenting out blocks of lines. OTOH, let's say for the moment that we choose to extend the analogy between embedded comments and quotes: one could, in theory, do a Heredoc-style comment: :# END line 1 line 2 line 3 END where ':#' is the comment-equivalent of 'q', whatever that turns out to be. (I'm not sold on ':#'; but I _would_ like to see a two-symbol token that begins with a non-'#' and ends with a '#', for conciseness and clarity.) Technically, this would also allow for the likes of ':#comment'. But I agree with the gentleman from the original discussion years ago that we should probably forbid non-bracketing characters when delimiting embedded comments. -- Jonathan Dataweaver Lang
Re: confusing list assignment tests
Larry Wall wrote: Moritz Lenz wrote: : Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should : get both elements, and so should @z. Not according to S03, at least by one reading. �...@a[0] as a scalar container only wants one item, so it only takes the first item off the list, and the list assignment produces a warning on the second because it's discarded. Since an assignment returns its left side, only one element is available to @z from @a[0]. So, do we still have p5's 'want_array' (or whatever it was called)? That is, the predicate that tells the you whether the function is being called in item or list context? I know that the generalized 'want' function proved to be unworkable; but I'd expect p6 to at least be able to do everything that p5 can do; and that includes functions that are aware of whether they're being used as singular or plural. -- Jonathan Dataweaver Lang
Re: confusing list assignment tests
Damian Conway wrote: Mark J. Reed wrote: My understanding is that the P6 way to do that is to return a Capture containing the desired return values (which can lazily do things only when accessed) in the appropriate slots. Return a Capture or a more heavily overloaded object, depending on how fine a degree of context discrimination you need. Further to that idea, I'm actually planning to attempt to port Contextual::Return to Perl 6 in the next few weeks. Right. I don't think that a Capture has sufficiently fine context discrimination to handle even those cases that Perl 5 was able to handle. For instance, consider a function that's intended to return a list of items in list context, or a count of the items in item context: since imposing item context on a Capture object extracts the first positional parameter, a Capture object wouldn't be able to be loaded properly to do this. So something along the lines of Contextual::Return is probably a good idea. Hmm... it might be nice to be able to use something akin to a given ... when construct: sub foo() { return context { when Item { 5 } when List { a, b, c, d, e } } } The idea here is that the 'context' keyword means that the block is to be called as soon as the desired context is known, with said context being passed to the block as its topic ('$_'). -- Jonathan Dataweaver Lang
Re: r27635 - docs/Perl6/Spec
On Mon, Jul 20, 2009 at 6:03 PM, pugs-comm...@feather.perl6.nl wrote: Author: lwall Date: 2009-07-21 03:03:38 +0200 (Tue, 21 Jul 2009) New Revision: 27635 Modified: docs/Perl6/Spec/S03-operators.pod Log: [S03] rename 'nonchaining infix' to 'structural infix' Modified: docs/Perl6/Spec/S03-operators.pod === --- docs/Perl6/Spec/S03-operators.pod 2009-07-20 23:56:21 UTC (rev 27634) +++ docs/Perl6/Spec/S03-operators.pod 2009-07-21 01:03:38 UTC (rev 27635) @@ -42,7 +42,7 @@ X Junctive and also X Junctive or | ^ L Named unary sleep abs sin temp let - N Nonchaining infix but does = leg cmp .. ..^ ^.. ^..^ + N Structural infix but does = leg cmp .. ..^ ^.. ^..^ C Chaining infix != == = = eq ne lt le gt ge ~~ === eqv !eqv X Tight and X Tight or || ^^ // min max Hmm... maybe Chaining infix should become Comparison? -- Jonathan Dataweaver Lang
Re: r27635 - docs/Perl6/Spec
On Mon, Jul 20, 2009 at 7:15 PM, Darren Duncandar...@darrenduncan.net wrote: Jon Lang wrote: On Mon, Jul 20, 2009 at 6:03 PM, pugs-comm...@feather.perl6.nl wrote: Modified: docs/Perl6/Spec/S03-operators.pod === --- docs/Perl6/Spec/S03-operators.pod 2009-07-20 23:56:21 UTC (rev 27634) +++ docs/Perl6/Spec/S03-operators.pod 2009-07-21 01:03:38 UTC (rev 27635) @@ -42,7 +42,7 @@ X Junctive and also X Junctive or | ^ L Named unary sleep abs sin temp let - N Nonchaining infix but does = leg cmp .. ..^ ^.. ^..^ + N Structural infix but does = leg cmp .. ..^ ^.. ^..^ C Chaining infix != == = = eq ne lt le gt ge ~~ === eqv !eqv X Tight and X Tight or || ^^ // min max Hmm... maybe Chaining infix should become Comparison? I second that notion, ... assuming that the category would not later be expanded with other operators that don't fit the Comparison description. Tight or includes min and max; I see nothing wrong with the Comparison precedence level eventually picking up a handful of operators that aren't comparators, as long as so many of them are. And especially if the question being asked when creating a new operator is should this have the same precedence as the comparison operators? A stronger argument against it would be to find comparison operators that exist at other precedence levels. I don't think that there are any. (Well, besides =, leg, and cmp.) Indeed, I'll be surprised if there are any other precedence levels that are chaining - which is another key point: what kind of operator would be chaining, but _not_ some sort of comparison? And please don't even consider instead using the term Relational in reference to these operators, that some people do. The Comparison term is more descriptive, and it doesn't conflict with other meanings of relational that relational databases deal with. Seconded. :) -- Jonathan Dataweaver Lang
Re: YAPC::EU and Perl 6 Roles
Raphael Descamps wrote: Am Freitag, den 10.07.2009, 17:06 -0700 schrieb Jon Lang: How about this: in role composition, mandate causes methods to take precedence over other methods with which they would normally conflict, and to conflict with methods that would normally take precedence over them. I really dislike this because it is contrary to the original idea of the stateless traits as defined in the original paper from Nathanael Schärli. Agreed. OTOH, Roles are already contrary in this respect, because they can provide attributes as well as methods. Note also that this was my first proposal; I have since abandoned it in favor of (I hope) a more intuitive approach. The main reason why traits have been introduced was to solve the problems inherent to mixins. In mixins the main problem is that the class using the mixin is not able to control the composition (which is simply done sequencially) and that lend to fragile hierarchies. The brilliant idea with traits is that it bring back the control to the class consuming the trait and conflicts have to be solved explicitly. The traits paper propose 3 different operators to solve such conflicts: overriding, excluding or aliasing. I definitively think that perl 6 roles should also have an excluding operator because I think that *every* composition conflicts arising should be solvable by the class comsuming the role. What you propose here is a step behind: you reintroduce the problem existing with mixins by bringing back precedence rules in the way composition is made. Well, yes and no. The class still has the final say on how a given method is to be implemented; the only thing being debated here is whether or not the class should have to explicitly pull rank to redefine a method being provided by a role, or if it does so silently. The latter approach is how things currently stand, and is being criticized as a source of bugs as authors of classes inadvertently override method definitions that they didn't intend to override. So far, I have only seen reference to the original paper decribing the stateless traits. As roles are an implementation of stateful traits, maybe we should start to point to the paper formalising it: http://scg.unibe.ch/archive/papers/Berg07eStatefulTraits.pdf Thanks for the link. -- Jonathan Dataweaver Lang
Re: YAPC::EU and Perl 6 Roles
TSa wrote: HaloO, Jon Lang wrote: Well, yes and no. The class still has the final say on how a given method is to be implemented; the only thing being debated here is whether or not the class should have to explicitly pull rank to redefine a method being provided by a role, or if it does so silently. The latter approach is how things currently stand, and is being criticized as a source of bugs as authors of classes inadvertently override method definitions that they didn't intend to override. I think the distinction can be made implicitly. Methods in a role with no implementation are silently overridden. Ones with an implementation produce a warning if the composing class overrides it without some extra syntax. This bites only the case where the role provides a default implementation intended for overriding. Perhaps. FWIW, applying the supersede keyword to the class method would work as the extra syntax to which you refer. Your last sentence is pointing to the distinction that I was trying to make with the mandate/suggest pairing. For clarity, let me propose the following terminology: an interface is a role with methods that suggest their implementations by default; a mixin is a role with methods that mandate their implementations by default. I could see adopting one of these terms as a variation on role and treating role itself as the other one; if we do this, which would be preferable: interfaces and roles, or roles and mixins? That is: when you think role, do you think of the interface semantics or the mixin semantics most readily? -- Jonathan Dataweaver Lang
Re: RFC: overriding methods declared by roles (Was: Re: Reusing code: Everything but the kitchen sink)
Daniel Ruoso wrote: Jon Lang wrote: The key to understanding roles is to note that roles don't implement methods; classes implement methods. Er, while I see your point, Roles are not just interfaces... they are OO components that can be plugged into other classes. They often are used for type identity exactly because of that attribute, since you won't be enforcing any hierarchy. Right. But as they were originally conceived, they were interfaces that could also handle code reuse, rather than units of code reuse that could also be used as interfaces. From this perspective, it makes perfect sense that a role's methods can be overridden as easily as they are. But you make a good point: there are some (a few? most?) programmers who are going to want to use roles primarily for code reuse, and who will want it to be a little more difficult to override the code provided by a role (e.g., requiring the use of supersede and perhaps augment in order to replace the definition with a new one). First and foremost, this distinction between suggested ans mandatory implementation is what I was trying to make a little more explicit in my proposal: a suggested method can be overridden by the class with no extra effort; a mandatory method requires that the class be explicit about the override. The next question is which of these approaches Perl 6 should use with roles. Currently, it's using suggested implementations; what I'm hearing you say is that you'd rather have mandatory implementations. IMHO, there's a time ans place for both; so I was trying to come up with a compromise of sorts: a way of letting the programmer select the approach that most suits his needs. Roles define which methods must be implemented, and suggest ways that they might be implemented; classes decide which implementation to use. Anything that breaks this paradigm is a Bad Thing. That's not the common conception in Roles usage, specially in Moose. As I said, Roles are not just interfaces, they are OO reuseable components. FWIW, I never said that they're just interfaces. Also, I question whether that is or is not the common conception of role usage. I readily admit that it isn't so in the programming circles that you travel in; but are you typical of the perl community in this regard? This is not a rhetorical question; the way that we end up addressing this issue hinges on this question: should roles provide suggested implementations by default, or should they provide mandatory implementations by default? Even if Perl is rich enough to provide for both, the decision of which way to go when no explicit decision has been made is an important one. The spec itself says: Classes are primarily for instance management, not code reuse. Consider using Croles when you simply want to factor out common code. Right: roles are preferable to classes when it comes to code reuse. That doesn't necessarily mean that roles are _primarily_ intended for code reuse. They _might_ be; but if so, it's because they've grown beyond their original concept. The key issue here is Perl 6 wasn't yet used to the extent that Moose::Roles are, and Moose people have identified that the use of Roles as reusable components raised the issue when the class inadvertedly overrides one of the methods that are implemented by one of the composed roles. You know what? Until Moose was mentioned in this conversation, I had never heard of it. I did think that this should be the expected behavior, but when the people that is heavily using it says it took me a lot of time to debug, it indicates that there's something wrong with the behavior. So now I changed my mind, inheritance is about overriding behavior, so when you implement a method in the subclass it is a natural thinking that this should override the superclass, but when you think about it really carefully this logic doesn't really map well to Roles (considering roles as OO reuseable components). That may indeed be the case. It's entirely possible that we may want to change things so that roles define mandated methods, and possibly introduce interfaces as a variation of roles that define suggested methods. But we may instead want to keep roles as they are, and define some other variation that works just like a role except that it mandates its methods. And its also possible that I'm fundamentally wrong about this, and that we _don't_ need both approaches available for roles. That being said, I'd think the following as an interesting solution: role R1 { method foo() {...} # degenerates to interface } role R2 does R1 { method bar() { # some implementation } method baz() { # some implementation } } class Bla does R2 { method foo { # implementing here is natural, since the role only # declared a stub, it's even a warning not to implement it } supersede method bar { # explicitly tells that I want to ignore
Re: Reusing code: Everything but the kitchen sink
The key to understanding roles is to note that roles don't implement methods; classes implement methods. Roles define which methods must be implemented, and suggest ways that they might be implemented; classes decide which implementation to use. Anything that breaks this paradigm is a Bad Thing. Where things get slightly fuzzy is that there is one case where a class is implicitly assumed to accept an implementation suggested by a role - namely, if that implementation is the only one available. Otherwise, the role is required to explicitly define a given method's implementation. David Green wrote: Jonathan Worthington wrote: The spec is right in that you need to write a method in the class that decides what to do. This will look something like: method fuse() { self.Bomb::fuse() } That makes sense for using the combined role on its own, but can we still handle separate roles that get mixed together? That is, after defining that method so I can call $joke.fuse(), can I still call $joke.Bomb::fuse and $joke.Spouse::fuse as well? This is one of the distinctions between role composition and class inheritance. With class inheritance, the full tree of inherited classes is publicly accessible; with role composition, the methods of the combined role are the only ones that are made available to the class. In effect, a combined role acts as a middle manager that looks over the available implementations and picks one, provides its own alternative, or defers the decision to its boss (i.e., the class or role into which it is composed). Either way, once the class has chosen an implementation, that is the implementation that will be used. As I understand it, the reason for this has more to do with attributes than with methods: with role composition, you want to be able to cut away any attributes that have become extraneous to the implementations defined in the class. E.g.: role R { has $foo; } class C does R { method foo() is rw { doIO() } } The idea here is that C has chosen to implement foo by querying an outside source (such as a database) whenever a read request is made of it, and by sending information to an outside source whenever a write request is made. It never refers to the internal state that R defined. As such, there's no reason for C to set aside memory to track an internal state. You can't do this if someone is allowed to explicitly call R::foo from any object of class C, overriding C's choice as to how foo should be implemented. I'm thinking that it's useful to be able to refer to the fully-qualified names for anything composed into a role or class; often there will be no ambiguity, so the full name won't be necessary. If the names aren't unique, then you can specify them fully, and perhaps add an unqualified fuse() that does one or the other (or both? or neither??) for convenience. That shouldn't be necessary, I think -- it just means you would have to spell out exactly which method you wanted. This is class inheritance think. In role composition think, you should never have to worry about how the composed roles might have done things once composition is complete; you only concern yourself with how the class does things. In the case Ovid also mentioned where two roles have a method of the same name because both methods really are doing the same thing, there ought to be a way to indicate that (though if they both come with implementations, you'd still have to pick one or write your own). Of course, in a perfect world, the common method would come from its own role: if Foo.fuse and Bar.fuse really mean Foo.Bomb::fuse and Bar.Bomb::fuse, then doing Foo and Bar together should automatically give you a single .fuse method (again, at least as far as the interface is concerned). You have a point: it would be nice if you didn't have to engage in unnecessary conflict resolution. Of course, this may actually be the case already; it all depends on how the compiler decides when to complain about conflicting methods. role R { method foo() { say foo } role R1 does R { method bar() { say bar } role R2 does R { method baz() { say baz } class C does R1 does R1 { } The question is whether or not Rakudo is smart enough to realize that R1::foo is the same as R2::foo, or if it complains that R1 and R2 are both trying to supply implementations for foo. The former is the desired behavior. I guess being able to create a role by dropping some bits from an existing role would be useful sometimes, but it seems to lose one of the most useful benefits of roles: as Jon Lang pointed out, R1 :withoutfoo bar would effectively be a new role, one that doesn't do R1. But you want something to do a role in the first place so that it will work anywhere else there is code looking for that role. Obviously, someone who explicitly drops methods from a role isn't concerned with the new role being usable wherever the original role could
Re: Reusing code: Everything but the kitchen sink
The key to understanding roles is to note that roles don't implement methods; classes implement methods. Roles define which methods must be implemented, and suggest ways that they might be implemented; classes decide which implementation to use. Anything that breaks this paradigm is a Bad Thing. Where things get slightly fuzzy is that there is one case where a class is implicitly assumed to accept an implementation suggested by a role - namely, if that implementation is the only one available. Otherwise, the role is required to explicitly define a given method's implementation. David Green wrote: Jonathan Worthington wrote: The spec is right in that you need to write a method in the class that decides what to do. This will look something like: method fuse() { self.Bomb::fuse() } That makes sense for using the combined role on its own, but can we still handle separate roles that get mixed together? That is, after defining that method so I can call $joke.fuse(), can I still call $joke.Bomb::fuse and $joke.Spouse::fuse as well? This is one of the distinctions between role composition and class inheritance. With class inheritance, the full tree of inherited classes is publicly accessible; with role composition, the methods of the combined role are the only ones that are made available to the class. In effect, a combined role acts as a middle manager that looks over the available implementations and picks one, provides its own alternative, or defers the decision to its boss (i.e., the class or role into which it is composed). Either way, once the class has chosen an implementation, that is the implementation that will be used. As I understand it, the reason for this has more to do with attributes than with methods: with role composition, you want to be able to cut away any attributes that have become extraneous to the implementations defined in the class. E.g.: role R { has $foo; } class C does R { method foo() is rw { doIO() } } The idea here is that C has chosen to implement foo by querying an outside source (such as a database) whenever a read request is made of it, and by sending information to an outside source whenever a write request is made. It never refers to the internal state that R defined. As such, there's no reason for C to set aside memory to track an internal state. You can't do this if someone is allowed to explicitly call R::foo from any object of class C, overriding C's choice as to how foo should be implemented. I'm thinking that it's useful to be able to refer to the fully-qualified names for anything composed into a role or class; often there will be no ambiguity, so the full name won't be necessary. If the names aren't unique, then you can specify them fully, and perhaps add an unqualified fuse() that does one or the other (or both? or neither??) for convenience. That shouldn't be necessary, I think -- it just means you would have to spell out exactly which method you wanted. This is class inheritance think. In role composition think, you should never have to worry about how the composed roles might have done things once composition is complete; you only concern yourself with how the class does things. In the case Ovid also mentioned where two roles have a method of the same name because both methods really are doing the same thing, there ought to be a way to indicate that (though if they both come with implementations, you'd still have to pick one or write your own). Of course, in a perfect world, the common method would come from its own role: if Foo.fuse and Bar.fuse really mean Foo.Bomb::fuse and Bar.Bomb::fuse, then doing Foo and Bar together should automatically give you a single .fuse method (again, at least as far as the interface is concerned). You have a point: it would be nice if you didn't have to engage in unnecessary conflict resolution. Of course, this may actually be the case already; it all depends on how the compiler decides when to complain about conflicting methods. role R { method foo() { say foo } role R1 does R { method bar() { say bar } role R2 does R { method baz() { say baz } class C does R1 does R1 { } The question is whether or not Rakudo is smart enough to realize that R1::foo is the same as R2::foo, or if it complains that R1 and R2 are both trying to supply implementations for foo. The former is the desired behavior. I guess being able to create a role by dropping some bits from an existing role would be useful sometimes, but it seems to lose one of the most useful benefits of roles: as Jon Lang pointed out, R1 :withoutfoo bar would effectively be a new role, one that doesn't do R1. But you want something to do a role in the first place so that it will work anywhere else there is code looking for that role. Obviously, someone who explicitly drops methods from a role isn't concerned with the new role being usable wherever the original role could
Re: YAPC::EU and Perl 6 Roles
Larry Wall wrote: Dave Whipp wrote: Ovid wrote: I'd like to see something like this (or whatever the equivalent Perl 6 syntax would be): class PracticalJoke does Bomb does SomeThingElse { method fuse() but overrides { ... } } The overrides tells Perl 6 that we're overriding the fuse() method from either Bomb or SomeThingElse (or both). Otherwise, a warning or exception would be useful to prevent me from accidentally overriding needed behavior. This would also be useful to catch the case where you mistype the override method, and so have to go debug why you're still using the base-class (or role) version of the method. Note we already have syntax that can be applied here: supersede method fuse {...} augment method fuse {...} It only remains to spec what those mean... :) supersede already has a meaning with respect to classes; and what I'm thinking of would apply to classes as well as roles; so I'm going to suggest another keyword. How about this: in role composition, mandate causes methods to take precedence over other methods with which they would normally conflict, and to conflict with methods that would normally take precedence over them. So: role R1 { mandate method foo { ... } } role R2 { method foo { ... } } class C does R1 does R2 { ... } Normally, the compiler would complain of a conflict between R1 and R2; but because R1::foo is mandated, it wins out. role R { mandate method foo { ... } } class C does R { method foo { ... } } Normally, C::foo would take precedence over R::foo; but because R::foo is mandated, the compiler complains of a conflict between C and R. When two methods have the mandate keyword, they are compared to each other as if neither had the keyword. role R { mandate method foo { ... } } class C does R { mandate method foo { ... } } Since both R::foo and C::foo are mandated, C::foo supersedes R::foo. Applying the mandate keyword to a role is shorthand for applying it to all of its methods. mandate role R { method foo { ... } method bar { ... } method baz { ... } } is the same as: role R { mandate method foo { ... } mandate method bar { ... } mandate method baz { ... } } This behavior can be overridden by the suggest keyword: mandate role R { suggest method foo { ... } method bar { ... } method baz { ... } } is the same as: role R { method foo { ... } mandate method bar { ... } mandate method baz { ... } } That is, every method is either mandated or suggested, and suggested by default. Mandating a role changes the default for its methods, or you could explicitly suggest the role. The latter possibility would allow for a pragma that changes the role's default importance from suggested to mandated. Ovid's distinction between interface and unit of behavior could be managed by this distinction: suggest role R is primarily intended as an interface, with behavior being a suggestion only and implicitly overriden by the class; mandate role R is primarily intended as a unit of behavior, and overriding its behavior requires that you explicitly supersede it. In Ovid's programs, he might start by saying use mandate, so that roles operate as units of behavior by default, and can be declared as interfaces by saying suggest role instead of role. Or maybe the pragma declares interface as a synonym for suggest role. (I'd be more comfortable with this if I could think of a comparable synonym for mandate role; at that point, you could do away with the pragma - use role, suggest role, or interface to mean interface, and use mandate role or ??? to mean unit of behavior.) At this point, you can strengthen the importance of a method (raising it from a suggestion to a mandate); but you cannot weaken it. Thus, interfaces can be composed into units of behavior; but not vice versa: attempting to do so would result in a unit of behavior. I think that the converse _should_ be possible; but I'm not quite sure how it might be done. -- Jonathan Dataweaver Lang
Re: Huffman's Log: svndate r27485
On Fri, Jul 10, 2009 at 2:22 PM, Austin Hastingsaustin_hasti...@yahoo.com wrote: Mark J. Reed wrote: I'm all for not having any variety of log() in the default namespace. Regardless, mathematical functions should follow mathematical norms. Changing Perl tradition is one thing, but we have centuries, sometimes millennia, of tradition to deal with in the mathematical realm. It should not be violated lightly. That's okay. Preserve their thousands of years of historical legacy. Just preserve it in a separate container. #! /usr/bin/perl6 say(log(1000, 10)); # Error - no such function log use Math::Simple; say(log(1000, 10)); # 2.999... Ugh; no thanks. However, it occurs to me that when you log messages, you should specify where you're logging them as well as what they are. log(Str) might lead to ambiguous results; but IO.log(Str) should be pretty clear. But maybe I'm not understanding what people are wanting out of message logging. -- Jonathan Dataweaver Lang
Re: YAPC::EU and Perl 6 Roles
Jon Lang wrote: supersede already has a meaning with respect to classes; and what I'm thinking of would apply to classes as well as roles; so I'm going to suggest another keyword. How about this: in role composition, mandate causes methods to take precedence over other methods with which they would normally conflict, and to conflict with methods that would normally take precedence over them. Or, perhaps more simply, say that if you mandate a method in a role, you must supersede it in whatever you are composing it into in order to override the definition. So: role R { mandate method foo { ... } } class C does R { supersede method foo { ... } } I'd still recommend the suggest/mandate pairing, and their application directly to methods or indirectly via the role; the only change is that mandate be redefined as Thou Shalt Not Override This/These Methods... and supersede becomes ...Unless You Really Mean It. Conflicts still occur as normal when composing multiple roles; the only catch is that you _have to_ resolve them using a supersede method if any of the conflicting methods are mandated. Or maybe not. Perhaps a conflict between composed roles cancels out the conflicting method implementations whether or not any of them are mandates, leaving the class free to define its own version. That is, the only time you must supersede a method is when you're trying to override a single mandate method. I'd still like to get a synonym for mandate role, though - a word that captures the meaning of unit of behavior. -- Jonathan Dataweaver Lang
Re: YAPC::EU and Perl 6 Roles
Jonathan Worthingtonjonat...@jnthn.net wrote: Ovid wrote: Though I have issues with Jonathan's approach (I don't like classes silently discarding role methods as this has caused us many bugs at the BBC), it's much cleaner that what I see here. s/Jonathan's approach/Perl 6's approach/ # at least, so far as I understand Perl 6 No; I think he meant Jonathan's approach, as in the suggestion that I made earlier about disambiguating by exclusion. It occurs to me that but might be a way to approach this, since the linguistic purpose of that operator is to generate a class or role that is a slight departure from an existing role: A but without(foo) might generate an anonymous role that's exactly like A except that it doesn't have the foo method; you could then say something like: role A { method foo() { }; method bar() { }; method baz() { } } role B { method foo() { }; method bar() { }; method baz () { } } class C does A but without(foo, bar) does B but without(baz) { } I agree that there are dangers involved in excluding methods from a role; thus my use of fairly lengthy phrases in order to accomplish it - a sort of handle with care warning. Alternatively, I could see a version of this exclusionary policy being done through method delegation, by means of the whatever splat - something like: class C { has A $a handles * - (foo, bar); has B $b handles * - baz; } -- Jonathan Dataweaver Lang
Reusing code: Everything but the kitchen sink
Jonathan Worthington wrote in YAPC::EU and Perl 6 Roles: More fitting to me would be an adverb to the does trait modifier... class C does R1 :withoutfoo bar does R2 :withoutbaz { ... } The thing is that in this case, does the class actually do R1 and R2? If you are going to derive an anonymous role with the methods missing, then answer is no. That is, C ~~ R1 would be false. So I think it'd need to act as a modifier to the action of composition, rather than a modification to the thing that we're composing. Moving the adverb from the role to the trait modifier would still violate the notion that C ~~ R1; so it doesn't actually gain us anything. Instead, consider the following possibility: R1 :withoutfoo bar is a separate but related role from R1. The implicit relationship between them is that R1 ~~ R1 :withoutfoo bar. So C ~~ R1 would be false; but C ~~ R1 :withoutfoo bar would be true. I wonder if we'd want to mandate that a method of the name must come from _somewhere_ otherwise it's an error. At least then you get a promise that a method of that name exists...which is about all that it does this role tells you as an interface contract anyway. Right. Another way to handle this without establishing reverse-does relationships that I describe above would be to say that the adverb doesn't actually remove the method in question; it just suppresses its implementation. That is, given: role R1 { method foo() { say foo } } class C does :blockingfoo R1 { ... } this would compose R1 into C, but would discard the implementation of R1::foo while doing so. In the spirit of TIMTOWTDI, both approaches could be available: R1 :withoutfoo acts as an anonymous role that R1 implicitly does, and which is set up almost exactly like R1 except that it doesn't have method foo. This could have other uses besides role composition, such as expanding a web of roles from the specific to the general. C does :blockingfoo R1 composes R1 into C, but discards foo's implementation while doing so. Alternatively, I could see a version of this exclusionary policy being done through method delegation, by means of the whatever splat - something like: class C { has A $a handles * - (foo, bar); has B $b handles * - baz; } The RHS of the handles is something we smart-match the method name against (unless it's one of the special syntactic cases). And thus if you care about performance you probably don't want to be falling back to handles to do your role composition, since it's kind of the last resort after we've walked the MRO and found nothing. You're right, but for a different reason. Perl 6 has three techniques for code reuse, which I refer to as the be, do, have triad: Class inheritance (to be): 'is C;' Role composition (to do): 'does R;' Attribute delegation (to have): 'has A $a handles foo;' Just on a conceptual level, you don't want to fall back on attribute delegation in order to emulate role composition. Still, there are uses for delegating to all or most of an attribute's methods. Anyway, you'd put something on the RHS maybe like: has A $a handles none(foo bar) But I'm not sure that will fall through to B for anything that A doesn't define other than those two. You'd perhaps just get a dispatch error if you said A handles everything but those and it didn't. So it'd probably look more like... has A $.a handles all(any(A.^methods.name), none(foo bar)); Which you almost certainly don't want to be writing. ;-) Right; which is why I was looking for a more abbreviated form. If we go with the idea that we're using a Set on the RHS, then '*' could be shorthand for 'Set($a.^methods)', and 'Set::infix:-' could be the Set Difference operator, with the item, list, or set on the RHS being excluded from the LHS. So: $a handles * - foo bar would be short for something like: $a handles Set($a.^methods) - Set(foo, bar) This use of the Whatever splat is similar to its use in a list index, where '*' behaves as if it were the list's element count. -- Looking this over, I note that the only code reuse mechanism for which we haven't looked at the everything except... concept is class inheritance. OTOH, I think that the blocking tool that works for role composition could be adapted for use with class inheritence as well: Class C is :blockingfoo bar C1 is :blockingbaz C2 { ... } That is, if you were to search the class heierarchy for foo, it would skip the C1 branch in its search. This would have to be treated with care, because it would mean that C doesn't inherit everything from C1. This _would_ break the anything you can do I can do, too nature of class inheritence; but I'm not sure how big of a crime that is. Perl generally discourages the use of class hierarchies, and it certainly isn't the preferred means of type-checking. And maybe you could get around this by having the isa predicate return a more involved response than
Re: YAPC::EU and Perl 6 Roles
On Tue, Jul 7, 2009 at 2:48 AM, Ovidpubliustemp-perl6langua...@yahoo.com wrote: Giving a talk about roles at YAPC::EU in Lisbon and I'm a bit stuck on how to translate a Perl 5 example into Perl 6. Basically, Imagine a PracticalJoke class which has fuse() and explode methods(). It needs the timed fuse() from a Bomb role and a non-lethal explode() from a Spouse role, though each role provides both methods. In Moose, it's easy: package PracticalJoke; use Moose; with 'Bomb' = { excludes = 'explode' }; 'Spouse' = { excludes = 'fuse' }; Try as I might, I can't figure out how to translate that into Perl 6. I have the following: role Bomb { method fuse () { say '3 .. 2 .. 1 ..' } method explode () { say 'Rock falls. Everybody dies!' } } role Spouse { method fuse () { sleep rand(20); say Now! } method explode () { say 'You worthless piece of junk! Why I should ...' } } class PracticalJoke does Bomb does Spouse { } Nothing I see in S14 (http://perlcabal.org/syn/S14.html) seems to cover this case. I can't declare them as multis as they have the same signature. There's a note that one can simply to write a class method that overrides the conflicting role methods, perhaps figuring out which role method to call, but I don't understand how a particular role's methods would be called here. I believe that the official word is to say: class PracticalJoke does Bomb does Spouse { method fuse () { Bomb::fuse } method explode () { Spouse::explode } } Personally, I agree that some sort of ability to exclude individual methods from Roles, such as what Moose does, would be beneficial; but this is an old argument that has been hashed out many times before. -- Jonathan Dataweaver Lang
Re: Signature for the series operator
On Thu, Jun 25, 2009 at 1:20 PM, Moritz Lenzmor...@faui2k3.org wrote: Hi, I had the pleasure to implement the series operator (infix:...) in Rakudo(*), and came across the difficulty to come up with a signature for it. These are the use cases I want to cover: 1, 2 ... { $^a + $^b } 1 ... { $_ + 1 } The first one can clearly be written as sub infix:...(@values, Code $geneator) but the second will fail to bind to that signature, because the 1 isn't a list. I'd like to write sub infix:...(*...@values, Code $generator) instead, but I think that required positional parameters are forbidden after slurpy arrays. Do I have to install another multi that accepts a single scalar? Or is there a neat trick to cover both use cases with a single signature? I'm surprised that '1, 2 ... { $^a + $^b }' binds properly. I suppose that it's because of the relative precedences of '...' vs ','. ',' gets evaluate first, combining 1 and 2 into a two-element list; then that list gets fed into the left side of '...'. If that's not the case, then I don't see why '...' isn't just grabbing the '2', and then failing to bind it because '2' isn't a list. Perhaps non-associating infix operators should be an exception to the usual rules concerning signatures, seeing as how you are guaranteed to have exactly two positional parameters. In particular, I'm thinking that a non-associating infix operator might be permitted to have a slurpy array as either _or both_ of its positional parameters, on the theory that Perl 6 should strive to allow as much flexibility as possible within the constraints of ambiguity. (Currently, I believe, it's sheer nonsense to have a slurpy array in either position.) Or perhaps not; this may open a can of worms that we don't want to mess with. I can think of two complications off the top of my head: pipes and reducing operators. If you allow a slurpy list on either side of an infix operator, how does that interact with piping operators? If you allow one on both sides, how do you determine which one you're piping to? If you reduce the operator so that it operates according to function syntax (i.e., name first; then parameters) and the first parameter is a slurpy list, how will you know when the first parameter ends and the second begins? Do you use an all but the last rule? etc. -- Jonathan Dataweaver Lang
Re: XOR does not work that way.
On Wed, Jun 24, 2009 at 10:35 AM, John Macdonaldj...@perlwolf.com wrote: On Tue, Jun 23, 2009 at 07:51:45AM +1000, Damian Conway wrote: Perl 6's approach to xor is consistent with the linguistic sense of 'xor' (You may have a soup (x)or a salad (x)or a cocktail), [ ... ] That choice tends to mean exactly one, rather than the first one the waiter hears. (A good waiter will explain the choice limitation at the time the order is made rather than having to deal with it being escalated to a complaint when the missing item is demanded.) Which means that short-circuiting is not right here - it must go through the entire list to determine whether there are zero true selections, find the first of exactly one true selections, or die if there are more than one true selections. Which, I believe, is exactly how XOR short-circuiting currently works: it short-circuits to false if both sides are true; otherwise, it returns true or false as usual for XOR and continues on down the chain. -- Jonathan Dataweaver Lang
Re: XOR does not work that way.
On Mon, Jun 22, 2009 at 4:12 PM, Minimiscienceminimiscie...@gmail.com wrote: On Jun 22, 2009, at 5:51 PM, Damian Conway wrote: Perl 6's approach to xor is consistent with the linguistic sense of 'xor' (You may have a soup (x)or a salad (x)or a cocktail), and also with the IEEE 91 standard for logic gates. I don't think natural language -- especially the abomination that is English -- is the best guide for understanding logical operations (why, yes, I *do* speak Lojban; how did you know?). As for consistency, Perl 6's bitwise exclusive-or operators follow the mathematical meaning of XOR, so using the exactly one true value definition for ^^ and xor would make Perl 6 inconsistent with itself. You're aware that Perl was designed by a linguist, with an eye toward incorporating natural language concepts, right? As for the bitwise xor: I consider the inconsistency between it and the logical xor to be a feature, not a bug. Mind you, it's a feature that needs to be made apparent; but it's a feature nonetheless. Specifically, it gives you a simple way of choosing which semantics you wish to use: '^' gives you the natural language semantics, while '?^' gives you the mathematical semantics. This gives the programmer an easy way of choosing which semantics he wants to use. I was going to say more in support of adding a separate operator for exactly one true value, but Darren Duncan beat me to it. Well, we already have one to mean exactly one true value. -- Jonathan Dataweaver Lang
Re: XOR does not work that way.
Take a look at the page to which Damian provided a link. You'll find that XOR does indeed correspond to the definition being used by Perl 6, as well as the natural language meaning. What other languages call XOR is actually an odd parity check. As I suggested above, I think that Perl 6 already addresses both of these: use '^' or 'xor' (or 'one()') if you want XOR semantics; use '?^' if you want odd parity semantics. I suggest that to aid learnability, Perl 6 has the same semantics for 'xor' as other languages with that operator, unless there is a good explicit reason to do differently; that is, don't do differently just for the heck of it. We never do things differently for the heck of it. -- Jonathan Dataweaver Lang
Re: Multi-d array transforms (was Re: Array rotate)
On Fri, Jun 12, 2009 at 11:23 PM, Matthew Waltonmatt...@matthew-walton.co.uk wrote: Although some things may be able to be implemented far more efficiently if they know that they're being called with infix:.= and not with infix:.. Last I checked, Perl 6 had some types that are mutating and others that aren't (e.g., List and Array, I think). An additional benefit of setting up the primitive methods as non-mutating is that you increase the amount of functionality shared by the two: if all mutating methods are syntactic sugar for non-mutating counterparts, then non-mutating types will be able to do everything that their mutating brethren can do (except mutate, of course). E.g., a List can push, unshift, splice, etc; an Array can append, perpend, impend, etc. And if you want to do purely functional programming, you can do so by restricting yourself to the use of non-mutating types and staying away from those methods that have side effects (which should [i]also[/i] be easily identifiable). Indeed, this same notion of ensuring that pure functional versions of mutating methods exist should also apply to methods with side effects: as much as possible, if a method is designed to perform a calculation and to produce a side effect, there should also be an equivalent method that merely performs the calculation. Even better would be to segregate the methods that produce side effects from the methods that perform calculations. Am I making sense? -- Jonathan Dataweaver Lang
Re: Array rotate
On Fri, Jun 12, 2009 at 10:02 AM, yarynot@gmail.com wrote: I am tickled pink to see an Array rotate method in the settings spec S032, as I was thinking of writing up a little discussion on the very topic. Has there been discussion on using array rotate on multi-dimensional arrays? Being able to pass in a vector as the amount to rotate would be useful. With a multi-dimensional array, a number of transforms can be considered: * you can rearrange the elements along a given dimension (e.g., rotate and reverse). * you can rearrange the dimensions themselves (e.g., transpose). -- Jonathan Dataweaver Lang
Re: Multi-d array transforms (was Re: Array rotate)
On Fri, Jun 12, 2009 at 10:58 AM, yarynot@gmail.com wrote: * you can rearrange the dimensions themselves (e.g., transpose). Reflecting on 2 or more axes creates a transposition. No, it doesn't: @a = (1, 2, 3; 4, 5, 6; 7, 8, 9); Reflecting on two axes would result in: @a = (9, 8, 7; 6, 5, 4; 3, 2, 1); Transposing the axes would result in: @a = (1, 4, 7; 2, 5, 8; 3, 6, 9); -- Jonathan Dataweaver Lang
Re: Array Dimensionality (Was: Re: Multi-d array transforms (was Re: Array rotate))
On Fri, Jun 12, 2009 at 11:51 AM, Daniel Ruosodan...@ruoso.com wrote: Ok, There's one thing that is not clear in the thread, which is when an array is multidimensional or not... For instance: �...@a = (1, 2, 3; 4, 5, 6; 7, 8, 9); Will produce a flatten array, because list assignment causes flattening, so the dimensionality was lost. Right. I should have said: @@a = (1, 2, 3; 4, 5, 6; 7, 8, 9); -- Jonathan Dataweaver Lang
Re: Assigning duplicate values to several hash keys using junctions?
2009/6/8 Ville Koskinen vrk...@iki.fi: Hello all, I was curious if this is possible in Perl 6: %hash{ 'foo' 'bar' } = 'some value'; # %hash{'foo'} eq 'some value' and %hash{'bar'} eq 'some value' By autothreading, this would be equivalent to: (%hash{'foo'} %hash{'bar'}) = 'some value'; which in turn is the same as: (%hash{'foo'} = 'some value') (%hash{'bar'} = 'some value'); So yes, this is possible. -- Jonathan Dataweaver Lang
Re: Implicit threading vs Imperative barriers
On Thu, Jun 4, 2009 at 9:57 AM, TSa thomas.sandl...@vts-systems.de wrote: HaloO, Daniel Ruoso wrote: So the questions are: * Are there any imperative barriers in Perl 6? I would think that at least every method call is a barrier. An object's lifetime is a sequence of states and methods are either returning information about the state or calculate a new state. The latter cannot be concurrent. Furthermore it is usually a bad idea to have an object in several concurrent computations such that streams of mutating method calls interleave. So objects destined for parallel computing need some explicit locking mechanism. Perhaps it isn't the method call that's the barrier, but rather the mutating function. If you do nothing but call a series of non-mutating methods, I don't see how it matters how quickly any given one of them gets evaluated, or even in what order they're evaluated, as long as the information is ready by the time you need it. But as soon as you call a mutating method, you'd better get all of those pending non-mutating calls taken care of before you proceed with the mutating call. Rule of thumb: if you want to be lazy, look but don't touch. -- Jonathan Dataweaver Lang
Re: Module naming conventions
On Mon, Jun 1, 2009 at 5:44 PM, Daniel Carrera daniel.carr...@theingots.org wrote: I think we might need to come up with some sort of standard naming convention to distinguish dependencies. Something that the *user* can recognize quickly when he browses CPAN. Why do we need the dependencies to be part of the name? Perl 6 provides a rugged versioning system for its modules; we should use it. -- Jonathan Dataweaver Lang
Re: Amazing Perl 6
On Fri, May 29, 2009 at 6:52 AM, John Macdonald j...@perlwolf.com wrote: Yep, I've done that. But comparing the difference in effort between: - press a key - Google for a web page that has the right character set, cut, refocus, paste means that I don't bother for the one or two weird characters every few months that is my current Unicode usage. If I were working with Unicode frequently, it would be worth setting up links and mechanisms, or learning the keyboard compose sequences for frequently used characters. I'm sure that there are many people in a similar situation. Agreed. Given the frequency with which « and » come up in Perl 6, I'd love to be able to have a simple keyboard shortcut that produces these two characters. Unfortunately, I am often stuck using a Windows system when coding; and the easiest method that I have available to me there (that I know of) is to pull up Character Map. -- Jonathan Dataweaver Lang
renaming or adding some operators
On Fri, May 29, 2009 at 6:53 PM, Darren Duncan dar...@darrenduncan.net wrote: I had some thoughts lately about the Perl 6 operators, and wanted to bounce some ideas. Firstly, regarding the string replication ops as documented in Synopsis 3, 'x' and 'xx', I'm wondering whether it might be better to have something that incorporates a '~', since that operation is about catenation. Would perhaps '~*' work better than 'x' to signify better what the operation is doing; the '~' in this case means catenation and the '*' is meant to invoke 'multiply', not 'whatever'. So '~*' means catenate a multiple of times. This would then free up 'x' to be used for something else, if anything. As for a substitution for 'xx', I'm less sure about that. Thoughts? I wouldn't mind 'x' becoming '~x' and 'xx' becoming 'x'; it strikes me as a lot more intuitive - and I've wanted to see this done for a while now. I suppose that you might also introduce a '?x' and/or a '+x' to complete the set, though for the life of me I can't think of how they'd work or what they'd be good for. Secondly, regarding the Bool type, I think it would be useful for Perl 6 to define the full complement of dyadic logical operators, of which I count a few that you don't appear to already have. Probably the best place is in Synopsis 32. Note that all the dyadic ops I am discussing are meant to be read as infix ops only. These are the boolean/logical ops you already have: Niladic ops aka value literals / constants: * Bool::False * Bool::True Monadic: * not aka !, but ¬ alias could be added Dyadic: * and aka , but ∧ alias could be added * or aka ||, but ∨ alias could be added * xor aka ^^ aka !===, but ⊻, ↮ aliases could be added * ===, but xnor, ↔ aliases could be added Now I'm not sure whether or not [also, andthen, orelse] have the desired semantics of any others or not, or whether [if, unless] could be used as a value-resulting infix operator or not. also andthen orelse carry subtly varied semantics involving short-circuiting behavior: andthen and orelse are like and || except that they work off of success/failure instead of true/false; also is an ordered, short-circuiting version of (and thus all). For some time now, I've wanted an analog for '|' and 'any' - but the only name I can think of for it would be 'else', which has some obvious clarity issues. But here are a few more dyadic: * nand aka ⊼ aka ↑ * nor aka ⊽ aka ↓ * implies aka imp aka → * nimp aka ↛ * if aka ← * nif aka ↚ For that matter, as you know, every single boolean/logical operator could also have a bitwise analogue, if people were so inclined. Side note: one thing that I recently learned concerning implication operators is that the direction of the implication doesn't necessarily follow the direction of the arrow. In particular, A if B is A←B, and A only if B is A→B: in both of the original statements, the implication flows right to left. Most of these suggestions could be implemented in a Unicode Operators module; I see little need to put them into the default setting. I'm leery of introducing new unicade operators that don't have ASCII aliases, as you might be inclined to do with set operators. -- Jonathan Dataweaver Lang
Re: renaming or adding some operators
Darren Duncan wrote: Side note: one thing that I recently learned concerning implication operators is that the direction of the implication doesn't necessarily follow the direction of the arrow. In particular, A if B is A←B, and A only if B is A→B: in both of the original statements, the implication flows right to left. I thought that the direction did matter, and that's why there are distinct versions in each direction. It's like how and are the same thing but with the direction reversed, or subset/superset or contains/contained-by. If you read A → B as A implies B then that's the same as if A then B, then the cause-effect reads left to right, which does follow the direction of the arrow, like Perl's if cond() then action(). The point is that it's equally valid to read A → B as A only if B, with the cause-effect going from B to A. You have the same truth table for both A only if B and if A then B, so they use the same logical operator; but the cause/effect flow is reversed between them. -- Jonathan Dataweaver Lang
Re: Amazing Perl 6
On Thu, May 28, 2009 at 1:37 AM, Daniel Carrera daniel.carr...@theingots.org wrote: Hi Damian, This is a really good list. Mind if I copy it / modify it and post it somewhere like my blog? One question: * Compactness of expression + semi-infinite data structures: �...@fib = 1,1...[+] # The entire Fibonacci sequence Very impressive. That's even shorter than Haskell. What's [+] ? How does this work? In Haskell: Start with the addition operator, '1 + 1'. Apply the reducing metaoperator to it so that it works syntactically like a function: '[+] 1, 1'. Instead of calling it, pass a code reference to it: '[+]'. The lazy list then uses that function to extend the list as needed. What I'm wondering is how the list knows to feed two items into '[+]'. While 'infix:+' must accept exactly two arguments, '[+]' can accept an arbitrarily long (or short) list of arguments. -- Jonathan Dataweaver Lang
Re: Continuations
Andrew Whitworth wrote: The issue mentioned in the Synopses is that junctions autothread, and autothreading in a conditional could potentially create multiple threads of execution, all of which are taking different execution paths. At some point, to bring it all back together again, the various threads could use a continuation to return back to a single execution flow. Hmm. If that's the case, let me suggest that such an approach would be counterintuitive, and not worth considering. When I say if any of these books are out of date, review your records for inconsistencies; otherwise, make the books available for use, I don't expect to end up doing both tasks. In a similar manner, I would expect junctions not to autothread over conditionals, but to trigger at most one execution path (continuation?). The real issue that needs to be resolved, I believe, is illustrated in the following statement: if any of these books are out of date, review them. The question, as I understand it, is what is meant by 'them'? Is it these books, or is it the ones that are out of date? In perl 6 terms: $x = any(@books); if $x.out-of-date { $x.review } Is this equivalent to: if any(@books).out-of-date { any(@books).review } or: if any(@books).out-of-date { any(@books.grep {.out-of-date} ).review } I don't mean to reopen the debate; though if we can get some resolution on this, I won't mind. But I _would_ at least like to see the summary of the issue stated a bit more clearly. -- Jonathan Dataweaver Lang
Re: Unexpected behaviour with @foo.elems
On Wed, May 27, 2009 at 7:05 AM, John Macdonald j...@perlwolf.com wrote: On Tue, May 26, 2009 at 04:38:21PM -0700, yary wrote: perl4-perl5.8 or so had a variable that let you change the starting index for arrays, so you could actually make the above work. But then everyone who'd re-arranged their brains to start counting at 0, and written code that has a starting index of 0, would have problems. That was $[ and it goes back to perl 1 or so. I recall experimenting with it a couple of times. Using it, though, means that you have to use $[ as the lower range limit for *every* array everywhere. Is it still a global in Perl 6? I've noticed a trend toward using less expansive scopes, so that setting $[ to 1 might mean that arrays that are defined in the current scope are 1-based instead of 0-based, whereas arrays defined in other scopes (such as inside a function imported from a module) might continue to be 0-based. That gets stale very quickly, and I then decided that I would just never change the setting of $[ and would remove such a change from any code that I called. ...which is probably the cleanest way to handle it. It's for a similar reason that postcircumfix:[ ] always uses $[-based consecutive integers for indexing: you always have a consistent way of referring to, e.g., the first element (@x[0]) or the last element (@x[*-1]), without having to worry about which indexing scheme any particular array might be using. That's also the reason for custom indexing: if you _want_ to use 1-based indexing for a given array, you can always define a custom index and then refer to the first element by saying @x{1}'. -- Jonathan Dataweaver Lang
Re: Unexpected behaviour with @foo.elems
Jonathan Scott Duff wrote: Or perhaps for 0...@foo.end - $k { ... } @foo.keys may not be what the user wanted if @foo is a sparse array. IIRC, you have to explicitly ask for the custom index in order to get sparse array keys. By design, the normal index is never sparse; only the custom index. That said, a case could be made that the custom index rules as currently presented are too restrictive to implement sparse arrays. In particular, the fact that you must map the custom index to the standard index when the array is first created, and that you are not permitted to adjust things later on, kills much of the power inherent in sparse arrays. To implement a sparse array, I'd recommend using hashes. In particular, allow hashes that have sortable keys to be able to access them by number as well as by name - E.g.: my %x = { 'b' = 2, 'c' = 3 } say %x[0]; # same as say %xb %xa = 1; say %x[0]; #same as say %xa -- Jonathan Dataweaver Lang
Continuations
From S09, under Junctions: The exact semantics of autothreading with respect to control structures are subject to change over time; it is therefore erroneous to pass junctions to any control construct that is not implemented via as a normal single or multi dispatch. In particular, threading junctions through conditionals correctly could involve continuations, which are almost but not quite mandated in Perl 6.0.0. What is a continuation? -- Jonathan Dataweaver Lang
Re: Meditations on a Loop
On Thu, May 21, 2009 at 11:25 PM, John M. Dlugosz 2nb81l...@sneakemail.com wrote: Larry Wall larry-at-wall.org |Perl 6| wrote: And since the when modifier counts as a conditional, you can rewrite grep Dog, @mammals as $_ when Dog for @mammals; So perhaps will see a lot of subtypes used this way: subset Odd if Int where { $_ % 2 }; �...@evens = ($_ * 2 when Odd for 0..*); @primes = do $_ if prime($_) for 1..100; becomes @primes = $_ when prime($_) for 1..100; ? Not sure that is any better. subset Prime of Int where { prime($_) } @primes = do $_ when Prime for 1..100; But yes, something does get lost when you have to explicitly pass $_ into a function; its topical nature gets degraded. Back when .prime was shorthand for prime $_, this wasn't a big deal; now, with the fact that you'd somehow have to add a prime method to Int before you could reliably say .prime, it's a bit more of a problem. -- Jonathan Dataweaver Lang
Re: Meditations on a Loop
On Fri, May 22, 2009 at 5:34 AM, Timothy S. Nelson wayl...@wayland.id.au wrote: On Fri, 22 May 2009, Jonathan Worthington wrote: Daniel Ruoso wrote: Em Sex, 2009-05-22 às 01:25 -0500, John M. Dlugosz escreveu: �...@primes = do $_ if prime($_) for 1..100; becomes �...@primes = $_ when prime($_) for 1..100; you gained one stroke, it's certainly better... I think it's time to play golf with Perl 6 already ;) jokes aside, $_ when prime($_) looks more natural than do $_ if prime($_) Yes and: @primes = 1..100.grep: { prime($^n) }; Is actually vaguely, like, readable AND two characters shorter than the best you've managed so far. Oh, if we're looking for readability, I'd look for: 1..100.grep: { prime($^n) } == @primes; It's longer, though :). These are only readable if you know geek-speak (i.e., what does 'grep' mean?). The alternatives being proposed are using words like do, if, when, and for. I think that it's rather impressive that they're coming within a handful of characters of a grep-based version. -- Jonathan Dataweaver Lang
Re: r26700 - docs/Perl6/Spec
@@ -1836,6 +1836,12 @@ prototype objects, in which case stringification is not likely to produce something of interest to non-gurus.) +The C.^parents method by default returns a flattened list of all +parents sorted in MRO (dispatch) order. Other options are: + + :local just returns the immediate parents + :hierarchical the inheritance heirarchy as nested arrays Bad Huffman coding, IMHO. Could we s/hierarchical/tree/? -- Jonathan Dataweaver Lang
Re: Docstrings in Perl 6
This message deals strictly with the syntax of '#='-based POD; the semantics is a separate issue. -- I'd like '#=' to follow similar rules to what '#' follows, with the caveat that a line beginning with '#' counts as a single-line comment no matter what the second character is. Specifically, having the second character be an = does not transform a full-line comment into a single line of documentation. This preserves the ability to comment out a series of lines by prepending a '#' to each of them without having to worry about whether or not any given line will start doing strange things. This means that '#=' can never appear at the start of the line if you want it to denote documentation; but anywhere else is fine. This should be a simple enough rule for a POD parser to handle with minimal trouble. There are additional complications that arise with '#=', such as: say '#='; In order to keep a POD parser from having to parse the code as well, we'd want to say that the #= sequence initiates a POD block that extends to the end of the line. IOW, the POD parser would end up with: CODE: say ' POD: '; But if that's the case, how would you ever actually print the character sequence '#='? Conversely, if you say that the fact that it's within a string literal means that it counts as string characters rather than the start of some POD, the POD parser will need to know how to identify string literals - which, as Perl illustrates, may not be a simple task. A possible middle ground might be to say that '#=' starts some POD, but (e.g.) '\#=' doesn't: where a POD extractor would remove '#=' and the following POD from the resulting code, it would replace '\#=' with '#='. So to actually display the '#=' character sequence, you'd say: say '\#='; With this in play, you can place '#='-based POD literally anywhere except at the beginning of a line. -- With this in mind, I'd propose two forms of '#=', based on what comes after the '='. If it is followed by one or more '['s, you have bracketed POD which is terminated by an equal number of ']'s; otherwise, you have POD which is terminated at the end of the current line. Note that I specifically said '[' rather than 'a bracketing character'; this is for the same reason that 'Ccode' is POD markup, but 'C{code}' isn't. As well, I chose '[' instead of '' to minimize the need to double or triple up on the encapsulating brackets whenever inline POD markup is involved. Compare: #=This text has Iitalics! #=[This text has Iitalics!] #=C$x5 #=[C$x5] Conversely: #=$x[5] = 7 #=[[$x[5] = 7]] ...which isn't too bad IMHO (and is pretty close to a worst-case scenario). Finally, I'd want bracketed POD to follow indentation rules similar to what Hinrik suggested above: if the '#=' is preceded by nothing but whitespace and every line within the bracketed POD starts with at least as much whitespace, trim the shortest whitespace off of every line within the POD. -- Again, note that the above addresses only the syntax of '#='-based POD, and not the semantics. -- Jonathan Dataweaver Lang
Re: junctions and conditionals
Martin Kealey wrote: On Tue, 31 Mar 2009, Jon Lang wrote: Another issue: what happens if conditional code mutates a junction that it filtered? For example: $x = any (-5 .. 5); if $x 0 { $x++ }; At this point, which of the following does $x equal? any(-4 .. 6) # the original junction gets mutated any(-5 .. 0, 2 .. 6) # the filtered part of the original junction gets mutated; the rest is untouched any(2 .. 6) # the filtered part of the original junction gets mutated; the rest is lost I choose #3. Reality can only take one path through a conditional; which one depends on the one/any/all/none binding of the junction. Once you've passed the conditional, you have: one - single matching value (no longer a junction) any - filtered list all - original junction none - empty (*1) I'm a bit worried about 'none', for reasons that I'll get to in a moment. The threading is an implementation detail; the important thing is a junction is collection of values and a smart way of rewriting expressions that contain them, with special treatment for comparison operators (or indeed anything that forces Boolean content): $x CMP all($y,$z) $x CMP $y $x CMP $z $x CMP one($y,$z) $x CMP $y ^^ $x CMP $z (*2) $x CMP none($y,$z) all($x !CMP $y, $x !CMP $z) $x CMP any($y,$z) $x !CMP none($y, $x) $x OP all($y,$z) all( $x OP $y, $x OP $z) $x OP any($y,$z) any( $x OP $y, $x OP $z) $x OP one($y,$z) one( $x OP $y, $x OP $z) $x OP none($y,$z) none($x OP $y, $x OP $z) -Martin (*1: An argument could be made that none should leave the junction alone, the same as all.) (*2: I would like to suggest that the semantics of one be changed to mean pick one (randomly) rather than exactly one. In this respect it would be the same as any except it wouldn't have the overhead of filtering *every* match, just at least one.) A few thoughts here. First: should autothreading be lazy or eager? As things stand, it seems to be eager: the moment you pass a junction into a routine that doesn't ask for a junction in its signature, you autothread that routine. This has the nice benefit of being easy to implement (autothread if the parameter doesn't specify 'junction'; don't autothread if it does); but as has been mentioned before, making life easy on the implementor isn't a primary design goal for Perl. I submit that autothreading should be lazy. As I see it, there are currently three things that can be done with a junction: 1. Nothing. Using the junction as threads paradigm, you bundle the threads together and route them through a given part of the program as a single rope. 2. Autothreading. You feed each thread through individually, and rebundle the results on the other side. 3. Sieving. You feed only some of the threads through a decision point into its guarded region, and rebundle at the end of the guarded region. Option 3 raises some additional questions. What do you rebundle at the end of the guarded region? Just the threads that were passed through it, or all of the original threads? And what happens if the program flow gets rerouted inside the guarded region such that it never comes out the other side? If I say: $x = any(-5 .. 5) if $x 0 { $x++ } if $x ~~ (-1 .. 1) { $x *= 2 } What is $x just before and just after '$x++'? What is $x just before and just after 'if $x 0 { $x++ }'? Ditto with '$x *= 2' and 'if $x 0 { $x *= 2 }'? If I say: $x = any(-5 .. 5) if $x 0 { return } if $x ~~ (-1 .. 1) { doit($x) } What junction should doit be receiving? Second: sub sayit (Str $s) { say $s } sayit 'S' | 5; What should happen? Should the junction be autothreaded, and then one of the threads fail due to a type mismatch? Or does parameter-passing count as a kind of decision-point, such that you only get the sayit 'S' thread? And what happens with the following? sayit none('S'); -- Jonathan Dataweaver Lang
Re: S08 Draft questions (Captures and Signatures)
Jonathan Worthington wrote: Jon Lang wrote: Invocants: * Does anyone object to roles having an invocant, and that invocant referring to the class that is doing the role? Yes; on further reflection, the ability to type that invocant raises all kinds of possible WTFs without a good enough use case. So I'd really rather we don't go down this road. How does this situation differ from the ability to type a method's invocant? I'm thinking that an argument might be made that you don't get to specify any invocant's type: a method's invocant would always be typed as the class to which it belongs (with the value set as the object calling it), while a role's invocant would always be typed as a type reference (i.e., the :: sigil), with the value being the class composing it. Would any significant functionality be lost in such a move? Longnames: * Are placeholder parameters ever considered to be part of a function's longname? (I'm expecting that they aren't: if you want a longname, you ought to specify it in a formal signature.) Placeholder parameters result in a signature being generated based upon them, as far as I can tell (and so far as we've implemented in Rakudo). So yes, they would all count in the long name - or at least, the positional ones. Also note that if you do have placeholder parameters it's illegal to write a signature on the block too. True: forbidding placeholder parameters from counting as part of the longname would effectively forbid functions that use placeholder parameters from _having_ a longname; and if you've explicitly asked for one (via the multi keyword), you should get one. Placeholder parameters: * does the use of placeholder parameters interfere with the use of the slurpy parameters normally provided by the default signature (i.e., *...@_ and *%_)? I'm guessing not. We only generate *...@_ and *%_ for subs when there is no signature; the presence of placeholder parameters generates a signature, so you'd not get them. Exception: methods, where by S12 we always add a *%_ unless the method defines its own slurpy named parameter. Is this the desired behavior, or merely the current behavior? I can see a case for wanting the placeholder parameters to be pushed onto front of the default signature instead of replacing it. -- Jonathan Dataweaver Lang
Re: simultaneous conditions in junctions
On Wed, Apr 1, 2009 at 12:58 AM, Richard Hainsworth rich...@rusrating.ru wrote: Thinking about Jon Lang's -1|+1 example in another way, I wondered about simultaneous conditions. Consider $x = any (1,2,5,6) How do we compose a conditional that asks if any of this set of eigenstates are simultaneously both 2 and 5? Clearly the desired answer for $x is False, but my $x = any(1,2,5,6); say ?( 2 $x 5); # true Is there some combination of any/all that will achieve this? As Carl indicated, there are other ways to do this. For instance, s/ 2 $x 5 / $x ~~ 2 ^..^ 5 /. But as I indicated in a recent email, part of my concern is that those two expressions _ought to be_ equivalent: changing the junction, or making do without one as Carl proposes, doesn't fix this lack of equivalence. As for Carl's proposed alternative: no, it isn't _much_ longer (but it _is_ longer), and _perhaps_ it's _slightly_ more understandable - or perhaps not. Other than making the implementors' lives harder, what's wrong with trying to find a way to get Jonathan's example to work the way people expect it to? I don't understand this aversion to everything remotely hinting of eigenstates/eigenthreads/threshing/whatever. -- Jonathan Dataweaver Lang
Re: S08 Draft questions (Captures and Signatures)
On Wed, Apr 1, 2009 at 5:07 AM, Daniel Ruoso dan...@ruoso.com wrote: Em Ter, 2009-03-31 às 22:54 -0700, Jon Lang escreveu: Yes, I know that there is no S08. I'm working on writing one, and I'd like some feedback to help me do so. ++ My draft is going to be about Signatures and Captures. Thus, my questions: Invocants: The concept of invocant only exists in terms of syntax now. In runtime the invocant is simply the first positional argument. This simplifies things a lot. I think you're confusing signatures with captures here. Captures and the arguments that they, well, capture, don't care about the invocant; but signatures and the parameters that they define still do. * Likewise, if I interpolate a signature with an invocant into another signature (somewhere other than at the start), is this an error, or will the invocant be silently converted into an ordinary positional parameter? What does interpolate a signature mean? ...my bad. For some reason, I made the opposite mistake: I thought that it was possible to assemble a signature out of other signatures. * Why are we using ;; to denote the end of a multi function's longname? Because a capture may have more than one dimension, which would be delimited by ;. Note that I didn't propose ; as the longname terminator. * Can any required parameter be part of the longname, or are only positional parameters allowed? (I'm expecting the latter; but I'd like confirmation.) I suspect you meant named parameter in place of required parameter. I meant both, actually: can required named parameters be part of the longname? For Perl 6.0.0, it is accepted that named parameters don't take part in multi dispatch. OK. * does the use of placeholder parameters interfere with the use of the slurpy parameters normally provided by the default signature (i.e., *...@_ and *%_)? I'm guessing not. Yes, it does. The default signature is the *default*. Having placeholder parameters imply defining a signature, one could argue that *...@_ and *%_ are still part of that generated signature, but @_ certainly won't contain the values that were in the placeholder parameters. ...nor would I expect it to. I'm just wondering if (@_, %_) _are_ still part of a placeholder-generated signature. In short, is there a way to access a slurpy array or hash in a block that uses placeholder parameters? -- Jonathan Dataweaver Lang
junctions and conditionals
In Junction Algebra, Martin Kealey wrote: On Mon, 30 Mar 2009, Mark J. Reed wrote: ( $a = any(-1,+1) = $b ) == ( $a = any(-1,+1) any(-1,+1) = $b ) Clearly, the RHS is true for $a == $b == 0, but I'm not sure the LHS shouldn't also be. Isn't it just syntactic sugar for the RHS? I suspect not. Rather I think that $a = any(-1,+1) = $b corresponds to $tmp = any(-1,+1); $a = $tmp = $b and thence to $tmp = any(-1,+1); $a = $tmp $tmp = $b The more I think about this, the more I come to the conclusion that a junction should appear to have a uniform (single) value in each eigenthread. Ugh. Let me float another problem, and a possible solution to both, that doesn't require persistent threading environments: $x = -1 | +1; if $x 0 { say $x } As I understand junctions right now, the result of this code is identical to: say -1 | +1; In both cases, the problem arises when you apply a predicate to a junction, and then use the junction within code that only gets executed according to the truth of the predicate. The possible solution to both of these: junctions collapse when they hit conditional statements - but only within the conditioned scope. So: within the code block for the if $x 0 statement above, $x only equals +1, since -1 didn't pass the test. Thus, say $x is the same as say 1. In the case of the range test, the code on the RHS of the only executes if the code on the LHS evaluated to true; therefore, when evaluating the RHS, $tmp doesn't include any of the possibilities that would have failed on the LHS. That means that: 0 = -1 | +1 = 0 ...becomes: 0 = -1 | +1 +1 = 0 ...which, obviously, is false. Extending this further: $x = +1 | -1; if $x 0 { say $x is positive. } else { say $x is negative. } I suspect that both codeblocks would be executed; but within the first block, $x == +1, and within the second codeblock, $x == -1. $x = +1 | -1; say $x 0 ?? $x + 2 :: $x * 2; In this case, $x is +1 when evaluating $x + 2, and it is -1 when evaluating $x * 2. After this expression is fully evaluated, they get recombined into a single junction: +3 | -2. This last one might be easier to manage simply by having $x autothread through the ?? :: operator, since you need to be able to reassemble a junction on the other end. -- Jonathan Dataweaver Lang
Re: junctions and conditionals
I've been having some second thoughts concerning this. Here's where I stand on it now: In Perl 6, you have the following decision points, where code may or may not be executed depending on a condition: if/unless/while/until/loop/when statements; if/unless/while/until statement modifiers; short-circuit operators; the trinary conditional operator. When you apply a junction to a decision point, only one of the possible paths will be taken; and the any/all/one/none nature of the junction will determine which one. (Without this, there would be no reason to have a distinction between any/all/one/none.) However, I stand by my proposal that after passing one of these decision points, and until you get back to code that would have been reached regardless of the decision point, every junction that was involved in the decision point should be limited such that it acts as if only those possibilities within it that would have passed the decision point exist. With unless, while, until, and loop, the associated block is the conditional block where the junction gets filtered. With if, the main block likewise filters the junctions; but the else block also provides junction filtering, but in a way that's complementary to what the main block does. With short-circuit operators, the RHS counts as a block that provides junction filtering based on what it would take for the LHS to avoid tripping the short-circuit behavior. Similarly, ?? :: treats the expression following the ?? as a junction-filtering block and the expression following the :: as a complementary junction-filtering block, in direct analogy to if/else, above. Finally, there's the when statement: as with if, etc., the block that follows the when statement filters junctions according to the match criterion. However, when is a bit more complicated in terms of getting it to DWIM w.r.t. junctions. Because of the way that when works conceptually, I'd recommend that for the rest of the block containing the when statement, it should provide the same sort of complementary filtering that an else block does for an if statement. That is: given $x { when $a { ... } when $b { ... } when * } ...should not be thought of as being equivalent to: given $x { if $_ ~~ $a { ...; break } if $_ ~~ $b { ...; break } if $_ ~~ * {...; break } } ...but rather: given $x { if $_ ~~ $a { ... } else { if $_ ~~ $b { ... } else { if $_ ~~ * { ... } } } } -- Another issue: what happens if conditional code mutates a junction that it filtered? For example: $x = any (-5 .. 5); if $x 0 { $x++ }; At this point, which of the following does $x equal? any(-4 .. 6) # the original junction gets mutated any(-5 .. 0, 2 .. 6) # the filtered part of the original junction gets mutated; the rest is untouched any(2 .. 6) # the filtered part of the original junction gets mutated; the rest is lost -- Jonathan Dataweaver Lang -- Jonathan Dataweaver Lang
S08 Draft questions (Captures and Signatures)
Yes, I know that there is no S08. I'm working on writing one, and I'd like some feedback to help me do so. My draft is going to be about Signatures and Captures. Thus, my questions: Invocants: * Is it illegal to specify an invocant in a sub, or is it merely nonsensical? That is, should the compiler complain, or should it silently treat the invocant as the first positional parameter? (The latter has the advantage that you don't have to worry about what the signature is being used for; it has the disadvantage of being, well, nonsensical: invocants are meaningless without the context of a method - and /maybe/ a role - to provide them meaning.) * Likewise, if I interpolate a signature with an invocant into another signature (somewhere other than at the start), is this an error, or will the invocant be silently converted into an ordinary positional parameter? * What types are you allowed to assign to an invocant? * Does anyone object to roles having an invocant, and that invocant referring to the class that is doing the role? Longnames: * Why are we using ;; to denote the end of a multi function's longname? I'm thinking that doubling up on the normal delimiter may make more sense - which would normally mean ,,, but would mean ;; if you're using a multidimensional argument list and the longname ends where a semicolon would normally go. * Can any required parameter be part of the longname, or are only positional parameters allowed? (I'm expecting the latter; but I'd like confirmation.) * Are placeholder parameters ever considered to be part of a function's longname? (I'm expecting that they aren't: if you want a longname, you ought to specify it in a formal signature.) Starting and Ending delimiters: * Why are pointy blocks forbidden from enclosing their signatures in parentheses, or from using the :( ... ) notation? Is this a holdover from the early days, when parentheses denoted a list? Or is there still a good reason not to allow such notation? * Why do parameterized roles use [ ... ] for their signatures instead of :( ... ) or ( ... )? Named parameters: * Must required named parameters be defined before optional named parameters are, or are we allowed to interleave the two? Placeholder parameters: * does the use of placeholder parameters interfere with the use of the slurpy parameters normally provided by the default signature (i.e., *...@_ and *%_)? I'm guessing not. -- Jonathan Dataweaver Lang
Re: On Junctions
On Sun, Mar 29, 2009 at 10:57 PM, Mark Lentczner ma...@glyphic.com wrote: What I see here is that there is a tendency to want to think about, and operate on, the eigenstates as a Set, but this seems to destroy the single value impersonation of the Junction. In my case, this tendency comes more from a desire to be able to reverse the creation of a junction: you create a (singular) junction from a (plural) list ('1|3|5' === 'any 1, 3, 5'); so I naturally want to be able to (more or less) reverse this process and create a (plural) Set from a (singular) junction. Further, if one ever calls .!eigenstates() on a Junction, then you have really bollox'd your code up, as then this code fails if the value you thought was a Junction happens to be, actually, just a single value! (Unless .!eigenstates() is defined on Object, and returns a Set of self...) Which is why I'd _want_ eigenstates to be callable on an Object as described - and, in general, _any other_ function that operates directly on junctions should be able to accept Objects as well, treating the Object as a one-eigenstate junction. Otherwise, the moment you write a function that passes a junction as a parameter, your code will break if you ever try to pass an Object in instead. And the only other ways to avoid that would be: 1. to provide a means of testing whether or not something is a junction, or 2. to forbid anyone from ever using junction in a signature. I think what is needed is a single value threshing function, which can be applied to, well, single values. Such a function would take a value and a predicate, and if the predicate applied to the value is true, returns the value, else it returns... nothing. If such a function were applied to a Junction, then the result would be a Junction of just those those eigenstates that passed this function. The nothings would not end up contributing to the Junction. ...that could work. The only catch is that if you ever want to get a list of the cases that passed so that you can operate on them individually, you'd still need a means of extracting the eigenstates from the junction. Now, I'm not sure I know how to return nothing in Perl6, but I'll guess that undef can serve the purpose, since I can't think of a useful use of undef as part of a Junction. As Daniel indicated, returning an empty list should work. -- Jonathan Dataweaver Lang
Re: Junction Algebra
Here's another useful one: any($x) eqv all($x) eqv one($x) eqv $x but: none($x) !eqv $x That is, applying any, all, or one to a one-item list produces the equivalent to a single item. For an empty list: any() eqv all() eqv (). But what about one() and none()? -- Jonathan Dataweaver Lang
Re: On Sets (Was: Re: On Junctions)
On Sun, Mar 29, 2009 at 1:18 PM, John Macdonald j...@perlwolf.com wrote: On Sat, Mar 28, 2009 at 10:39:01AM -0300, Daniel Ruoso wrote: That happens because $pa and $pb are a singular value, and that's how junctions work... The blackjack program is an example for sets, not junctions. Now, what are junctions good for? They're good for situation where it's collapsed nearby, which means, it is used in boolean context soon enough. Or where you know it's not going to cause the confusion as in the above code snippet. Unfortunately, it is extremely common to follow up a boolean is this true with either if so, how and/or if not, why not. A boolean test is almost always the first step toward dealing with the consequences, and that almost always requires knowing not only what the result of the boolean test were, but which factors caused it to have that result. True point. Along these lines, I'd like to see at least one threshing function that separates a junction's eigenstates that passed a boolean test from those that didn't. I can see several possible semantics for such: 1. It returns a list of the eigenstates that passed the test. 2. It returns a junction composed of only those parts of the junction which passed the test. 3. It returns a two-item list: the wheat and the chaff. The form that the items take would conform to one of the first two options. The G[op] proposal could be thought of as one approach to the first option. Note also that this option can be turned into a generic list all of the eigenstates function by choosing a test that every possible eigenstate is guaranteed to pass; as such, it would be a very small step from this sort of threshing function to a public .eigenstates method - e.g., $j.eigenstates :where { ... } (to add optional threshing capabilities to a list of eigenstates function) or * G~~ $j (to use a thresher to retrieve all of the eigenstates). The infix:where (junction, Code -- junction) proposal that I made earlier is an example of the second option. This option has the advantage that it preserves as much of the junction's internal structure (e.g., composite junctions) as possible, in case said structure may prove useful later on. (I'm a big fan of not throwing anything away until you're sure that you don't need it anymore.) The downside is that if you want a list of the eigenstates that passed the test, this is only an intermediate step to getting it: you still have to figure out how to extract a list of eigenstates from the threshed junction. The third option has the benefit of letting you handle if so if not without having to thresh twice, once for the wheat and again for the chaff. OTOH, it's bound to be more complicated to work with, and is overkill if you only care about one of the outcomes. I have no syntax proposals at this time. Note further that these aren't necessarily mutually exclusive options: TIMTOWTDI. I prefer the ones that use some form of where; but that's just because those approaches feel intuitive to me. The canonical example of quantum computing is using it to factor huge numbers to break an encryption system. There you divide the huge number by the superposition of all of the possible factors, and then take the eigenstate of the factors that divide evenly to eliminate all of the huge pile of potential factors that did not divide evenly. Without being able to take the eigenstate, the boolean answer yes, any(1..n-1) divides n is of very little value. Right. Something like: any(2 ..^ $n).eigenstates :where($n mod $_ == 0) or: ( any(2 ..^ $n) where { $n mod $_ == 0 } ).eigenstates ...might be ways to get a list of the factors of $n. (I'm not sure how this would be done with junctions and the proposed grep metaoperator - although I _can_ see how to do it with _just_ the metaoperator, or with just a grep method. But that's list manipulation, not junctive processing.) Of course, evaluating this code could be a massive headache without a quantum processor. I'm sure that one _could_ come up with a Set-based approach to doing this; it might even be fairly easy to do. But again, TIMTOWTDI. Perl has never been about trying to come up with an ideal approach and then forcing everyone to use it - that would be LISP, among others. Telling people that they must use Sets instead of junctions in cases such as this runs counter to the spirit of Perl. -- Jonathan Dataweaver Lang
Re: [perl #62528] Match.keys method returns nothing.
Moritz Lenz wrote: Since afaict this is not specced, I'll hand that over to p6l. Eric Hodges (via RT) wrote: use v6; rule test {test}; test ~~ /test/; say '$/.keys = ', $/.keys.perl; say '%($/).keys = ', %($/).keys.perl; # outputs # $/.keys = [] # %($/).keys = [test] Same could be said for .values and .kv It would be very DWIM for it to act like a hash in these cases by default. Actually I think it would DWIM more in the general case if Match.keys (and .kv, .pairs, .values etc) would give a list of the array and hash part, so $/.keys would be @($/).keys, %($/).keys. Your suggestion would be just a degenerate case of that. Any thoughts on that? Take it one step more general: IIRC, Match returns a Capture of the matches found. What happens if you apply .keys, .values, etc. directly to a Capture object? I'm thinking that it should return a multidimensional array: e.g., (@$capture; %$capture).«keys. -- Jonathan Dataweaver Lang
Re: On Junctions
Daniel Ruoso wrote: But the semantics of sets are still somewhat blurry... there are some possibilities: 1) Sets are in the same level as junctions, but have no collapsing and allow you to get its values. The problem is if it autothreads on method calls or not... It also makes $a $b confuse... 2) Set ~~ Any, and all the inteligence is made implementing multis, it has the disadvantage that new operators will need to have explicit implementations in order to get Set DWIMmery... I have been unsure about that, but lately I'm mostly thinking option 2 is the sanest, which means we only get as much DWIMmery as explicitly implemented (which may or may not be a good idea). My understanding is that Set operates on the same level as Hash and List - indeed, a Set could be thought of as a Hash that only cares about the keys but not the values, and has a few additional methods (i.e., the set operations). That is, a junction is an item with an indeterminate value; but a Set is a collection of values in the same way that a hash is. And the proper sigil for a Set is %, not $. -- Jonathan Dataweaver Lang
Re: On Sets (Was: Re: On Junctions)
On Sat, Mar 28, 2009 at 6:39 AM, Daniel Ruoso dan...@ruoso.com wrote: Em Sáb, 2009-03-28 às 13:36 +0300, Richard Hainsworth escreveu: Daniel Ruoso wrote: The thing is that junctions are so cool that people like to use it for more things than it's really usefull (overseeing that junctions are too much powerfull for that uses, meaning it will lead to unexpected behaviors at some point). What are the general boundaries for junctions? Junctions are superposition of values with a given collapsing type. The most important aspect of junctions is that they are a singular value, which means that they are transparent to the code using it. You always use it as a singular value, and that's what keep its semantics sane. Closely related to this is that junctions autothread. If you type in foo($a | $b), it will be processed exactly as if you had typed foo($a) | foo($b) - that is, it will call foo twice, once for $a and once for $b, and it won't care which order it uses. And this is true whether or not you know that a junction is involved. Given 'foo($j)', foo will be called once if $j isn't a junction, and will be called multiple times if $j is a junction. If you were dealing with a Set instead, you'd need to make use of 'map' and/or hyperoperators to achieve a similar result. -- Jonathan Dataweaver Lang
Re: On Sets (Was: Re: On Junctions)
Thomas Sandlaß wrote: Set operations are with parens. Which Synopsis is this in? -- Jonathan Dataweaver Lang
Re: On Sets (Was: Re: On Junctions)
Henry Baragar wrote: The blackjack program is an excellent example for junctions (and not so good for sets, IMHO). The problem in the example above is that the calculation of the value of a hand was not completed. The complete calculation is as follows: my $pa = ([+] @a).eigenstates.grep{$_ 21}.max Per the recent change to the synopses, eigenstates is now a private method, rendering the above code invalid. -- Jonathan Dataweaver Lang
Re: deciphering infix:cmp
In the case of strings and numbers, I'd recommend using leg instead of cmp - that is, coerce both items to strings, then compare the strings. But as far as cmp goes, 3 cmp '3' should fail because a number isn't a string. -- Jonathan Dataweaver Lang
Re: On Junctions
On Fri, Mar 27, 2009 at 10:39 AM, Dave Whipp d...@dave.whipp.name wrote: Richard Hainsworth wrote: The following arose out of a discussion on #perl6. Junctions are new and different from anything I have encountered, but I cant get rid of the feeling that there needs to be some more flexibility in their use to make them a common programming tool. I strongly agree with you, but Larry has repeatedly said that he wants to view Junctions as lexical sugar rather than as a powerful programming tool. So I'm thinking that we'll need to experiment with modules before anything gets admitted to the core language. Maybe you could have something like a filter function that takes a junction and a test condition and returns a junction of those eigenstates from the original one that passed the test. You could then handle the Blackjack problem by saying something to the effect of: $p = [+] @p; $d = [+] @d; if $p = 21 { # Could the total be 21 or less? $p where= { $_ = 21 } #[ infix:where filters the junction according to the given criteria. ] if $p $d { say you won! } } else { say you went over. } -- Jonathan Dataweaver Lang
Re: On Junctions
Dave Whipp wrote: [I’d been planning to put this suggestion on hold until the spec is sufficiently complete for me to attempt to implement it as a module. But people are discussing this again, so maybe it's not just me. I apologize if I appear to be beating a dead horse...] Jon Lang wrote: Maybe you could have something like a filter function yes, but that takes a junction and a test condition and returns a junction of those eigenstates from the original one that passed the test. But why is this a useful thing to do? I think that you're proposing, for compound junctions: ok any( 1|2, 12, 5|15, 515 ) where { $_ 10 } === any( 1|2, 12, 5|15 ) ...not really, no. The way I was looking at it, the above expression is ultimately a junction of the values 1, 2, 5, and 15; no matter how compounded the junction is, these would be its eigenstates. Since 15 would fail the test, anything having to do with it would be filtered out. Exactly how that would work with a compound junction, I'm not sure; as I said, I was thinking of the eigenstates as ordinary items, not nested junctions. But yes, I _was_ suggesting something that transforms one junction into another. That said, I'm also leery of compound junctions. Please tell me the difference between: any( 1|2 ) ...and: any( 1, 2 ) If there is no difference, then: any( 1|2, 12, 5|15, 515 ) eqv any( 1, 2, 12, 5, 15, 515 ) For that matter, I'm not seeing a difference between: any( 12 ) # any of all of (1, 2) ...and: any( 1, 2 ) # any of (1, 2) If I'm not mistaken on these matters, that means that: any( 1|2, 12, 5|15, 515 ) eqv any(1, 2, 5, 15) And I expect that similar rules hold for other compound junctions. In short, I won't be surprised if all compound junctions can flatten into equivalent simple junctions. To me, it still feels like you're thinking of a junction as a set of values, and inventing an operator specifically for the purpose of messing with those values. I do not see values of a junction as a meaningful user-level concept. I'm pretty sure that Larry agrees with you here, seeing as how his latest revision concerning junctions makes direct access to a junction's eigenstates very difficult to arrange. I prefer to turn the problem around, and suggest a different operator, motivated by a different issue, and then apply that operator to junctions. Consider this statement: say (0..Inf).grep: { $_ 10 }; I would expect it to take infinite time to complete (or else fail quickly). It would be wrong to expect perl to figure out the correct answer analytically, because that is impossible in the general case of an arbitrary code block. So I instead propose an operator-based grep: say 0..inf G[] 10; [0..9] This “grep metaoperator” can be expected to analytically determine the result (of grepping an infinite list) in finite time. It might also be used to avoid curlies for simple greps: say @lines G~~ /foo/; The operator exists to filter infinite lists in finite time. But it also solves the junction problem: say (-Inf .. Inf) G== 3|4; [3,4] And how would it handle a compound junction (assuming they exist)? That is: say (-Inf .. Inf) G== any(1|2, 12, 5|15, 515); ??? $score = [+] 1|11, 1|11, 1+11, 1+11, 4; I assume you meant: $score = [+] 1|11, 1|11, 4; say max( 1..21 G== $score ) // bust; 18 ...and the answer to that would be 16, right? -- Jonathan Dataweaver Lang
Re: On Junctions
Damian Conway wrote: Jon Lang wrote: For that matter, I'm not seeing a difference between: any( 12 ) # any of all of (1, 2) ...and: any( 1, 2 ) # any of (1, 2) Those two are very different. any(1,2) == 2 is true any(12) == 2 is false Nested heterogeneous junctions are extremely useful. For example, the common factors of two numbers ($x and $y) are the eigenstates of: all( any( factors($x) ), any( factors($y) ) ) I stand corrected. That said: with the eigenstates method now private, it is now quite difficult to get a list of the eigenstates of the above expression. -- Jonathan Dataweaver Lang
Re: Logo considerations
2009/3/24 Larry Wall la...@wall.org: http://www.wall.org/~larry/camelia.pdf Cute. I do like the hyper-operated smiley-face. What I'd really like to see, though, is a logo that speaks to Perl's linguistic roots. That, more than anything else I can think of, is _the_ defining feature of Perl. -- Jonathan Dataweaver Lang
Re: routine arrow syntax and return/of types
Darren Duncan wrote: Jon Lang wrote: Spitballing here: you drew an analogy to the feed operators. I wonder if that analogy could be taken further: use -- and -- outside of signatures as feed operators - but instead of feeding arrays back and forth, have them feed capture objects and engage in some implicit currying. That is: foo -- $capture $capture -- foo would both be equivalent to: foo :assuming(|$capture) ...or something to that effect. So instead of composing a series of functions by nesting them in each others' argument lists, you could do so by chaining them together using -- or --. That could be interesting. But do you have an example use case or example code illustrating its use? Perhaps something like: my $name = jonathan; $name -- capitalize -- say; Or: $y = acos 'degrees' -- sin 'radians' -- $x; -- Jonathan Dataweaver Lang
Re: routine arrow syntax and return/of types
Darren Duncan wrote: Maybe the problem is a technicality with the parser because ... I'm guessing that the problem is that until you see the -- then what you've read so far on its left is ambiguous as to whether it is a result type or a parameter. I can understand that but I don't know if its a big problem. AFAIK the token -- isn't used anywhere yet in Perl 6 and so its presence inside a parameterized list would be unambiguous once you've read up to it. And AFAIK the token -- is used in exactly one place in perl 6: within signature syntax, to mark the transition from the parameter signature to the return type signature. As with Darren, I don't see why this would be a big problem. The biggest stumbling block that I can think of is that a return type cannot have an invocant, whereas the parameter signature might be able to have one. May I inquire as to the nature of the complications that I'm missing, for my own edification? (If you can't afford the time, I'll understand.) Anyway, while I would appreciate if -- worked, if it doesn't then I can live with one of the existing alternatives ('of' being my current preference). This is a nice to have but not something I would push as hard yet as some other issues. Yeah; definitely not an urgent request. I wonder how hard it would be to write a module that hacks the parser to enable this feature... Spitballing here: you drew an analogy to the feed operators. I wonder if that analogy could be taken further: use -- and -- outside of signatures as feed operators - but instead of feeding arrays back and forth, have them feed capture objects and engage in some implicit currying. That is: foo -- $capture $capture -- foo would both be equivalent to: foo :assuming(|$capture) ...or something to that effect. So instead of composing a series of functions by nesting them in each others' argument lists, you could do so by chaining them together using -- or --. But, like Darren's request, this definitely isn't something that I'd insist on for 6.0.0. -- Jonathan Dataweaver Lang
Re: r25891 - in docs/Perl6/Spec: . S32-setting-library
+ method !eigenstates (Junction $j: -- List) Shouldn't that be lowercase-j junction? -- Jonathan Dataweaver Lang
Re: a junction or not
Larry Wall wrote: I think I've mentioned before that .perl autothreads. It's the final (low-level) stringification of a junction that slaps the appropriate quantifier around that, I suspect. Please bear with me; I'm starting to get a little lost: are you telling me that $j.perl does what I'd expect of an indeterminate item, and that the trick is in getting a perlization of the Junction itself? If so, cool. So maybe $j.Str returns the eigenstring, while prefix:~ autothreads. Or maybe there's a method named .eigenstring or some such for use by print and say and anyone else who absolutely must end up with something printable. Or maybe there's a method that returns a frozen reference that masquerades as the Junction, but doesn't trigger autothreading. Or would that be opening up an infinitely regressing can of worms? I don't know; I've got this gut feeling that something's off here, but I can't quite put my finger on what it is. Although, maybe I can. As written (I believe), .perl generates a String representation of whatever code is needed to build the object that called it. However, there may come a point somewhere down the road where you'll want .perl to instead return a parse-tree of that code, with the ability to stringify appropriately. If you've written a separate .eigenstring function to perform the same purpose with Junctions, or you've set it up so that prefix:~ autothreads while Junction.Str returns the eigenstring, that will potentially be two functions that will need to be rewritten. More generally, a programmer who writes a function that operates on an Object (and thus autothreads when given a Junction) will be forced to decide between writing a second Junction-aware version if he wants to treat the Junction as a Junction instead of autothreaded Objects, or not bothering and thus not allowing the function to manipulate a Junction directly. In short, you have to reinvent the wheel every time the to Junction or not to Junction question arises. Providing a means to momentarily disable a Junction's autothreading properties would, in one fell swoop, solve every instance of this problem. At least, I think it would. If it wouldn't, it would at least solve a large swath of them. -- Jonathan Dataweaver Lang
Re: a junction or not
Darren Duncan wrote: Jon Lang wrote: Darren Duncan wrote: I would assume that invoking .perl on a Junction would result in Perl code consisting of the appropriate any/all/etc expression. -- Darren Duncan Tough to parse, though; and feels like a kludge. I expect better of Perl 6. What do you mean by tough to parse and feels like a kludge? If I'm understanding Larry correctly, then given: my $choice = any(1..10); $choice.perl will return the same thing that the following would: any($choice.eigenstates.«perl) That is, it would return a Junction of Str, not a Str. So the question is how to get something that returns an expression to the effect of: 'any(' ~ $choice.eigenstates.«perl.join(',') ~ ')' Or, if I'm reading Larry incorrectly and $choice.perl provides the latter, how do you get the former (without knowing ahead of time that $choice is an any-junction)? -- The other question is: given $choice as defined above, how do I find out which type of junction it is? Do I somehow call something that would produce the latter string, and then extract the first word from it? Or is there a more direct way to find out which kind of Junction you're dealing with? -- Jonathan Dataweaver Lang
Re: a junction or not
Larry Wall wrote: Sigh. The current design of Junctions is quite extensible *because* it is based on a real type. You can easily write operators that work only on Junctions, just as you can easily write operators that are transparent to Junctions or autothread on Junctions by declaring their arguments to take Object or Any, respectively. Right; that was the solution to which I was referring. That being said, the reason Junctions are there in Perl 6 is primarily *linguistic* rather than mathematical; Perl 6 has a Set type because we've had this argument already. Anyone who extends Junctions to try to do some kind of set theory is on the road to Perdition, or at least the road to Brain Pretzels Without End, amen. Agreed. My own concern has nothing to do with set theory; it's in making sure that there's an easy way to distinguish between method calls that are supposed to be fielded by the Junction itself (e.g., give me perl for the Junction) and method calls that are supposed to be fielded by the Junction's eigenstates (e.g., give me a Junction of perls for the eigenstates of this Junction) - bearing in mind that the Junction _does_ try to stay out of the way and pretend to be (a superposition of) its individual eigenstates as much as possible. _That's_ why I suggested pushing its methods into HOW: not to make it not a type, but rather to ensure that its method calls will never clobber (or be clobbered by) the method calls of its eigenstates. This allows the programmer to continue to think of 1 | 2 as an item, although I'm not sure which one most of the time, and only as a Junction when it is convenient to do so (i.e., by making his intent explicit). The business of referring to it as a meta-type was perhaps an unfortunate digression from my main point; but I mentioned it to justify why I would feel comfortable with allowing Junction to put things in HOW: not only the practical reason that you wouldn't need to present _another_ HOW-like collection of methods to keep the Junction's stuff out of the way, but also because Junction _is_ a strange creature in that it's a collection of items that can usually be treated as a single (indeterminate) item - and this would highlight this fact to the programmer, perhaps making the task of understanding the Junction easier by providing an analogy to another language feature that has similar properties (i.e., meta-operators). Admittedly though, this latter reason takes a back seat to the practicalities. Bottom line, the goal is to keep Junction's methods from conflicting with its members' methods. -- Jonathan Dataweaver Lang
Re: Roles driven by events
Ovid wrote: Requiring methods and requiring methods to be called are different things. It might be a nice feature to have roles which tie into events. If a particular condition doesn't hold true by, say, INIT time, the role fails. How would I implement something like that in Perl 6? Or am I just looking at this wrong? AFAICT, event-driven programming hasn't been incorporated into Perl 6 yet. S17 has mention of an event loop, and S12 speculates on a WHEN introspective method that would have something to do with events. -- Jonathan Dataweaver Lang
Signature notes and questions
OK: as I see it, this is how signatures work: There are three broad use-cases for signatures: function parameters (S06), role parameters (S14), and variable declarators (S03). Question: Do binding operators (S03) count as a fourth use? There are two broad styles of signatures: those that want an invocant, and those that don't. The former includes methods, submethods, and roles; the latter includes subroutines, regexes, tokens, rules, macros, and variable declarators. Signatures that want an invocant will implicitly add one if none is explicitly specified; signatures that don't want one will complain if you specify one. Signature literal syntax: usually, this involves enclosing the signature between ':(' and ')'. In variable and function declarators, you may omit the leading colon; in a pointy-block signature, you must omit both the colon and the parentheses. In a role declarator, you must use square braces instead. (Questions: why is the pointy-block exclusion of the enclosing delimiters mandatory? Why do role declarators use different enclosing delimiters?) Variable declarators have no use for longname parameters. Function and role declarators do. (Question: are optional and/or slurpy parameters excluded from the longname?) Can attributive parameters be used in methods, or are they exclusive to submethods? --- Questions and issues pertaining to absent signatures: All functions have a default signature of :(*%_, *...@_). Note that methods and submethods will implicitly prepend :($?CLASS $self:) to this. All roles are parameterized, and have a default signature of :(Any $?CLASS:). Variable declarators have no default signatures. (Question: is it still appropriate to use the '$?' twigil?) Placeholder variables can be used within bare blocks (but not pointy blocks) and methods that lack signatures. Can they be used in any other function declarators? If not, why not? If so, are they considered to be part of the longname of a named function? (Doubtful.) They can't be used in variable declarators for several reasons, not the least of which is that a variable declarator will always have an explicit signature. But can they be used in roles? Can you have a placeholder variable for a type parameter? -- Jonathan Dataweaver Lang
Re: a junction or not
Larry Wall wrote: This is basically a non-problem. Junctions have one public method, .eigenstates, which is vanishingly unlikely to be used by accident by any mere mortal any time in the next 100 years, give or take a year. If someone does happen to be programming quantum mechanics in Perl 6, they're probably smart enough to work around the presence of a reserved--well, it's not even a reserved word-- a reserved method name. Actually, the problem isn't with '.eigenstates'; the problem is with '.perl'. If I'm viewing a Junction of items as a single indeterminate item, I'd expect $J.perl to return a Junction of the items' perl by default. Admittedly though, even that isn't much of an issue, seeing as how you _can_ get that result by saying something to the effect of Junction of $J.eigenstates.«perl - the only tricky part being how to decide which kind of junction to use (e.g., any, all, one, none) when putting the perl-ized eigenstates back together. (And how _would_ you do that?) This would represent another corner-case where the programmer would be tripped up by a simplistic understanding of what a Junction is; but being a corner-case, that's probably acceptable. -- Jonathan Dataweaver Lang
Re: a junction or not
Darren Duncan wrote: Jon Lang wrote: Larry Wall wrote: This is basically a non-problem. Junctions have one public method, .eigenstates, which is vanishingly unlikely to be used by accident by any mere mortal any time in the next 100 years, give or take a year. If someone does happen to be programming quantum mechanics in Perl 6, they're probably smart enough to work around the presence of a reserved--well, it's not even a reserved word-- a reserved method name. Actually, the problem isn't with '.eigenstates'; the problem is with '.perl'. If I'm viewing a Junction of items as a single indeterminate item, I'd expect $J.perl to return a Junction of the items' perl by default. Admittedly though, even that isn't much of an issue, seeing as how you _can_ get that result by saying something to the effect of Junction of $J.eigenstates.«perl - the only tricky part being how to decide which kind of junction to use (e.g., any, all, one, none) when putting the perl-ized eigenstates back together. (And how _would_ you do that?) This would represent another corner-case where the programmer would be tripped up by a simplistic understanding of what a Junction is; but being a corner-case, that's probably acceptable. I would assume that invoking .perl on a Junction would result in Perl code consisting of the appropriate any/all/etc expression. -- Darren Duncan Tough to parse, though; and feels like a kludge. I expect better of Perl 6. -- Jonathan Dataweaver Lang
Re: a junction or not
This isn't the first (or second, or third, or fourth...) time that I've seen complications arise with regard to junctions. Every time, the confusion arises when some variation of the question is it a junction? is raised. Ultimately, this is because Perl is trying it's darnedest to treat Junctions as their members; this is something that it doesn't try anywhere else, leading to a counterintuitive approach. The other big example of this phenomenon that I've seen has to do with passing parameters into a routine: Should the code auto-parallelize, executing the code separately for each value in the junction, or should it execute only once, passing the parallelization buck on to whatever routines it happens to call? That is, should parallelization be eager or lazy? (I'm pretty sure that this was resolved, although I'm not recalling how.) The problem that Richard just identified is that Junctions don't fully manage to hide themselves when it comes to their method calls. Let's say that I'm writing a role that deals with quantum mechanics (say, Quantum), and for whatever reason I decide that I need an eigenstate method. Now we've got a problem: if I ever find myself dealing with a Junction that has at least one Quantum among its eigenstates, what happens when I call the .eigenstates method? I'm betting that I'll get Junction.eigenstates, rather than a Junction of Quantum.eigenstates. In fact, I see no easy way to get the latter. I'm thinking that maybe Junction shouldn't be a type. Instead, it should be a meta-type, in (very rough) analogy to the concept of the meta-operator. In particular, Junction bears a certain resemblance to the hyper-operator. Thus far, it's the only meta-type; and, like meta-operators, additional meta-types should be added sparingly. As I see it, the difference between a type and a meta-type is that all of the meta-type's methods are accessed via HOW. You wouldn't say $x.eigenstates to access a Junction's eigenstates; you'd say $x.^eigenstates for that. (Further speculation: maybe there's a meta-type that defines the default HOW methods.) That still doesn't solve the problem that Richard first raised, though. To do that, I'm thinking that his original suggestion should also be implemented: in the same way that an item can be treated as a one-item list for the purposes of list context (and vice versa), a non-Junction should be able to be treated as a Junction with a single eigenstate (i.e., a Singleton) for the purposes of junctive semantics. That is, $x.^eigenstates === ($x) if $x is not a junction. Not only does this reduce the need to test for junctions, but it also makes that test fairly straightforward: count the eigenstates. If you only have one, it isn't a junction. (Further speculation: perhaps undefined values have _no_ eigenstates...) -- Jonathan Lang
Re: r25807 - docs/Perl6/Spec
On Sat, Mar 14, 2009 at 7:29 AM, Larry Wall la...@wall.org wrote: : So if I were to say: : : rand $n: : : is the compiler smart enough to notice that trailing colon and : recognize this as an indirect method call rather than two adjacent : terms? No, currently under STD you get: Obsolete use of rand(N); in Perl 6 please use N.rand or (1..N).pick instead at (eval) line 1: : Or would I have to say: : : rand($n:) : : to get the indirect method call? That would work, but then why not: rand*$n $n*rand $n.rand (1..$n).pick In fact, given that you usually want to integerize anyway, I could almost argue myself out of supporting the $n.rand form as well... It's largely a matter of principle: if I can say $x.foo, I expect to be able to say foo $x: as well. Every time you introduce an exception to the rule, you're throwing something in that has the potential to cause confusion; so you should do so with some caution. I think that best uses should include something to the effect of avoid using the same identifier for both a term and a routine. IMHO, rand should either be a term or a method; but not both. There are also some linguistic reasons for this best uses proposal: people tend to think of terms as nouns and routines as verbs. And gerunds are more akin to foo than to term:foo. Left-field idea here: there was recently some discussion on this list about the possibility of continuous ranges, which would be in contrast to how 1..$n is a discrete list of options. If you were to do this, then you could use .pick on a continuous range to generate a random number anywhere within its bounds. So: (1 to 5).pick (where infix:to creates a continuous range, inclusive of both boundaries) would in theory be as likely to return 2.5 or pi as 3. IMHO, this does a better job of handling what most people want rand to do when they start thinking in terms of assigning parameters to it. And with that in place, rand could become a term that's short for something like: pick (0 to^ 1): -- Jonathan Dataweaver Lang
Re: r25807 - docs/Perl6/Spec
+To declare an item that is parsed as a simple term, you must use the +form C term:foo , or some other form of constant declaration such +as an enum declaration. Such a term never looks for its arguments, +is never considered a list prefix operator, and may not work with +subsequent parentheses because it will be parsed as a function call +instead of the intended term. (The function in question may or +may not exist.) For example, Crand is a simple term in Perl 6 +and does not allow parens, because there is no Crand() function +(though there's a C$n.rand method). So if I were to say: rand $n: is the compiler smart enough to notice that trailing colon and recognize this as an indirect method call rather than two adjacent terms? Or would I have to say: rand($n:) to get the indirect method call? -- Jonathan Dataweaver Lang
Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)
Daniel Ruoso wrote: Daniel Ruoso escreveu: What really got me confused is that I don't see what problem this change solves, since it doesn't seem that a signature that expects an invocant (i.e.: cares about invocant) will accept a call without an invocant, so method foo($b,$c) is export still need to have a transformed signature in the sub version of foo. Thinking again, Unless that actually means that we're really removing all the runtime semantics around the invocant... and methods implicitly do my $self = shift all the time... That'd be sad... we loose invocant semantics... SMOP will require a HUGE refactoring... :( Remember that Captures are also being used as Perl 6's answer to references. When used in that way, problems arise when you treat a single item as being fundamentally different from a one-item list. -- Jonathan Dataweaver Lang
Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)
Darren Duncan wrote: Here's a question: Say I had an N-adic routine where in OO terms the invocant is one of the N terms, and which of those is the invocant doesn't matter, and what we really want to have is the invocant automatically being a member of the input list. How about allowing submethods to be declared outside of classes and roles as well as inside them? When declared inside a class or role, it is declared in has scope, and works as described; when declared elsewhere, it is declared in my scope, and works just like a sub, except that you're forced to specify an invocant in the signature(s). You could then use the same sort of tricks that subs can use to specify alternate signatures, including the one that lets the positional arguments be filled out in any order. -- Jonathan Dataweaver Lang
Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)
OK; let me get a quick clarification here. How does: say Hello, World!; differ from: Hello, World!.say; or: say $*OUT: Hello, World!; in terms of dispatching? And more generally, would there be a reasonable way to write a single routine (i.e., implementation) that could be invoked by a programmer's choice of these calling conventions, without redirects (i.e., code blocks devoted to the sole task of calling another code block)? Could you use binding? my sub say (String *$first, String *...@rest, OStream :$out = $*OUT, OStream :$err = $*ERR) { ... } role String { has say:(String $first: String *...@rest, OStream :$out = $*OUT, OStream :$err = $*ERR) := OUTER::say; } That (or something like it) might be doable. But in the spirit of TIMTOWTDI, I'd like to explore another possibility: what difficulties would arise from allowing subs to have signatures with invocants, which in turn allow the sub to be called using method-call syntax (though possibly not method dispatch semantics)? In effect, allow some syntactic sugar that allows properly-sigged subs outside of a role to masquerade as methods of that role. -- Jonathan Dataweaver Lang
Re: Range and continuous intervals
Thomas Sandlaß wrote: The benefit of a dedicated Interval type comes from supporting set operations (), (|) etc. which are still unmentioned in S03. Have set operations been implemented in either Rakudo or Pugs? BTW, what does (1..^5).max return? I think it should be 4 because this is the last value in the Range. Only in 4.7 ~~ 1..^5 does the five matter. How does ~~ retrieve that information? For open intervals the .min and .max methods should return the bound outside. Or better, we should introduce infimum and supremum as .inf and .sup respectively. No offense, but I've noticed a tendency on your part to suggest highly technical names for things. Infimum and supremum may be technically accurate; but I wouldn't know, since I don't know for certain what they mean. Min and max may be misleading in terms of the specifics; but they get the general point across. I'm thinking of a Range-alike that one could use with Rat|Num or Instant etc, and not just Int etc. There would be operators to test membership of a value in the interval, and set-like operators to compare or combine intervals, such as is_inside, is_subset, is_overlap, union, intersection, etc. Such an interval would be what you use for inexact matching and would be the result of a ± infix operator or % postfix operator. Also, as Range has a .. constructor, this other type should have something. Since the Interval type shall be an addition to the Set subsystem I propose the (..) Interval creation operator together with the open versions. Admittedly that leaves (^..^) at a lengthy six chars. But Jon's proposal of setting the by to zero isn't any shorter. Note that the open versions are more important for Interval than they are for Range because for Range you can always write it without ^ at the ends. In defense of my proposal, note that it _can be_ shorter if you say that :by defaults to zero when the endpoints are of continuous types such as Num, Instance, or Rat. That said, I admit that my proposal is something of a kludge - albeit te type of kludge that Perl tends to embrace (where reasonable, make a best guess as to the programmer's intentions; but provide a means gor him to be more explicit if your guess is wrong). -- Jonathan Dataweaver Lang
Re: Range and continuous intervals
Darren Duncan wrote: In reply to Jon Lang, What I'm proposing here in the general case, is a generic collection type, Interval say, that can represent a discontinuous interval of an ordered type. A simple way of defining such a type is that it is a Set of Pair of Ordered, where each Pair defines a continuous interval in terms of 2 ordered end-points, and the whole set is discontinuous (or replace Pair with 2-element Seq). Note that you lose the distinction between inclusive and exclusive endpoints if you do this. That is one benefit that Range has over Pair: Range _does_ keep track of whether its endpoints are inclusive or exclusive. The main problem with Range is that it is (usually?) enumerable - which is generally considered to be a feature, but which gets in the way in the case of using it to represent a continuous interval. Thus my suggestion of somehow doing away with the enumerability if the step size is zero. As such, I'd be inclined to define Interval as a Range-like role that isn't enumerable, representing a continuous span between its lower and upper boundaries. A disjoint interval would be a role that usually delegates to an internal Set of Interval of Type, except when it needs to do otherwise in order to resemble a Set of Type. -- Jonathan Dataweaver Lang