Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Pugs Baby Steps

by eyepopslikeamosquito (Archbishop)
on Mar 18, 2005 at 12:26 UTC ( [id://440685]=perlmeditation: print w/replies, xml ) Need Help??

I took my first baby steps with Pugs and Perl 6 during the past week and thought I'd share the experience.

Though I doubt it really counts as Exploratory Testing I decided to help test Pugs simply by converting an existing p5 program to p6.

The tsanta.pl test program (from my first Pugs node Replaying Santa Claus Golf Apocalypse with Pugs/Perl6) has now been rewritten as tsanta.p6 so that it runs successfully using Pugs, as shown below. You will need a more recent Pugs than 6.0.11 to run it -- suggest you simply install Subversion on your machine and enter:

svn checkout http://svn.openfoundry.org/pugs/
to get the latest Pugs release, then build it in the normal way. For full details on getting and building Pugs go to pugscode.org.

My other reason for attempting this is I feel we need more examples of real working Perl 6 code, both to help newbies learn the language and to provide valuable feedback to the Perl 6 design team. This is where I need some help from you. Though I can provide feedback on how easy Perl 6 is to learn and use for a newbie moving from Perl 5, a newbie cannot provide examples of good Perl 6 style. So, please feel free to suggest improvements to the code below (even if said improvements are not yet implemented in Pugs). It's nice to know the "right" way to do it.

The code below is constrained by the following assumptions about the current state of Pugs. If I am in error in any of these, please let us know.

  • In loops, next, last, redo are not yet implemented.
  • The length or similar function is not implemented. BTW, in p6 length is verboten, replaced by the more specific: bytes, codes, graphs, chars and elems.
  • Built-in vars like $., $! and $? are not yet implemented.
  • The chomp function is not yet implemented.
  • Here-docs are not yet implemented.
  • Backticks are not yet implemented.
  • Test for file existence with -f is not yet implemented.

So without further ado, here it is:

# tsanta.p6. Pugs version of tsanta.pl. use v6; sub length (Str $s) returns Int { +split("", $s) } sub golf_score (Str $script) returns Int { my $fh = open($script) or die("open '$script' failed"); my $golf = 0; my $dollar_dot = 0; # $. not implemented yet for =$fh -> $line { ++$dollar_dot; $golf += length($line) - 1 unless $dollar_dot==1 && $line.index("#!") == 0; } $fh.close(); return $golf; } sub print_golf_score (*@scr) { my $tot = 0; for @scr -> $s { $tot += golf_score($s) } print "You shot a round of $tot strokes.\n"; } sub build_file (Str $fname, Str $data) { my $fh = open('>'~$fname) or die("open '$fname' failed"); print($fh, $data) or die("print '$fname' failed"); $fh.close(); } sub slurp_file (Str $fname) returns Str { my $fh = open($fname) or die("open '$fname' failed"); my $s; for =$fh -> $line { $s ~= $line } $fh.close(); return $s; } sub check_one (Str $scr, Str $label, Str $data, Str $exp) { my $intmp = 'in.tmp'; my $outtmp = 'out.tmp'; build_file($intmp, $data); my $cmd = "pugs $scr $intmp >$outtmp"; print("$label : running: '$cmd'..."); # my $out = `$cmd`; # not implemented yet system($cmd); my $rc = 0; my $out = slurp_file($outtmp); print "done (rc=$rc).\n"; if ($out ne $exp) { $*ERR.print("Expected:\n$exp"); $*ERR.print("Got:\n$out"); die("Oops, you failed.\n"); } } # ----------------------------------------------------- my $file1 = "1st line "; my $file2 = "1st line 2nd line "; my $file3 = "1st line 2nd line 3rd line "; my $file4 = "1st line 2nd line 3rd line 4th line "; my $file12 = "1st line 2nd line 3rd line 4th line 5th line 6th line 7th line 8th line 9th line 10th line 11th line 12th line "; my $file21 = "1st line 2nd line 3rd line 4th line 5th line 6th line 7th line 8th line 9th line 10th line 11th line 12th line "; # ----------------------------------------------------- sub check_head (Str $scr) { my @tt = ( [ 'file1', $file1, "1st line\n" ], [ 'file2', $file2, "1st line\n2nd line\n" ], [ 'file3', $file3, "1st line\n2nd line\n3rd line\n" ], [ 'file12', $file12, "1st line\n2nd line\n3rd line\n4th line\n5th line\n"~ "6th line\n7th line\n8th line\n9th line\n10th line\n" ] ); for @tt -> $f0, $f1, $f2 { check_one($scr, $f0, $f1, $f2) } } sub check_tail (Str $scr) { my @tt = ( [ 'file1', $file1, "1st line\n" ], [ 'file2', $file2, "1st line\n2nd line\n" ], [ 'file3', $file3, "1st line\n2nd line\n3rd line\n" ], [ 'file12', $file12, "3rd line\n4th line\n5th line\n6th line\n7th line\n"~ "8th line\n9th line\n10th line\n11th line\n12th line\n" ], [ 'file21', $file21, "12th line\n\n\n\n\n\n\n\n\n\n" ] ); for @tt -> $f0, $f1, $f2 { check_one($scr, $f0, $f1, $f2) } } sub check_rev (Str $scr) { my @tt = ( [ 'file1', $file1, "1st line\n" ], [ 'file2', $file2, "2nd line\n1st line\n" ], [ 'file3', $file3, "3rd line\n2nd line\n1st line\n" ], [ 'file21', $file21, "\n\n\n\n\n\n\n\n\n12th line\n11th line\n10th line\n"~ "9th line\n8th line\n7th line\n6th line\n5th line\n"~ "4th line\n3rd line\n2nd line\n1st line\n" ] ); for @tt -> $f0, $f1, $f2 { check_one($scr, $f0, $f1, $f2) } } sub check_mid (Str $scr) { my @tt = ( [ 'file1', $file1, "1st line\n" ], [ 'file2', $file2, "1st line\n2nd line\n" ], [ 'file3', $file3, "2nd line\n" ], [ 'file4', $file4, "2nd line\n3rd line\n" ], [ 'file12', $file12, "6th line\n7th line\n" ], [ 'file21', $file21, "11th line\n" ] ); for @tt -> $f0, $f1, $f2 { check_one($scr, $f0, $f1, $f2) } } sub check_wc (Str $scr) { my @tt = ( [ 'file1', $file1, "0000000001\n" ], [ 'file2', $file2, "0000000002\n" ], [ 'file3', $file3, "0000000003\n" ], [ 'file4', $file4, "0000000004\n" ], [ 'file12', $file12, "0000000012\n" ], [ 'file21', $file21, "0000000021\n" ] ); for @tt -> $f0, $f1, $f2 { check_one($scr, $f0, $f1, $f2) } } # ----------------------------------------------------- my $head = 'head.p6'; my $tail = 'tail.p6'; my $rev = 'rev.p6'; my $mid = 'mid.p6'; my $wc = 'wc.p6'; # -f $head or die("error: file '$head' not found"); # -f $tail or die("error: file '$tail' not found"); # -f $rev or die("error: file '$rev' not found"); # -f $mid or die("error: file '$mid' not found"); # -f $wc or die("error: file '$wc' not found"); print_golf_score($head, $tail, $rev, $mid, $wc); check_head($head); check_tail($tail); check_rev($rev); check_mid($mid); check_wc($wc); print_golf_score($head, $tail, $rev, $mid, $wc); say("Hooray, you passed.");

Discussion

The code is remarkably similar to the Perl 5 version, indicating that many p5 scripts could be routinely converted to p6. I didn't try for any massive p6 improvements in converting this program -- mainly out of p6 ignorance.

I found writing this program a little frustrating mainly because of the lack of Perl 6 examples. The Synopses are important, but for learning a new language, my brain really needs lots of examples. Needless to say, if anyone knows of a good set of Perl 6 examples, please let me know.

I really like the new subs. Larry (or was it Damian) really hit the nail on the head when they said that p5 subs were, ironically, too orthogonal -- being implemented just with a special list @_ and without requiring any specialized language support at all! My first impression is that the new design of subs is a brilliant work of art and I salute the design team.

The new list stuff and functional programming support looks to be a huge improvement over p5 and I look forward to using it more in the future.

This little exercise uncovered one design bug and a couple of Pugs bugs also, so I feel it was worthwhile. If nothing else, it proves that real live working Perl 6 scripts can be written today. As a word of caution however, note that there are many p6 language features missing from Pugs today and working around them can be frustrating. On the other hand, the speed of the Pugs developers in implementing them is astonishing.

I knew there must be a better way than the slurp_file function above. As an example of the phenomenal enthusiasm and support by the Pugs developers, within an hour or so of posting a question about file slurping, autrijus has just now implemented the slurp primitive! Update: The latest version of tsanta.p6 (including replacing slurp_file above with the new slurp primitive) along with rg0now's excellent Santa golf solutions can be found under examples/golf in the Pugs distribution.

Finally, I would like to thank all the Perl 6 folks for being so helpful to a Perl 6 newbie and for not flaming me for my many silly questions. :-)

Replies are listed 'Best First'.
Re: Pugs Baby Steps
by TimToady (Parson) on Mar 18, 2005 at 16:52 UTC
    Also, $. is probably spelled $fh.linenum or some such, though we'll probably have to provide some emulation for the exact meaning of $. just for the p5-to-p6 translator (which I'm working on in my spare time, and which should provide you a whole raft of examples when it's done).

    And the $? variable is probably subsumed into $! now, since it's really just another kind of unthrown exception.

    And don't anyone be embarrassed for asking "silly" questions. It's the only way we can get readings on how people actually approach Perl 6. When it comes down to it, all this fancy design stuff is really Just Guessing. (But thanks for affirming some of our guesses on sub declarations!)

Re: Pugs Baby Steps
by audreyt (Hermit) on Mar 18, 2005 at 13:08 UTC
    You rock, Mad Golfer! :-)

    Some short corrections on your assumptions:

    • last was already there; it had to be written as last(), which is a bug. I am fixing that and implemeting next()/redo() now.
    • The $! builtin is available.
    • chomp works.

    Again, wonderful work! I'll, as usual, implement features you (or anyone else, for that matter) need for future conversion of real-world scripts at highest priority.

