In the machine world, we have Int and Num. A High Level Language such as Raku is a abstraction to make it easier for humans. Humans expect decimal math 0.1 + 0.2 = 0.3 to work.
Neither Int nor Num can do this! Huh? How can that be?
Well Int is base-2 and decimals are base-10. And Num (IEEE 754 Floating Point) is inherently imprecise.
Luckily we have Rat. Raku automatically represent decimals and other rational numbers as a ratio of two integers. Taking into account all the various data shuffling any program creates, the performance is practically as fast as Int. Precision, accuracy and performance are maintained for the entire realm of practical algebraic calculations.
And when we get to the limit of Rat (at around 3.614007241618348e-20), Raku automatically converts to a Num. After this, precision cannot be recovered – but accuracy and dynamic range are maintained. Modern Floating Point Units (FPUs) make Num nearly as fast as Int so performance is kept fast.
Here, we have smoothly transitioned to the world of physical measurements and irrational numbers such as square root and logarithms. It’s a one way trip. (Hint: If you want a Num in the first place, just use ‘e’ in the literal.)
Good call, Raku!
Footnote: FatRat and BigInt are not important for most use cases. They incur a performance penalty for the average program and rightly belong in library extensions, not the core language.
It was an emotional moment to see the keynote talk at TPRCiC from Sawyer X announcing that perl 7.00 === 5.32. Elation because of the ability of the hardcore perl community to finally break free of the frustrating perl6 roadblock. Pleasure in seeing how the risky decision to rename perl6 to raku has paid off and hopefully is beginning to defuse the tensions between the two rival communities. And Fear that improvements to perl7 will undermine the reasons for many to try out raku and may cannibalise raku usage. (Kudos to Sawyer to recognising that usage is an important design goal).
Then the left side of my brain kicked in. Raku took 15 years of total commitment of genius linguists to ingest 361 RFCs and then synthesise a new kind of programming language. If perl7 seeks the same level of completeness and perfection as raku, surely that will take the same amount of effort. And I do not see the perl community going for the same level of breaking changes that raku did. (OK maybe they could steal some stuff from raku to speed things up…)
And that brought me to Sadness. To reflect that perl Osborned sometime around 2005. That broke the community in two – let’s say the visionaries and the practical-cats. And it drove a mass emigration to Python. Ancient history.
So now we have two sister languages, and each will find a niche in the programming ecosystem via a process of Darwinism. They both inherit the traits (https://en.wikipedia.org/wiki/Perl#Design) that made perl great in the first place….
The design of Perl can be understood as a response to three broad trends in the computer industry: falling hardware costs, rising labor costs, and improvements in compiler technology. Many earlier computer languages, such as Fortran and C, aimed to make efficient use of expensive computer hardware. In contrast, Perl was designed so that computer programmers could write programs more quickly and easily.
Perl has many features that ease the task of the programmer at the expense of greater CPU and memory requirements. These include automatic memory management; dynamic typing; strings, lists, and hashes; regular expressions; introspection; and an eval() function. Perl follows the theory of “no built-in limits,” an idea similar to the Zero One Infinity rule.
Wall was trained as a linguist, and the design of Perl is very much informed by linguistic principles. Examples include Huffman coding(common constructions should be short), good end-weighting (the important information should come first), and a large collection of language primitives. Perl favours language constructs that are concise and natural for humans to write.
Perl’s syntax reflects the idea that “things that are different should look different.” For example, scalars, arrays, and hashes have different leading sigils. Array indices and hash keys use different kinds of braces. Strings and regular expressions have different standard delimiters. This approach can be contrasted with a language such as Lisp, where the same basic syntax, composed of simple and universal symbolic expressions, is used for all purposes.
But perl7 and raku serve distinct interests & needs:
one pass compiler
relies on pre-c0mp
relies on jit
Cor not module
Roles + Is
Roles + Is + multiple
Sets & Mixes
cleaner (e.g. for ->)
…and so on
A long list and perhaps a little harsh on perl since many things may be got from CPAN – but when you use raku in anger, you do see the benefit if having a large core language. Only when I made this table, did I truly realise just what a comprehensive language raku is, and that perl will genuinely be the lean and mean option.
And, lest we forget our strengths:
When I first saw Python code, I thought that using indents to define the scope seemed like a good idea. However, there’s a huge downside. Deep nesting is permitted, but lines can get so wide that they wrap lines in the text editor. Long functions and long conditional actions may make it hard to match the start to the end. And I pity anyone who miscounts spaces and accidentally puts in three spaces instead of four somewhere — this can take hours to debug and track down. [Source: here]
Coming from Python, the Raku object model is recognizable, but brings a tad more structure:
What works for me, as a convenience seeker, is:
the attributes $.x, $.y are automatically provided with setter and getter methods
the constructor new() is automatically provided
the output method e.g. ‘say $p.Str’ is automatically provided
I can simply assign to an attribute with ‘=’
These are the things you want if you are writing in a more procedural or functional style and using class as a means to define a record type.
Chapter 2: The Control Freak
Here’s the rub…
When we describe OO, terms like “encapsulation” and “data hiding” often come up. The key idea here is that the state model inside the object – that is, the way it chooses to represent the data it needs in order to implement its behaviours (the methods) – is free to evolve, for example to handle new requirements. The more complex the object, the more liberating this becomes.
However, getters and setters are methods that have an implicit connection with the state. While we might claim we’re achieving data hiding because we’re calling a method, not accessing state directly, my experience is that we quickly end up at a place where outside code is making sequences of setter calls to achieve an operation – which is a form of the feature envy anti-pattern. And if we’re doing that, it’s pretty certain we’ll end up with logic outside of the object that does a mix of getter and setter operations to achieve an operation. Really, these operations should have been exposed as methods with a names that describes what is being achieved. This becomes even more important if we’re in a concurrent setting; a well-designed object is often fairly easy to protect at the method boundary.
Having hit rock bottom with an ‘I can’t understand my own code sufficiently enough to extend/maintain it’, I have been on a journey to review the perl5 Physics::Unit design and to use this to cut through my self made mess of raku Physics::Unit version 0.0.2.
Now I bring the perspective of a couple of years of regular raku coding to bear, so I am hoping that the bastard child of mature perl5 and raku version one will surpass both in the spirit of David Bowie’s “Pretty Things”.
One of the reasons I chose Physics::Units as a project was that, on the face of it, it seemed to have an aspect that could be approached by raku Grammars – helping me learn them. Here’s a sample of the perl5 version:
Yes – a recursive descent parser written from scratch in perl5 – pay dirt! There are 215 source code lines dedicated to the parse function. 5 more screens like this…
So I took out my newly sharpened raku tools and here’s my entire port:
Instead of ranging over 215 lines, raku has refined this down to a total of 58 lines (incl. the 11 blank ones I kept in for readability) – that’s a space saving of over 70%. Partly removal of parser boilerplate code, partly the raku Grammar constructs and partly an increased focus on the program logic as opposed to the mechanism.
For my coding style, this represents a greater than a two-thirds improvement – by getting the whole parser onto a single screen, I find that I can get the whole problem into my brain’s working memory and avoid burning cycles scrolling up and down to pin down butterflies bugs.
Attentive students will have noted that the Grammar / code integration provides a very natural paradigm for loading real-world data into an OO system, the UnitAction class starts with a stub object and populates ‘has’ attributes as it goes.
Oh and the raku code does a whole lot more such as support for unicode superscripts (up to +/-4), type assignment and type checking, offsets (such as 0 K = 273.15 °C), wider tolerance of user input and so on. Most importantly Real values are kept as Rats as much as possible which helps greatly for example, when round tripping 38.5 °C to°F and back it is still equals 38.5 °C!
One final remark – use Grammar::Tracer is a fantastic debugging tool for finding and fixing the subtle bugs that can come in and contributing to quickly getting to the optimum solution.
For anyone wondering where my occasional blog on raku has been for a couple of months – sorry. I have been busy wrestling with, and losing to, the first released version of my Physics::Measure module.
Of course, this is all a bit overshadowed by the name change from perl6 to raku. I was skeptical on this, but did not have a strong opinion either way. So kudos to the folks who thrashed this out and I am looking forward to a naissance. For now, I have decided to keep my nickname ‘p6steve’ – I enjoy the resonance between P6 and P–sics and that is my niche. No offence intended to either camp.
My stated aim (blogs passim) is to create a set of physical units that makes sense for high school education. To me, inspired by the perl5 Physics::Unit module, that means not just core SI units for science class, but also old style units like sea miles, furlongs/fortnight and so on for geography and even history. As I started to roll out v0.0.3 of raku Physics::Unit, I thought it would be worthwhile to track a real-world high school education resource, namely OpenStax CNX. As I came upon this passage, I had to take the firkin challenge on:
While there are numerous types of units that we are all familiar with, there are others that are much more obscure. For example, a firkin is a unit of volume that was once used to measure beer. One firkin equals about 34 liters. To learn more about nonstandard units, use a dictionary or encyclopedia to research different “weights and measures.” Take note of any unusual units, such as a barleycorn, that are not listed in the text. Think about how the unit is defined and state its relationship to SI units.
Disaster – I went back to the code for Physics::Unit and, blow me, could I figure out how to drop in a new Unit: the firkin??…. nope!! Why not? Well Physics::Unit v:0.0.3 was impenetrable even to me, the author. Statistically it has 638 lines of code alongside 380 lines of heredoc data. Practically, while it passes all the tests 100%, it is not a practical, maintainable code base.
How did we get here? Well I plead guilty to being an average perl5 coder who really loves the expressivity that Larry offers … but a newbie to raku. I wanted to take on Physics::Measure to learn raku. Finally, I have started to get raku – but it has taken me a couple of years to get to this point!
My best step now – bin the code. I have dumped my original effort, gone back to the original perl5 Physics::Unit module source and transposed it to raku. The result: 296 lines of tight code alongside the same 380 lines of heredoc – a reduction of 53%! And a new found respect for the design skill of my perl5 forbears.
One of the most exciting parts of blogging about and hacking on perl6* is that there’s a community out there and there’s (always) more than one way to do it!
For Physics::Measure I have been working on a design for a ‘nano-slang’ that can provide a shortcut for the usual new Class declaration… quite long winded for my target audience of physics undergraduates and high school students.
#Instances the usual way
my Unit $u .=new(name => ‘m’, unitsof => ‘Distance’); #Unit m
my Distance $a .=new(value => 10, units => $u); #Distance 10 m
So, duly inspired by Rakudo perl6 going atomic ⚛ applying unicode to some threading constructs, I started with the notion of the ‘libra’ operator ♎️ as shorthand to declare and load Measure instances.
#Introducing the libra operator ♎️ as shorthand to declare and load
my $b ♎️ ’50 m’; #Distance 50 m
$b ♎️ ‘3 yards’; #Distance 3 yards
As you can see, the gap created between ♎️ and ; is a slang zone that can consume strings and numeric literals. Here’s something a bit more elaborate:
#Normalization with the .norm method
my $p ♎️ ’27 kg m^2 / s^3′; #Power 27 kg m^2 / s^3
$p .= norm; #Power 27 W
A few design ideas drew me in this direction:
Physics::Measure overloads the main arithmetic operators (+,-,*,/,**,sqrt) and I felt that the use of ♎️ unicode would be a good convention to warn coders that there is something substantive happening to the core raku language.
It is verboten in Rakudo to overload assignment ‘=’ … quite right too! But I wanted something like a combined variable declaration and (default) assignment for the congenitally lazy coder (and the libra kinda looks like an equals sign).
Resistance is one of the Units implemented by Physics::Measure – and the Ohm symbol (Ω) looks a lot like ♎️.
There are a couple hundred definition lines in Physics::Measure covering metric SI units, cgi, feet and inches, US and imperial, plus some fun ones, so it wasn’t practical to inject infix/postfix equivalents 1:1 without overwhelming the raku module namespace.
I was born in October 😉
[‘Ω’, ‘Ohm:s’,], ’kg m^2 / A^2 s^3′,
[‘kilohm:s’,], ’kilo Ohm’,
[‘megohm:s’,], ’mega Ohm’,
Others have proposed a much more direct approach to generate and combine Measure objects – by the use of a simple postfix syntax – thank you!
say 500g; # –> Weight.new(grams => 500, prefix => “”)
say 2kg;# –> Weight.new(grams => 2000, prefix => “kg”)
Watch this space! Or even better zef Physics::Measure and give it a try…
Observant readers looking at the dateline on the left will have noticed a gap of nearly two years between my last blog and today. As a fascinated programming hobbyist, I have only limited time in the day to devote to coding – and a startup venture put the brakes on anything but the day job for a while.
In the meantime, I have had to choose between coding and blogging – and while the ideas have been flowing ahead, I am quite keen on the idea that ‘actions speak louder than words’.
The actions have covered:
learning baby perl6 (highly recommend Think Perl6 by Laurent Rosenfeld)
learning perl6 OO
learning perl6 Grammars
learning about Unit systems
writing Physics::Measure v0.0.1
figuring out the point of it all
writing and publishing Math::Polygons
asking a bunch of questions under the perl6 tag on Stack Overflow
learning a bit more about perl6
writing and publishing Physics::Measure v0.0.2 (~2k lines)
Apologies to those that have OO steeped in their blood. I am a wary traveller in OO space, maybe I am an technician, not an architect at heart. So for me, no sweeping frameworks unless and until they are needed. And, frankly, one can go a long way on procedural code with subroutines to gather repetitive code sequences.
(And don’t get me started on functional programming…)
Some time ago, I was tasked to write a LIMS in old perl. Physical ‘aliquots’ with injections of various liquids would be combined and recombined by bio-machines. This led to a dawning realization that these aliquot objects could be modelled in an object style with parent / child relationships. After a few weeks, I proudly delivered my lowly attempt at ‘Mu’ for this (and only this) problem. Kudos to the P6 team – after a couple of weeks in here, it’s just sensational the level of OO power that the real Mu delivers:
Now, hard at work, on the perl6 version of Physics::Unit, I am wondering how to put the OO theory into productive practice. One of my aims was to find a medium sized (not core tools) problem that (i) I know something about and (ii) would be a good-sized problem to wrangle.
So I am enjoying the chance to design some classes and some interfaces that will make this all hang together. But – as an explorer, it has become clear that I only have three options. The problem runs like this:
There is a parent Measure class that contains the methods for any real-world measurement handling dimension, units, value and errors.
Then there are child classes for my Distance $d = ’42 m’, my Time $t = 3 s’, etc.
First level, I have an operation like … my $r = ’23 ft’ + $d;
Initially I had some success with object types ::T – but these only let you read the type and duplicate if needed for a new left hand side container. Then I tried the built in (shallow) clone method. But…
What about the operation … my $s = $d / $t?
How do I create a new Speed object programatically?
Ultimately, thanks to rosettacode.org, I worked out that $x.perl.EVAL with some ~~ s/// substitions on the way would do the trick!
Phew. Please comment below if you have a better way to share – or would like to point out the risks of this technique…
The rationale for the use of unicode symbols is as follows:
These represent operations that are rare
They relate to a specific domain (in this case, concurrency)
Programmers can always fall back on the ASCII version (e.g. atomic-inc )
BTW- ASCII versions are known as Texas versions since they are always bigger
Certainly this has caused some consternation – ranging from how can I type ⚛️ on my keyboard (hit CTRL-CMD-SPACE if you are on macOS ) to this will never be accepted for the coding standards of my company.
On reflection, while it is understandable that programmers have a well established comfort zone of ASCII text and using English for keywords, I think that perl6 is leading the way on an irresistible path. Of the 6.5bn people on the planet, only a small fraction prefer to work in English – or even in Latin alphabets. Now, the pioneering work to embed unicode in a programming language will open the doors to all kinds of invention. What about:
A slang (i.e. a perl6 sublanguage) for the French, Germans or Japanese programmer
Ability to parse all unicode alphabets – so linguists can digitize, analyze and compose writing from all parts of the globe, even dead scripts like Egyptian
Or, back to the point, opening a new world of symbol space to side step the crammed ASCII non alphanumeric characters that confines our programming
And this, in combination with perl6 Grammars, opens some interesting conceptual doors.