tag:blogger.com,1999:blog-92212289629368057042024-03-13T00:56:59.208+00:00Jonathan's Adventures in ProgrammingRamblings on the art and craft, trials and tribulations of software programming.Jomathan Stowehttp://www.blogger.com/profile/10543685469826752411noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-9221228962936805704.post-66775553343191268262022-06-18T17:01:00.000+01:002022-06-18T17:01:49.638+01:00Make the Raku programming language familiar to C++ programmers<p>
So a couple of days ago I was taken with the fact that you could make the Raku
programming language appear to do I/O somewhat like C++:
</p>
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p dir="ltr" lang="en">Or you can even go full C++ if that takes you:<br /><br />use isms; sub infix:«<<»( IO::Handle <a href="https://twitter.com/search?q=%24h&src=ctag&ref_src=twsrc%5Etfw">$h</a>, Cool <a href="https://twitter.com/search?q=%24v&src=ctag&ref_src=twsrc%5Etfw">$v</a> ) { <a href="https://twitter.com/search?q=%24h&src=ctag&ref_src=twsrc%5Etfw">$h</a>.print: <a href="https://twitter.com/search?q=%24v&src=ctag&ref_src=twsrc%5Etfw">$v</a>; <a href="https://twitter.com/search?q=%24h&src=ctag&ref_src=twsrc%5Etfw">$h</a> }; sub term:<cout> { $*OUT }; sub term:<endl> { "\n" }; cout << "Whatever" << endl;<a href="https://twitter.com/hashtag/rakulang?src=hash&ref_src=twsrc%5Etfw">#rakulang</a></p>— Jonathan Stowe (@gellyfish) <a href="https://twitter.com/gellyfish/status/1537882968085057537?ref_src=twsrc%5Etfw">June 17, 2022</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<p>Now it occurs to me that this may be somewhat opaque to someone not familiar with Raku, so, rather than explain it in a bunch of tweets, I'll give a quick breakdown here</p>
<p>First up the weird looking "<span style="font-family: courier;">use isms;</span>": Raku has some heritage from languages that have some different operators for common operations such as "left shift", and to help avoid common mistakes due to these differences, <span style="font-family: courier;">rakudo </span><span style="font-family: inherit;">goes out of its way to provide a helpful error message when the programmer uses one of the common operators that have different meanings or none at all in Raku, So for example if one was to use the "left shift" (or C++ stream extraction in this case,) operator one would get something like:<br /><br /></span></p><p>
</p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><pre style="text-align: left;"><span style="font-family: courier;">[jonathan@menenius hesabu]$ raku -e 'my $a = 1; say $a << 2'</span></pre><pre style="text-align: left;">===SORRY!=== Error while compiling -e</pre><p style="text-align: left;"><span style="font-family: courier;">Unsupported use of << to do left shift. In Raku please use: +< or ~<.</span></p><p style="text-align: left;"><span style="font-family: courier;">at -e:1</span></p><p style="text-align: left;"><span style="font-family: courier;">------> my $a = 1; say $a <<⏏ 2</span></p></blockquote><p><br /></p><p>The "<span style="font-family: courier;">use isms;</span>" <i>pragma </i>turns <b>off</b> this behaviour, so you get a different error message, helpful in a different way, but assuming you know what you are doing:</p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><p><span style="font-family: courier;">[jonathan@menenius hesabu]$ raku -e 'use isms; my $a = 1; say $a << 2'</span></p><p><span style="font-family: courier;">===SORRY!=== Error while compiling -e</span></p><p><span style="font-family: courier;">Variable '&infix:«<<»' is not declared. Perhaps you forgot a 'sub' if</span></p><p><span style="font-family: courier;">this was intended to be part of a signature?</span></p><p><span style="font-family: courier;">at -e:1</span></p><p><span style="font-family: courier;">------> use isms; my $a = 1; say $a ⏏<< 2</span></p></blockquote><p><br /></p><p>Which kind of gives us a clue to what we need to do to implement something like the C++ stream extraction operator.</p><p>Raku allows you to define new operators (or define new candidates for some existing operators with different meanings for different "arguments",) by defining a new subroutine that specifies the operator's behaviour for the specific arguments. In the case of the "<span style="font-family: courier;"><<</span>" we want to define an <i>infix </i>operator (that is one that has two "arguments" to the left and right of the operator,) so one define something like the C++ stream extraction operator something like:</p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;"><span style="font-family: courier;">sub infix:«<<» ( IO::Handle $h, Cool $v ) { $h.print: $v; $h }</span></p></blockquote><p>That is to say a subroutine that will be called when the operator "<span style="font-family: courier;"><<</span>" is used with an <span style="font-family: courier;">IO::Handle (</span><span style="font-family: inherit;">which is the base class of most IO classes,)</span><span style="font-family: courier;"> </span><span style="font-family: inherit;">on the left hand side and a </span><span style="font-family: courier;">Cool </span><span style="font-family: inherit;">(which is the base class for most of the built in Scalar types such as </span><span style="font-family: courier;">Str</span><span style="font-family: inherit;">, </span><span style="font-family: courier;">Int</span><span style="font-family: inherit;"> etc,) on the right hand side. It returns the LHS handle so an expression using this operator can in turn be used on the LHS of further uses of the operator and so on.</span></p><p><span style="font-family: inherit;">So this allows us to do:</span></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;"><span style="font-family: courier;">$*OUT << "foo";</span></p></blockquote><p>(omitting the actual definition of the operator and the "use isms;" that allows it to work.)</p><p>The "<span style="font-family: courier;">$*OUT</span>" is a "Dynamic Variable", that is one that can be redefined by assignment within a runtime scope (retaining the original value in outer scopes,) by default it is the <span style="font-family: courier;">IO::Handle</span> for <span style="font-family: courier;">STDOUT</span>.</p><p>But in C++ the stream object is "<span style="font-family: courier;">cout</span>" so to be more like C++ we need to use that <i>bareword </i>symbol rather than Raku's dynamic variable to represent the target handle.</p><p>Now we could express that as a regular subroutine, or as a sigil-less constant but the former has constraints on where it can be used without (even empty,) argument list, and the latter won't retain the dynamic behaviour of the underlying value (being set at compile time.) So this will be defined as a "<i>term</i>".</p><p>A "<span style="font-family: courier;">term</span>" is defined as a subroutine without any arguments that can be used anywhere that a <i>value</i> can be used in Raku code (builtin examples include <span style="font-family: courier;">now</span> and <span style="font-family: courier;">pi</span>,) so we can define "<span style="font-family: courier;">cout</span>" simply as</p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;"><span style="font-family: courier;">sub term:<cout> { $*OUT }</span></p></blockquote><p>Which allows <span style="font-family: courier;">cout</span> to be used anywhere that a value can be used without needing parentheses and will still allow the underlying value to be set within the runtime scope.</p><p>Obviously then the C++ symbol "<span style="font-family: courier;">endl</span>" can be defined simply as:</p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;"><span style="font-family: courier;">sub term:<endl> { "\n" }</span></p></blockquote><p><br /></p><p>And there you have it:</p><p><br /></p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><p><span style="font-family: courier;">use isms; </span></p><p><span style="font-family: courier;">sub infix:«<<»( IO::Handle $h, Cool $v ) { $h.print: $v; $h }; </span></p><p><span style="font-family: courier;">sub term:<cout> { $*OUT }; </span></p><p><span style="font-family: courier;">sub term:<endl> { "\n" }; </span></p><p><span style="font-family: courier;">cout << "Whatever" << endl;</span></p></blockquote><p><br /></p><p>Making the Raku programming language more familiar to C++ programmers. </p><div><br /></div><div><br /></div><p style="text-align: left;"></p><div><br /></div>Jomathan Stowehttp://www.blogger.com/profile/10543685469826752411noreply@blogger.com0tag:blogger.com,1999:blog-9221228962936805704.post-32188220842460909312022-02-05T16:25:00.000+00:002022-02-05T16:25:19.936+00:00Making a home thermostat with a Raspberry Pi and the Raku Programming Language. Part 1: getting the temperature.<p>
A few weeks ago I had a moment of hubris on Twitter
</p>
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p dir="ltr" lang="en">It would be nice to see something like the first one done in <a href="https://twitter.com/hashtag/rakulang?src=hash&ref_src=twsrc%5Etfw">#rakulang</a> - totally doable but right now I've got quite a deep TODO on that front. <a href="https://t.co/0qc24om02j">https://t.co/0qc24om02j</a></p>— Jonathan Stowe (@gellyfish) <a href="https://twitter.com/gellyfish/status/1480864530846691332?ref_src=twsrc%5Etfw">January 11, 2022</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<p>
I was particularly interested in the idea of <a href="https://opensource.com/article/21/3/thermostat-raspberry-pi">making a thermostat with a Raspberry Pi</a> but using <a href="https://rakudo.org/">Raku</a> instead of Python. Being somewhat impatient and impulsive I bought all the parts I thought I would need from Amazon and set about thinking about what the software would need to do.
</p>
<p>
The digital thermometer used (the <a href="https://www.maximintegrated.com/en/products/sensors/DS18B20.html">DS18B20</a> from Maxim Integrated,) seemed to be the natural place to start so I wrote a <a href="https://github.com/jonathanstowe/RPi-Device-DS18B20">Raku module</a> to read the temperatures from one or more of the devices. As this may be more generally useful in another programme and I can leave you with a somewhat useful programme without all the other parts, we'll start with this part.
</p>
<p>
The DS18B20 is a digital thermometer that uses the <a href="https://en.wikipedia.org/wiki/1-Wire">Dallas 1-Wire interface</a>, the nature of the interface means that a number of the devices can be attached using only a single GPIO pin on the Raspberry Pi. The 1-Wire protocol in general and thermometers specifically are fairly well supported by the Raspberry Pi OS, presenting each attached device as nodes in the <a href="https://www.kernel.org/doc/html/latest/filesystems/sysfs.html">sysfs</a>
</p>
<p>
Assuming you have the <a href="https://github.com/jonathanstowe/RPi-Device-DS18B20">RPi::Device::DS18B20</a> installed on your Raspberry Pi you will only need one or more DS18B20 devices (I'm using the encapsulated "waterproof" ones with longer wires, it seems it's just as cheap to buy five of these from Amazon than the bare chips,) a 4.7K resistor and for convenience a solderless breadboard and some patch cables.
</p>
<p>
The circuit itself is really quite simple:
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh_5Z9KXGj9aB34YyNfXrWpNNe5TkViBuqknXPPJBn7e_Nj0qzSSki57FL6n2F2n9U3J7Qaw3HrRkyqq_Jhb_1oE4bTS2bV7tW80l-RRVp6Tur16OJ_kyHVdvYnctiypIevDRf3a-7U5VrzxlDN2G_eXvWOcdUIWZc9rQkBGQ1iVh3-2VYd3uuXm2T4aw=s1755" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="1443" data-original-width="1755" src="https://blogger.googleusercontent.com/img/a/AVvXsEh_5Z9KXGj9aB34YyNfXrWpNNe5TkViBuqknXPPJBn7e_Nj0qzSSki57FL6n2F2n9U3J7Qaw3HrRkyqq_Jhb_1oE4bTS2bV7tW80l-RRVp6Tur16OJ_kyHVdvYnctiypIevDRf3a-7U5VrzxlDN2G_eXvWOcdUIWZc9rQkBGQ1iVh3-2VYd3uuXm2T4aw=s400" width="400" /></a></div>
<p>
Additional thermometers can be added by providing the power and linking the data lines (the yellow wire.)
</p>
<p>
With this circuit you can run the <a href="https://github.com/jonathanstowe/RPi-Device-DS18B20/blob/main/examples/synopsis">synopsis example</a>:
</p>
<p>
<script src="https://gist.github.com/jonathanstowe/fa0c6560be0200c1108a328ca517d92c.js"></script>
</p>
<p>
And you should get some output like:
</p>
<blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><pre style="text-align: left;">
28-012113620c31: 20.562
28-03213194ea4f: 17.25
</pre></blockquote>
<p>
I have two thermometers attached. The first thing you've probably noticed is the "<i>name</i>" of the devices, this device ID is basically baked in the chip at manufacture and not very human friendly so we'll providing a mapping of these to more useful names as we build the application.
</p>
<p>
For the first part of this we'll create a web application with <a href="https://cro.services/docs/intro/http-server">Cro::HTTP</a> which displays the temperatures dynamically, and for this kind of purpose <a href="https://github.com/jonathanstowe/RPi-Device-DS18B20">RPi::Device::DS18B20</a> provides an asynchronous interface via a which provides the readings periodically:
</p>
<script src="https://gist.github.com/jonathanstowe/ecdfd8deb2fa74dc81ade0181edfdef5.js"></script>
<p>
This emits a <i>Reading</i> object for each attached device periodically, because the thermometers may take different times to produce a result they may not be in any particular order but this means that, unlike the first example, you don't have to wait for a preceding reading which is taking longer. This is ideal for a web application where we can use <a href="https://en.wikipedia.org/wiki/Server-sent_events">Server Sent Events</a> with <a href="https://github.com/jonathanstowe/EventSource-Server">EventSource::Server</a> and some javascript on the client side to update the web page when new reading become available.
</p>
<p>
Given that we already have a <a href="https://docs.raku.org/type/Supply">Supply</a> from the <a href="https://github.com/jonathanstowe/RPi-Device-DS18B20">RPi::Device::DS18B20</a> and the <a href="https://github.com/jonathanstowe/EventSource-Server">EventSource::Server</a> can take a Supply of the events to be emitted we can do the majority of the work by mapping one Supply to one suitable to pass to the EventSource::Server:
</p>
<script src="https://gist.github.com/jonathanstowe/29d34f757ba305aa466ad1e4c8b25fa0.js"></script>
<p>
Here we are mapping the <i>Reading</i> objects emitted by the RPi::Device::DS18B20 Supply to a custom class <i>TemperatureEvent</i> which contains the mapped name of the device, the device id and the temperature. This class does the role <a href="https://github.com/jonathanstowe/JSON-Class">JSON::Class</a> so the objects can be trivially serialised to JSON in the next step where the JSON representation of the object is mapped into a <i>EventSource::Server::Event</i> with a type of 'reading'.
</p>
<p>
Here I've used a plain Hash to lookup the user friendly name from the device id,for a larger programme it may be more suitable in some configuration or other storage. If you do have more than thermometer device the easiest way to derive the lookup is to apply some source of warmth to each device in turn (a hot liquid or even holding it in your hand,) while running the first example each time, noting the device id with the raised temperature (and possibly labelling for future reference.)
</p>
<p>
And that is basically that, all that remains is to provide the <i>out-supply</i> of the EventSource::Server object as the content of an appropriate route in the Cro::HTTP application and provide a web-page in which to display the readings and we're done:
</p>
<script src="https://gist.github.com/jonathanstowe/c3cd395931a45f722f41d3ad3d20f3ae.js"></script>
<p>
The <i>index.html</i> is simply:
</p>
<script src="https://gist.github.com/jonathanstowe/86ad67c878f87cb5fdc8ccddafe104b8.js"></script>
<p>
Which basically arranges to read the events from the stream and update the table as appropriate. It could obviously be a bit prettier but we'll leave that for later.
</p>
<p>
In the next post or posts we'll update this application to do the other part of the thermostat application which is to turn relays on and off in order to control the central heating, but as I'm taking a slightly different approach than the post that inspired this I'll need to write a library to drive an <a href="https://www.microchip.com/en-us/product/mcp23017">MCP23017</a> first.
</p>
<p>
The code of the example can be found on <a href="https://github.com/jonathanstowe/RPi-Device-DS18B20/tree/main/examples/thermostat-part-1">Github</a>
</p>
Jomathan Stowehttp://www.blogger.com/profile/10543685469826752411noreply@blogger.com0tag:blogger.com,1999:blog-9221228962936805704.post-29602921537675271052015-10-15T21:56:00.003+01:002021-08-21T18:34:49.460+01:00Learning Perl 6 from bad Perl 5 code My friend <a href="http://perlhacks.com/author/davorg/" target="_blank">Dave Cross</a> doesn't like to see bad Perl code in the wild, and often when he finds it he will write about it,usually presenting a rewritten version that conforms to the generally accepted standards for writing Perl 5 code in the 21st century.<br />
<br />
Anyway yesterday I saw this magazine in a supermarket:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr-GP_LlkFka6mgb2uh8lXL5UW03DBVUpzpRXrRWV58bTz70zi8Ek0EjJBeSjrq5kttWZOrq-Oyd-CYpNLvJz-_g9HmmvLMC5B9zrzlnXiQHJ7T3sE-tyV-jsfZyJ-uJ3YaRwRx47vUmPa/s1600/12105947_10153577435711830_102721808654766775_n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr-GP_LlkFka6mgb2uh8lXL5UW03DBVUpzpRXrRWV58bTz70zi8Ek0EjJBeSjrq5kttWZOrq-Oyd-CYpNLvJz-_g9HmmvLMC5B9zrzlnXiQHJ7T3sE-tyV-jsfZyJ-uJ3YaRwRx47vUmPa/s320/12105947_10153577435711830_102721808654766775_n.jpg" width="176" /></a></div>
<br />
It has three good articles by Dave in it, and, as Dave pointed out on Facebook, the article he wrote about in <a href="http://perlhacks.com/2012/09/learning-from-bad-code/" target="_blank">Learning from Bad Code</a> (if you haven't already read that you may want to do it now as it'll save me copying the code and re-iterating what Dave said about it.)<br />
<br />
So it occurred to me that this bad code would provide a good didactic vehicle for introducing <a href="http://perl6.org/" target="_blank">Perl 6</a>, especially as Dave had already provided a good quality Perl 5 example with which it can be compared.<br />
<br />
So I wrote a Perl 6 version of the Starfield example:<br />
<br />
<script src="https://gist.github.com/jonathanstowe/72e5e79cd1b49d7009d7.js"></script>
<br />
This is approximately the same length as Dave's (I've been concise in some places and verbose in others, it could probably be done in fewer lines if one was so inclined.) I've used the Perl 6 module <a href="https://github.com/azawawi/perl6-ncurses/" target="_blank">NCurses</a> which is basically the same as the Perl 5 module in the example except it doesn't provide an object oriented interface.<br />
<br />
If you're already familiar with Perl 6 you'll probably already understand the code.<br />
<br />
The first thing you may notice is that there is no "<span style="font-family: "courier new" , "courier" , monospace;"><i>use strict</i></span>" or "<span style="font-family: "courier new" , "courier" , monospace;"><i>use warnings</i></span>" in the code, this is because that these things are effectively on by default, which means (among other things,) that variables must be declared and types defined before they are used. Perl 6 in general will catch a lot more problems with code at compile time, (and typically provide more helpful error messages,) which can significantly enhance the programmer's experience.<br />
<br />
The "<span style="font-family: "courier new" , "courier" , monospace;"><i>use v6</i></span>" is not strictly necessary here, (infact it is basically ignored by the Perl 6 compiler,) however it is of benefit when you are working in both Perl 6 and Perl 5 as it will give rise to an error such as<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">Perl v6.0.0 required--this is only v5.20.3</span></blockquote>
When run as Perl 5 code, rather than something more confusing when it fails to parse the Perl 6 code later on.<br />
<br />
Rather than use variables for the basic parameters of the program in my example I have used constants defined with the "<span style="font-family: "courier new" , "courier" , monospace;"><i>constant</i></span>" keyword, this is conceptually similar to "<span style="font-family: "courier new" , "courier" , monospace;">use constant</span>" in Perl 5 in that it introduces a name that can be used in place of some value later in the code, however, unlike "<span style="font-family: "courier new" , "courier" , monospace;"><i>use constant</i></span>" which creates a constant subroutine which limits it's use in certain places in your code, it introduces a "term" which can be used anywhere that, for example, a literal value can be used. <br />
<br />
The names of the constants warrant mention too: Perl 6 allows the use of a hyphen in identifiers (such as variable or subroutine name, or constants as here,) there is a definite preference toward "<a href="http://c2.com/cgi/wiki?KebabCase" target="_blank">Kebab Case</a>" as opposed to "<a href="https://en.wikipedia.org/wiki/Snake_case" target="_blank">Snake Case</a>", as typically found in Perl 5. In some places this may lead to a reduction in brevity (because more white space becomes significant,) but this reflects a general inclination in favour of clarity and consistency over brevity in the design.<br />
<br />
I've used objects of the class "Star" to hold the star data and provide the movement behaviour. Dave's choice to use a hash to store the star data is sensible in a short program like this: in Perl 5 you would either have to provide an amount of boilerplate code to define the constructor and the accessors or use a fairly heavyweight external module such as <a href="https://metacpan.org/release/Moose" target="_blank">Moose</a>; with Perl 6 you get a powerful and clean object system out of the box: this is all documented in the <a href="http://doc.perl6.org/language/objects" target="_blank">Object Orientation</a> document, so I'll just describe the things that I have implemented.<br />
<br />
The <i style="font-family: 'Courier New', Courier, monospace;">BUILD </i><span style="font-family: inherit;">submethod here isn't strictly necessary as the values could have been supplied as default initializers to the attributes directly, but it makes things clearer in this example. The initialising expressions are quite a common idiom: using "</span><span style="font-family: "courier new" , "courier" , monospace;"><i><a href="http://doc.perl6.org/routine/pick#class_List" target="_blank">.pick</a></i></span><span style="font-family: inherit;">" on a list defined by an appropriate </span><a href="http://doc.perl6.org/type/Range" style="font-family: 'Courier New', Courier, monospace; font-style: italic;" target="_blank">Range</a>; Range is similar to the '...' range operator in Perl 5 but somewhat more generalised and more powerful, they crop up regularly in loop constructs, array slices and so forth.<br />
<br />
The observant may have noticed that the attributes of the class are declared as $.x, $.y and $.s but are used as $!x, $!y and $!s in the <span style="font-family: "courier new" , "courier" , monospace;"><i>BUILD</i></span>. This is quite common within classes: the '.' "<i>twigil</i>" declares the attribute as being public and a public accessor will be created for it, within the methods of the class itself the attribute can be referred to directly with the '!' twigil without going through the public accessor, by default the public accessor is read-only so within the class it can only be assigned to this way. The accessor can be made writeable by applying the "is rw" trait to the definition but this isn't necessary here.<br />
<br />
The "<span style="font-family: "courier new" , "courier" , monospace;"><i>move</i></span>" method uses the "ternary" or "conditional" statement for brevity as opposed to the two separate statements in the original example, this works exactly the same as it does in Perl 5, just the '?' and ':' of Perl 5 have been renamed to '??' and '!!' for reasons of grammatical simplicity.<br />
<br />
The array of star objects is declared and initialised in a single statement for brevity: the array is declared as being comprised of Star objects, any attempt to add anything else to it will result in a fatal error, this can reduce complexity and aid debugging in larger programs but isn't really necessary here and could be omitted. Of course arrays without a declared type can hold any types of objects just as in Perl 5.<br />
<br />
In order to keep the initialiser to one line and still be readable I have used "<span style="font-family: "courier new" , "courier" , monospace;"><i>gather</i></span>"/"<span style="font-family: "courier new" , "courier" , monospace;"><i>take</i></span>": the gather basically returns an iterator with one item for each time a "take" is encountered; the "for" statement modifier here works pretty much the same way as in Perl 5: the "<span style="font-family: "courier new" , "courier" , monospace;"><i>take Star.new</i></span>" is executed 'numstars' times (i.e 100 times.) The gather's iterator is automatically expanded on assignment to the array.<br />
<br />
While Perl 6 does still support the "<span style="font-family: "courier new" , "courier" , monospace;"><i>while(1)</i></span>" in the Perl 5 (though it would probably be better written "<span style="font-family: "courier new" , "courier" , monospace;"><i>while(True)</i></span>" as Perl 6 has true booleans,) it is more idiomatic to use "<span style="font-family: "courier new" , "courier" , monospace;"><i>loop</i></span>" for an infinite loop of this sort. The "<span style="font-family: "courier new" , "courier" , monospace;"><i>loop</i></span>" statement replaces the three-part or "C-Style" "<span style="font-family: "courier new" , "courier" , monospace;"><i>for</i></span>" in Perl 5 and its bare usage here is equivalent to "<span style="font-family: "courier new" , "courier" , monospace;"><i>loop (;;)</i></span>"; the "<span style="font-family: "courier new" , "courier" , monospace;"><i>for</i></span>" in Perl 6 no longer supports this iterator style.<br />
<br />
The inner loop iterating over the array of Star objects illustrates the way the "<span style="font-family: "courier new" , "courier" , monospace;"><i>for</i></span>" loop statement differs from that in Perl 5 (incidentally the "<span style="font-family: "courier new" , "courier" , monospace;"><i>foreach</i></span>" synonym no longer exists, Perl 6 code only has "<span style="font-family: "courier new" , "courier" , monospace;"><i>for</i></span>".) At its simplest the Perl 6 "<span style="font-family: "courier new" , "courier" , monospace;"><i>for</i></span>" can be thought of as iterating over the supplied list and for each item executing the associated block with the item as an argument; by default the item is passed in the 'topic' variable "<span style="font-family: "courier new" , "courier" , monospace;"><i>$_</i></span>" much as in Perl 5, however, as in this example, the argument can be named with the argument variable ( or variables separated by a comma,) following the '->'; in the Perl 6 jargon this is known as a "pointy block" and can be thought of as an anonymous subroutine with the specified parameters. the parameter variable doesn't need to be declared with '<span style="font-family: "courier new" , "courier" , monospace;"><i>my</i></span>' as you might the target variable in Perl 5 as the declaration is implicit in it being a parameter.<br />
<br />
So there you have it, the Perl 6 version is not much longer than the good Perl 5 one and is at least as readable and maintainable It uses the Perl 6 Object Orientation features without adding unwanted cruft to the code so you could extend the behaviour of the stars without changing the body of the code.<br />
<br />
Perl 6 not as frightening as you thought it was.Jomathan Stowehttp://www.blogger.com/profile/10543685469826752411noreply@blogger.com2