Re: Pugs Baby Steps
by Arunbear (Prior) on Mar 18, 2005 at 12:56 UTC
Re: Pugs Baby Steps
by rg0now (Chaplain) on Mar 18, 2005 at 22:01 UTC
    Regarding the Santa Claus Golf Apocalypse with Pugs/Perl6, I must note here that the final result of my golfing efforts can be found here: This one goes for the archives. It took me 153 strokes, so it should be a good starting point for you real Perl Golfers out there... (note that as of Pugs r883, it will not work as expected, so you have to downgrade to r882)...

    Update: but it sure works with r888, so you do not have excuses...

    In other news, something makes me think that the great breakthrough of Perl 6 will happen on the day when the first Emacs mode will be realeased for it... something like cperl6-mode...:-) I tend to edit Perl 6 code with cperl-mode that is specific to Perl 5, and sometimes it produces pretty interesting syntax highlighting and indentation effects.

    Update: if you came here from SuperSearching emacs AND perl6-mode, I have some mildly good news for you: even though Emacs does not seem to have a perl6-mode for now, apparently vim has one.

    Update: I could not resist: here you find a shiny new cperl6-mode for emacs. Enjoy!

    rg0now

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://440685]
Approved by Corion
Front-paged by Limbic~Region
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2024-03-19 06:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found