How would I do this in Perl6? #1
Dear all, I've recently thought of a possible syntax extension for (Perl5's) [un]pack() and I posted my RFC to clpmisc where it didn't have much success, I must say. However I'm not interested in proposing it here, only I would like to investigate a possible Perl6 technique inspired by those thoughts... Well, to come to the point, it does happen, even if admittedly not too often and with not too long sequences, to use cascaded [un]pack()s. Now I'm not specifically interested in *these* functions anymore, but more generally in a generic function that accepts a first argument as a template according to which it interpretates the other ones. For clarity I will still use, say, pack(). Now I want to take a list of templates, say $t1, ... $tn and get the result of $result = pack $tn, ... pack $t2, pack $t1, @input; without actually writing the whole thing. To my knowledge and great pleasure Perl6 will support currying and a builtin reduce/fold operator. So what I would like to do is (i) Cmap the list of templates to a list of curried closures in which the first parameter is fixed to each given template, (ii) Creduce this list by means of right pipe binop ( C == ) with a starting value (leftmost) of, say, @input. What I'm asking is (i) wether this would actually be possible, and if so, then (ii) what it would probably look like in actual Perl6 code. BTW: I guess something like my $result = @input == reduce operator:==, map {...}, @templates; where {...} would represent the curried closures, if only I knew how they are supposed to look like! TIA, Michele -- {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}-(map substr (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^RY]*YB=' .'KYU;*EVH[.FHF2W+#\Z*5TI/ERZ`S(G.DZZ9OX0Z')=~/./g)x2,$_, 256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:\r;print,redo}#JAPH,
But is it intuitive?
I was thinking about removing files this morning, and realized that I wish rm supported inclusion/exclusion. In particular, I wanted to remove * but not Makefile (since my Makefile uses lwp-download to re-fetch the source code, etc.) It occurred to me to wonder: can P6's cbut do the same thing? That is, can I say: $my_rex = qr/fo*/ but not 'foo'; while () { unlink if /$my_rex/; } and have it DWIM? What about globbing? In general, what needs to be done to support this 'but, used as part of a boolean'? In this case, but really means 'and': $my_rex = { my $re = qr/fo*/; $re.eval := sub { $_ ne 'foo' call; }; return $re; }; This has interesting implications for specification of generators, too. Comment? =Austin
Re: But is it intuitive?
On Tue, 14 Sep 2004, Austin Hastings wrote: I was thinking about removing files this morning, and realized that I wish rm supported inclusion/exclusion. In particular, I wanted to remove * but not Makefile (since my Makefile uses lwp-download to re-fetch the source code, etc.) It occurred to me to wonder: can P6's cbut do the same thing? That is, can I say: $my_rex = qr/fo*/ but not 'foo'; while () { unlink if /$my_rex/; } The word junction came to my mind as I read your mail. $my_rex = qr/fo*/ qr:not/foo/; (I don't think that :not is the option to negate, but there must be some syntax that works) I am not saying this is a better way to do it, but just another way that seems to do the same thing in the same way. In general, what needs to be done to support this 'but, used as part of a boolean'? --abhijit
Re: But is it intuitive?
On 2004-09-14 at 08:40:55, Austin Hastings wrote: In particular, I wanted to remove * but not Makefile (since my Makefile uses lwp-download to re-fetch the source code, etc.) Well, you can, depending on your shell: in ksh: rm !(Makefile) in bash: ditto, but you have to turn on the extglob option first with shopt -s extglob in csh: think you're out of luck here. Note that ksh/bash support multiple exclusions via alternation: rm !(Makefile|configure|config.in) -Mark
Re: But is it intuitive?
Abhijit Mahabal writes: On Tue, 14 Sep 2004, Austin Hastings wrote: I was thinking about removing files this morning, and realized that I wish rm supported inclusion/exclusion. In particular, I wanted to remove * but not Makefile (since my Makefile uses lwp-download to re-fetch the source code, etc.) It occurred to me to wonder: can P6's cbut do the same thing? That is, can I say: $my_rex = qr/fo*/ but not 'foo'; while () { unlink if /$my_rex/; } The word junction came to my mind as I read your mail. $my_rex = qr/fo*/ qr:not/foo/; Judging from this, maybe we ought to have :not. Anyway, it's still possible: $my_rex = rx/fo*/ none(rx/^foo$/); Luke
Re: But is it intuitive?
Luke Palmer wrote: Judging from this, maybe we ought to have :not. Anyway, it's still possible: $my_rex = rx/fo*/ none(rx/^foo$/); For sure. On a side note, there should be a negating match operator for use inside: rx/\d+/ none(rx/1984/) could get awfully long if you had to handle several exceptions. I like rx:not, though -- a little easier to read IMO. =Austin
Re: But is it intuitive?
On Tue, 2004-09-14 at 10:11, Abhijit Mahabal wrote: On Tue, 14 Sep 2004, Austin Hastings wrote: That is, can I say: $my_rex = qr/fo*/ but not 'foo'; The word junction came to my mind as I read your mail. $my_rex = qr/fo*/ qr:not/foo/; Of course, the regex itself can do this: qr{(fo*) ({$1 ne 'foo'})} This is probably the superior option, as it can backtrack, where the others cannot. Thus for the string foo you would match fo because you find foo first, and it fails, causing the first subexpression to backtrack, but you can still match fooo correctly on the first try. -- 781-324-3772 [EMAIL PROTECTED] http://www.ajs.com/~ajs
Re: How would I do this in Perl6? #1
On Tue, 2004-09-14 at 06:45, Michele Dondi wrote: [... snip ...] Now I want to take a list of templates, say $t1, ... $tn and get the result of $result = pack $tn, ... pack $t2, pack $t1, @input; Assuming Perl 6 has a pack, which it may not: for @t { $result = pack $_, ($result // @input); } no? -- 781-324-3772 [EMAIL PROTECTED] http://www.ajs.com/~ajs
Re: But is it intuitive?
Aaron Sherman skribis 2004-09-14 14:02 (-0400): qr{(fo*) ({$1 ne 'foo'})} What is the second set of parens for? Will the following suffice? rx/ (fo*) { $1 ne 'foo' } / And it is because of the lack of anchors that this won't work as expected? rx/ !before foo fo* / Juerd
Re: But is it intuitive?
On Tue, Sep 14, 2004 at 02:02:22PM -0400, Aaron Sherman wrote: : Of course, the regex itself can do this: : : qr{(fo*) ({$1 ne 'foo'})} Er, at the moment bare closures don't care about their return value, so as it currently stands, you'd want something more like: rx/(fo*) {fail if $1 eq 'foo'}/ or rx/(fo*) ($1 ne 'foo')/ But yes, backtracking is a decent way to handle it. Larry
Re: But is it intuitive?
On Tue, Sep 14, 2004 at 08:30:45PM +0200, Juerd wrote: : Aaron Sherman skribis 2004-09-14 14:02 (-0400): : qr{(fo*) ({$1 ne 'foo'})} : : What is the second set of parens for? Will the following suffice? : : rx/ (fo*) { $1 ne 'foo' } / Bare closures are used only for their side effects in the current design. It's vaguely possible that we could recognize a top level boolean operator and do something different, but there are problems with that approach. : And it is because of the lack of anchors that this won't work as : expected? : : rx/ !before foo fo* / No, the f pretty well anchors the front of it in any case. It's the other end that is the problem. Your solution disallows fooo. You'd have to say something like: rx/ !before foo !before o fo* / Larry
Re: But is it intuitive?
On Tue, 2004-09-14 at 14:40, Larry Wall wrote: On Tue, Sep 14, 2004 at 02:02:22PM -0400, Aaron Sherman wrote: : Of course, the regex itself can do this: : : qr{(fo*) ({$1 ne 'foo'})} Er, at the moment bare closures don't care about their return value, so as it currently stands, you'd want something more like: rx/(fo*) {fail if $1 eq 'foo'}/ Dang, where's that Perl 6 compiler when I need it to clear up this sort of thing? ;-) Thanks for the correction. I notice I fell for the qx vs rx thing too. Heh, old habits die hard. -- 781-324-3772 [EMAIL PROTECTED] http://www.ajs.com/~ajs
Re: How would I do this in Perl6? #1
On Tue, 14 Sep 2004, Aaron Sherman wrote: Assuming Perl 6 has a pack, which it may not: I know: this is one of the reasons why I wrote (hopefully *clearly* enough) that I was just using it as an example. A user defined pack() whoud do just the same here, anyway. for @t { $result = pack $_, ($result // @input); } It's hard to believe, but surprising as it may be, I could have thought of a (ton, possibly, of) solution(s) along those lines (the C// op is cool though). The point here is that I find it conceptually appealing, elegant and smart to be able to use functions as primitive data types as in functional languages. I'm not saying that I want to enforce only such constructs, but I'd like to be allowed to use them. So the question is: even being aware of more traditional solutions of the kind of that cited above, will it be possible to adopt one similar to that hinted to in my previous post? And if so, then how would it probably look like? no? Yes... ...So what?!? Michele -- It's not considered polite in my circles to tell others that they are being impolite, unless the others are your children. Looks like I'm not very polite, doesn't it? - Mike Prager on comp.text.tex, thread usenet news group style
Re: How would I do this in Perl6? #1
On Tue, 14 Sep 2004 12:45:17 +0200 (CEST), Michele Dondi [EMAIL PROTECTED] wrote: Now I want to take a list of templates, say $t1, ... $tn and get the result of $result = pack $tn, ... pack $t2, pack $t1, @input; without actually writing the whole thing. To my knowledge and great pleasure Perl6 will support currying and a builtin reduce/fold operator. You could do this with a recursive function (They're your friends. Really.). sub extended_pack( [EMAIL PROTECTED] = ($t1, ... , $tn), [EMAIL PROTECTED] ) { # start with the last template so we can use tail recursion @input = pack pop(@templates), @input; # if there aren't any more templates, we're done return @input if not @templates; return extended_pack(@templates, [EMAIL PROTECTED]); } Or in Perl 5, which has to use 2 subs to have the same interface (code untested): sub extended_pack { my (@input) = @_; my @templates = ($t1, ..., $tn); return extended_pack_rec([EMAIL PROTECTED], [EMAIL PROTECTED]); } sub extended_pack_rec { my ($input, $templates) = @_; @$input = pack pop(@$templates), @$input; return @$input if not @$templates; # special goto magic for tail recursion @_ = ($input, $templates); goto extended_pack_rec; } I prefer Perl 6. -- matt