Perl and Raku differ fundamentally, though in general the intent has been to "keep Raku Perl", so that Raku is clearly "a Perl programming language". Most of the changes are intended to normalize the language, to make it easier for novice and expert programmers alike to understand, and to make "easy things easier and hard things more possible".
A specification A major non-technical difference between Perl and Raku is that Raku began as a specification. This means that Raku can be re-implemented if needed, and it also means that programmers do not have to read the
source code for the ultimate authority on any given feature. In contrast, in Perl, the official documentation is not considered authoritative and only describes the behavior of the actual Perl interpreter informally. Any discrepancies found between the documentation and the implementation may lead to either being changed to reflect the other, a dynamic which drives the continuing development and refinement of the Perl releases.
A type system In Raku, the
dynamic type system of Perl has been augmented by the addition of
static types. For example: my Int $i = 0; my Rat $r = 3.142; my Str $s = "Hello, world"; However, static typing remains
optional, so programmers can do most things without any explicit typing at all: my $i = "25" + 10; # $i is 35 Raku offers a
gradual typing system, whereby the programmer may choose to use static typing, use dynamic typing, or mix the two.
Formal subroutine parameter lists Perl defines subroutines without
formal parameter lists at all (though simple parameter counting and some type checking can be done using Perl's "prototypes"). Subroutine arguments passed in are aliased into the elements of the array @_. If the elements of @_ are modified, the changes are reflected in the original data. Raku introduces true formal parameters to the language. In Raku, a subroutine declaration looks like this: sub do_something(Str $thing, Int $other) { ... } As in Perl, the formal parameters (i.e., the variables in the parameter list) are aliases to the actual parameters (the values passed in), but by default, the aliases are
constant so they cannot be modified. They may be declared explicitly as read-write aliases for the original value or as copies using the is rw or is copy directives respectively should the programmer require them to be modified locally.
Parameter passing modes Raku provides three basic modes of parameter passing: positional parameters,
named parameters, and slurpy parameters. Positional parameters are the typical ordered list of parameters that most programming languages use. All parameters may also be passed by using their name in an unordered way. Named-only parameters (indicated by a : before the parameter name) can only be passed by specifying its name, i.e. it never captures a positional argument. Slurpy parameters (indicated by an * before the parameter name) are Raku's tool for creating
variadic functions. A slurpy hash will capture remaining passed-by-name parameters, whereas a slurpy array will capture remaining passed-by-position parameters. Here is an example of the use of all three parameter-passing modes: sub somefunction($a, $b, :$c, :$d, *@e) { ... } somefunction(1, 2, :d(3), 4, 5, 6); # $a=1, $b=2, $d=3, @e=(4,5,6) Positional parameters, such as those used above, are always required unless followed by ? to indicate that they are optional. Named parameters are optional by default, but may be marked as required by adding ! after the variable name. Slurpy parameters are
always optional.
Blocks and closures Parameters can also be passed to arbitrary blocks, which act as
closures. This is how, for example, for and while loop iterators are named. In the following example, a list is traversed, 3 elements at a time, and passed to the loop's block as the variables, $a, $b, $c. for @list -> $a, $b, $c { ... } This is generally referred to as a "pointy sub" or "pointy block", and the arrow behaves almost exactly like the sub keyword, introducing an anonymous closure (or anonymous subroutine in Perl terminology). For example, a class to encapsulate a
Cartesian point could be defined and used this way: class Point is rw { has $.x; has $.y; method distance( Point $p ) { sqrt(($!x - $p.x) ** 2 + ($!y - $p.y) ** 2) } method distance-to-center { self.distance: Point.new(x => 0, y => 0) } } my $point = Point.new( x => 1.2, y => -3.7 ); say "Point's location: (", $point.x, ', ', $point.y, ')'; • OUTPUT: Point's location: (1.2, -3.7) • Changing x and y (note methods "x" and "y" used as lvalues): $point.x = 3; $point.y = 4; say "Point's location: (", $point.x, ', ', $point.y, ')'; • OUTPUT: Point's location: (3, 4) my $other-point = Point.new(x => -5, y => 10); $point.distance($other-point); #=> 10 $point.distance-to-center; #=> 5 The dot replaces the arrow in a nod to the many other languages (e.g.
C++,
Java,
Python, etc.) that have coalesced around dot as the syntax for method invocation. In the terminology of Raku, $.x is called an "attribute". Some languages call these
fields or
members. The method used to access an attribute is called an "accessor". An auto-accessor method is a method created automatically and named after the attribute's name, as the method x is in the example above. These accessor functions return the value of the attribute. When a class or individual attribute is declared with the is rw modifier (short for "read/write"), the auto-accessors can be passed a new value to set the attribute to, or it can be directly assigned to as an
lvalue (as in the example). Auto-accessors can be replaced by user-defined methods, should the programmer desire a richer interface to an attribute. Attributes can only be accessed directly from within a class definition via the $! syntax regardless of how the attributes are declared. All other access must go through the accessor methods. The Raku object system has inspired the
Moose framework that introduces many of Raku's OOP features to Perl.
Inheritance, Roles and Classes Inheritance is the technique by which an object or type can re-use code or definitions from existing objects or types. For example, a programmer may want to have a standard type but with an extra attribute. Inheritance in other languages, such as Java, is provided by allowing Classes to be sub-classes of existing classes. Raku provides for inheritance via Classes, which are similar to Classes in other languages, and Roles. Roles in Raku take on the function of
interfaces in Java,
mixins in Ruby, and
traits in
PHP and in the
Smalltalk variant
Squeak. These are much like classes, but they provide a safer composition mechanism. These are used to perform composition when used with classes rather than adding to their
inheritance chain. Roles define nominal types; they provide semantic names for collections of behavior and state. The fundamental difference between a role and a class is that classes can be instantiated; roles are not. Although Roles are distinct from Classes, it is possible to write Raku code that directly instantiates a Role or uses a Role as a type object, Raku will automatically create a class with the same name as the role, making it possible to transparently use a role as if it were a class. Essentially, a role is a bundle of (possibly abstract) methods and attributes that can be added to a class without using inheritance. A role can even be added to an individual object; in this case, Raku will create an anonymous subclass, add the role to the subclass, and change the object's class to the anonymous subclass. For example, a
Dog is a
Mammal because dogs inherit certain characteristics from Mammals, such as
mammary glands and (through Mammal's parent,
Vertebrate) a
backbone. On the other hand, dogs also may have one of several distinct types of behavior, and these behaviours may change over time. For example, a Dog may be a
Pet, a
Stray (an abandoned pet will acquire behaviours to survive not associated with a pet), or a
Guide for the blind (guide dogs are trained, so they do not start life as guide dogs). However, these are sets of additional behaviors that can be added to a Dog. It is also possible to describe these behaviors in such a way that they can be usefully applied to other animals, for example, a
Cat can equally be a Pet or Stray. Hence, Dog and Cat are distinct from each other, while both remain within the more general category Mammal. So Mammal is a Class and Dog and Cat are classes that inherit from Mammal. But the behaviours associated with Pet, Stray, and Guide are Roles that can be added to Classes, or objects instantiated from Classes. class Mammal is Vertebrate { ... } class Dog is Mammal { ... } role Pet { ... } role Stray { ... } role Guide { ... } Roles are added to a class or object with the does keyword. In order to show inheritance from a class, there is a different keyword is. The keywords reflect the differing meanings of the two features: role composition gives a class the
behavior of the role, but doesn't indicate that it is truly the
same thing as the role. class GuideDog is Dog does Guide { ... } # Subclass composes role my $dog = new Dog; $dog does Guide; # Individual object composes role Although roles are distinct from classes, both are types, so a role can appear in a variable declaration where one would normally put a class. For example, a Blind role for a Human could include an attribute of type Guide; this attribute could contain a Guide Dog, a
Guide Horse, a Guide Human, or even a Guide Machine. class Human { has Dog $dog; # Can contain any kind of Dog, whether it does the ... # Guide role or not } role Blind { has Guide $guide; # Can contain any object that does the Guide role, ... # whether it is a Dog or something else }
Regular expressions Perl's
regular expression and string-processing support has always been one of its defining features. Since Perl's pattern-matching constructs have exceeded the capabilities of
regular language expressions for some time, Raku documentation exclusively refers to them as
regexes, distancing the term from the formal definition. Raku provides a superset of Perl features with respect to regexes, folding them into a larger framework called "
rules" which provide the capabilities of
context-sensitive parsing formalisms (such as the
syntactic predicates of
parsing expression grammars and
ANTLR), as well as acting as a
closure with respect to their
lexical scope. Rules are introduced with the rule keyword which has a usage quite similar to subroutine definition. Anonymous rules can also be introduced with the regex (or rx) keyword, or they can simply be used inline as regexps were in Perl via the m (matching) or s (substitute) operators. In
Apocalypse 5, Larry Wall enumerated 20 problems with "current regex culture". Among these were that Perl's regexes were "too compact and 'cute'", had "too much reliance on too few metacharacters", "little support for named captures", "little support for grammars", and "poor integration with 'real' language".
Syntactic simplification Some Perl constructs have been changed in Raku, optimized for different syntactic cues for the most common cases. For example, the parentheses (round
brackets) required in
control flow constructs in Perl are now optional: @integers = 0..Inf; # integers from 0 to infinity The code above will not crash by attempting to assign a list of infinite size to the array @integers, nor will it hang indefinitely in attempting to expand the list if a limited number of slots are searched. This simplifies many common tasks in Raku including
input/output operations, list transformations, and parameter passing.
Gather Related to lazy evaluation is the construction of lazy lists using gather and take, behaving somewhat like generators in languages like
Icon or
Python. my $squares = lazy gather for 0..Inf { take $_ * $_; }; $squares will be an infinite list of square numbers, but lazy evaluation of the gather ensures that elements are only computed when they are accessed.
Junctions Raku introduces the concept of
junctions: values that are composites of other values. It is this Lisp-like macro concept that Raku will take advantage of. macro hello($what) { quasi { say "Hello { {} }" }; } In this particular example, the macro is no more complex than a C-style textual substitution, but because parsing of the macro parameter occurs before the macro operates on the calling code, diagnostic messages would be far more informative. However, because the body of a macro is executed at
compile time each time it is used, many techniques of
optimization can be employed. It is even possible to eliminate complex computations from resulting programs by performing the work at compile-time.
Identifiers In Perl, identifier names can use the ASCII alphanumerics and underscores also available in other languages. In Raku, the alphanumerics can include most Unicode characters. In addition, hyphens and apostrophes can be used (with certain restrictions, such as not being followed by a digit). Using hyphens instead of underscores to separate words in a name leads to a style of naming called "
kebab case". ==Examples==