Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: Prolegemona To A Future Scripting Language: Game Of Life In Perl 6

by TheDamian (Priest)
on Apr 27, 2003 at 01:31 UTC ( #253438=note: print w/ replies, xml ) Need Help??


in reply to Prolegemona To A Future Scripting Language: Game Of Life In Perl 6

That's a great effort, especially without a compiler. Here are a few corrections and some more "idiomatic" solutions.

Comments in bold italics explain corrections on the previous line.
Comments in normal italics explain stylistic choices on the previous line.


my $life = new life: 20;
# Indirect object syntax requires colon after invocant
loop { $life.display() }
# Argumentless &loop is cleaner that &while for infinite loops
class life { has Int $.count; has Int $.max; has Array of Bit @.grid;
# Bit is potentially much smaller than Int for 1/0 values
method BUILD(Int $dim)
# BUILD is the object initializer.
# CREATE is something else entirely (see Apocalypse 12 ;-)
{ $.count = 0; $.max = $dimension-1; my Array of Bit @grid is dim($dim,$dim) is default(0);
# Setting default value to 0 reduces initialization costs
@grid[$dim / 2 - 1][$dim / 2 ] = 1; @grid[$dim / 2 - 1][$dim / 2 + 1] = 1; @grid[$dim / 2 ][$dim / 2 ] = 1; @grid[$dim / 2 ][$dim / 2 - 1] = 1; @grid[$dim / 2 + 1][$dim / 2 ] = 1; @.grid := @grid;
# Can't declare variably dimensioned array as attribute.
# Have to declare it when dimension known (i.e. in
# constructor) and then bind it to attribute
} sub iterate (&block)
# Utility sub to factor out repetitive 2D iterations
{ for 0..$.max -> $x
# Prefer &for over &loop when possible (e.g. here)
{ for 0..$.max -> $y { block($x,$y); } } } method calculate() is private { my @newgrid; iterate { my $live = sum(@.grid[$^x-1..$^x+1][$^y-1..$^y+1]); @newgrid[$^x][$^y] = $live==2 && @.grid[$^x][$^y] || $live==3; }
# Pass &iterate a block with placeholders for $x and $y
@.grid = @newgrid; } method display { iterate { print $.grid[$^x][$^y] ?? '+' :: '.'; print "\n" if $^x == $.max; } print "\n"; print "Turn $(++$.count), press enter to continue or ctl-c to quit +; <$*IN>;
# STDIN is now $*IN
.calculate(); } }
Update: Fixed display method (thanks jkahn)


Comment on Re: Prolegemona To A Future Scripting Language: Game Of Life In Perl 6
Select or Download Code
Re: Re: Prolegemona To A Future Scripting Language: Game Of Life In Perl 6
by TheDamian (Priest) on Apr 27, 2003 at 02:16 UTC
    I should point out that the line:
    my $live = sum(@.grid[$^x-1..$^x+1][$^y-1..$^y+1]);
    is somewhat speculative. It's not clear to me how multidimensional slices will interact with flattening contexts (such as the argument list of the standard &sum function).

    It might be that that line needs to be:

    my $live = sum(map {sum .[$^y-1..$^y+1]} @.grid[$^x-1..$^x+1]);
    Though, given how ugly that is, I'd naturally prefer sum to be smart enough to flatten multidimensional slices.
Re: Re: Prolegemona To A Future Scripting Language: Game Of Life In Perl 6
by jkahn (Friar) on Apr 27, 2003 at 06:33 UTC
    Seems like the method display as written would actually print all the cells in one row -- method iterate doesn't have an explicit hook for "reached end of line". That's fine, since we have $.max available within the object.

    I think method display should actually look like this:

    method display { iterate { print $.grid[$^x][$^y] ?? '+' :: '.'; print "\n" if ($^x == $.max); # print each row on own line } print "\n"; # blank line follows grid print "Turn $(++$.count), press enter to continue" print " or ctl-c to quit"; <$*IN>; .calculate(); } # end method display

    A separate style comment: wouldn't it be a bit cleaner to remove the .calculate(); line from method display and change the loop at the top so that it reads:

    loop { $life.display(); $life.calculate(); }
    Then there's no nasty surprise when someone does:
    # somewhere far, far, away $life.display; `shell-script;clear`; # weird stuff on screen tty $life.display; # refresh terminal *only*
    later. I recognize that's personal preference, but Side Effects Are Scary.
      Quite so. Fixed in the original node. Thanks!

      (Hopefully someone will tie this back to the thread on "Damian Isn't Infallible" :-)

      As for changing the control flow in .display, yes, I was tempted to do so too.

      But that went beyond "idiomaticization" and became an issue of software engineering. In the end I deliberately didn't hoist the call to .calculate because I felt it was more important to preserve as much comparability with the original as was consistent with an idiomatic Perl 6 implementation.

Re: Re: Prolegemona To A Future Scripting Language: Game Of Life In Perl 6
by jryan (Vicar) on Apr 27, 2003 at 09:36 UTC
    # Setting default value to 0 reduces initialization costs

    How does setting a default value reduce initialization costs? Zero is the default initialization value for PMCs anyways, so wouldn't setting it explicitly just create extra work?

      I meant: reduces initialization costs in comparison to the previous version, which was iteratively setting every element to zero in a pair of nested for loops.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://253438]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (7)
As of 2015-07-07 03:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (86 votes), past polls