Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Raku (programming language)
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==Major changes from Perl== 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.<ref name="syn01">{{cite web | url=https://design.raku.org/S01.html | title=Synopsis 1: Overview | author=Wall, Larry | date=2004-08-10 }}</ref> 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|dynamic type system]] of Perl has been augmented by the addition of [[static type]]s.<ref name="syn2">{{cite web | url=https://design.raku.org/S02.html | title=Synopsis 2: Bits and Pieces | author=Wall, Larry | date=2009-05-20 }}</ref> For example: <syntaxhighlight lang="raku"> my Int $i = 0; my Rat $r = 3.142; my Str $s = "Hello, world"; </syntaxhighlight> However, static typing remains [[Type system#Combining static and dynamic type checking|optional]], so programmers can do most things without any explicit typing at all: <syntaxhighlight lang="raku"> my $i = "25" + 10; # $i is 35 </syntaxhighlight> 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 [[parameter (computer science)|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 <code>@_</code>. If the elements of <code>@_</code> are modified, the changes are reflected in the original data. Raku introduces true formal parameters to the language.<ref name="syn6">{{cite web | url=https://design.raku.org/S06.html | title=Synopsis 6: Subroutines | author=Wall, Larry | date=2003-03-21 }}</ref> In Raku, a subroutine declaration looks like this: <syntaxhighlight lang="raku"> sub do_something(Str $thing, Int $other) { ... } </syntaxhighlight> 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 (programming)|constant]] so they cannot be modified. They may be declared explicitly as read-write aliases for the original value or as copies using the <code>is rw</code> or <code>is copy</code> 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 parameter]]s, 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 <code>:</code> 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 <code>*</code> before the parameter name) are Raku's tool for creating [[variadic function]]s. 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: <syntaxhighlight lang="raku"> 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) </syntaxhighlight> Positional parameters, such as those used above, are always required unless followed by <code>?</code> to indicate that they are optional. Named parameters are optional by default, but may be marked as required by adding <code>!</code> after the variable name. Slurpy parameters are ''always'' optional. ====Blocks and closures==== Parameters can also be passed to arbitrary blocks, which act as [[Closure (computer science)|closures]]. This is how, for example, <code>for</code> and <code>while</code> 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, <code>$a, $b, $c</code>.<ref name="syn04">{{cite web | url=https://design.raku.org/S04.html | title=Synopsis 4: Blocks and Statements | author=Wall, Larry | date=2009-05-20 }}</ref> <syntaxhighlight lang="raku"> for @list -> $a, $b, $c { ... } </syntaxhighlight> This is generally referred to as a "pointy sub" or "pointy block", and the arrow behaves almost exactly like the <code>sub</code> keyword, introducing an anonymous closure (or anonymous subroutine in Perl terminology).<ref name="syn6"/> ===Sigil invariance=== In Perl, [[Sigil (computer programming)|''sigils'']] – the punctuation characters that precede a variable name – change depending on how the variable is used: # Perl code <!--Can't use tag "source lang" because of colorized emphasis on sigil--> my {{font color|red|@}}array = ('a', 'b', 'c'); my $element = {{font color|red|$}}array[1]; # $element equals 'b', my @extract = {{font color|red|@}}array[1, 2]; # @extract equals ('b', 'c') my $element = {{font color|red|@}}array[1]; # 'b' comes with a warning (5.10 option) In Raku, sigils are invariant, which means that they do not change based on whether it is the array or the array element that is needed:<ref name="syn2"/> <!--Can't use tag "source lang" because of colorized emphasis on sigil--> # Raku code my {{font color|red|@}}array = 'a', 'b', 'c'; my $element = {{font color|red|@}}array[1]; # $element equals 'b' my @extract = {{font color|red|@}}array[1, 2]; # @extract equals ('b', 'c') my @extract = {{font color|red|@}}array[1]; # @extract equals ('b') The variance in Perl is inspired by number agreement in English and many other natural languages: "'''This''' apple." # $a CORRECT "'''These''' apples." # @a CORRECT "'''This''' third apple." # $a[3] CORRECT "'''These''' third apple." # @a[3] WRONG However, this conceptual mapping breaks down when using [[Reference (computer science)|references]], since they may refer to data structures even though they are scalars. Thus, dealing with nested data structures may require an expression of both singular and plural form in a single term: <!-- compare the following two code blocks by using the same style syntax--> <syntaxhighlight lang="perl"> # Perl code: retrieve a list from the leaf of a hash containing hashes that contain arrays my @trans_verbs = @{ $dictionary{ 'verb' }{ 'transitive' } }; </syntaxhighlight> This complexity has no equivalent either in common use of natural language or in other programming languages,{{dubious|date=October 2015}} and it causes high [[cognitive load]] when writing code to manipulate complex data structures. This is the same code in Raku: <syntaxhighlight lang="raku"> # Raku code: retrieve a list from the leaf of a hash containing hashes that contain arrays my @trans_verbs = %dictionary<verb><transitive><>; </syntaxhighlight> ===Object-oriented programming=== Perl supports [[object-oriented programming]] via a mechanism known as ''blessing''. Any reference can be blessed into being an object of a particular class. A blessed object can have [[method (computer science)|method]]s invoked on it using the "arrow syntax" which will cause Perl to locate or "dispatch" an appropriate [[subroutine]] by name, and call it with the blessed variable as its first argument. While extremely powerful, it makes the most common case of object orientation, a [[struct]]-like object with some associated code, unnecessarily difficult. In addition, because Perl can make no assumptions about the [[object model]] in use, method invocation cannot be optimized very well. In the spirit of making the "easy things easy and hard things possible", Raku retains the blessing model and supplies a more robust object model for the common cases.<ref>{{cite web | url=https://design.raku.org/S12.html | title=Synopsis 12: Objects | author=Wall, Larry | date=2006-08-18 }}</ref> For example, a class to encapsulate a [[Cartesian coordinate system|Cartesian]] [[point (geometry)|point]] could be defined and used this way: <syntaxhighlight lang="raku"> 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 </syntaxhighlight> The dot replaces the arrow in a nod to the many other languages (e.g. [[C++]], [[Java (programming language)|Java]], [[Python (programming language)|Python]], etc.) that have coalesced around dot as the syntax for method invocation. In the terminology of Raku, <code>$.x</code> 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 <code>x</code> is in the example above. These accessor functions return the value of the attribute. When a class or individual attribute is declared with the <code>is rw</code> 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 [[Value (computer science)#lrvalue|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 <code>$!</code> 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 (Perl)|Moose]] framework that introduces many of Raku's OOP features to Perl.{{clarify|What does perl mean here? Perl5?|date=September 2020}} ====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 [[Interface (Java)|''interfaces'' in Java]], ''[[mixin]]s'' in Ruby, and ''[[Trait (computer science)|traits]]''<ref>{{cite web | title=Traits | url=http://www.iam.unibe.ch/~scg/Research/Traits/ | author=The Software Composition Group | year=2003 | access-date=22 September 2006 | archive-url=https://web.archive.org/web/20060811170712/http://www.iam.unibe.ch/~scg/Research/Traits/ | archive-date=11 August 2006 | url-status=dead }}</ref> in [[PHP]] and in the [[Smalltalk]] variant [[Squeak]]. These are much like classes, but they provide a safer composition mechanism.<ref>{{cite web| title=Day 18: Roles| url=https://perl6advent.wordpress.com/2009/12/18/day-18-roles/ | year=2009 | first=Jonathan| last=Worthington}}</ref> These are used to perform composition when used with classes rather than adding to their [[Inheritance (object-oriented programming)|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.<ref>{{cite web | title=The Why of Perl Roles | url=http://www.modernperlbooks.com/mt/2009/04/the-why-of-perl-roles.html | author=chromatic | year=2009 | author-link=chromatic (programmer)}}</ref> 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.<ref>{{Cite web|url=https://docs.raku.org/language/objects#Automatic_role_punning|title=Object orientation|website=docs.raku.org|access-date=2019-10-24}}</ref> 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 gland]]s and (through Mammal's parent, [[Vertebrate]]) a [[Vertebral column|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 [[feral|Stray]] (an abandoned pet will acquire behaviours to survive not associated with a pet), or a [[guide dog|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. <syntaxhighlight lang="raku"> class Mammal is Vertebrate { ... } class Dog is Mammal { ... } role Pet { ... } role Stray { ... } role Guide { ... } </syntaxhighlight> Roles are added to a class or object with the <code>does</code> keyword. In order to show inheritance from a class, there is a different keyword <code>is</code>. 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. <syntaxhighlight lang="raku"> class GuideDog is Dog does Guide { ... } # Subclass composes role my $dog = new Dog; $dog does Guide; # Individual object composes role </syntaxhighlight> 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|Guide Horse]], a Guide Human, or even a Guide Machine. <syntaxhighlight lang="raku"> 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 } </syntaxhighlight> ===Regular expressions=== {{Main|Raku rules}} Perl's [[regular expression]] and string-processing support has always been one of its defining features.<ref>{{cite web | url=http://cslibrary.stanford.edu/108/EssentialPerl.html#re | title=Essential Perl: String Processing with Regular Expressions | author=Parlante, Nick | year=2000}}</ref> Since Perl's pattern-matching constructs have exceeded the capabilities of [[regular language]] expressions for some time,<ref>{{cite web | url=http://www.perl.com/doc/FMTEYEWTK/regexps.html | title=PERL5 Regular Expression Description | author=Christiansen, Tom | year=1996 | quote=Perl's regexps "aren't" -- that is, they aren't "regular" because backreferences per sed and grep are also supported, which renders the language no longer strictly regular | access-date=25 March 2010 | archive-url=https://web.archive.org/web/20100331122815/http://www.perl.com/doc/FMTEYEWTK/regexps.html | archive-date=31 March 2010 | url-status=dead }}</ref> 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 "[[Raku rules|rules]]" which provide the capabilities of [[Context-sensitive language|context-sensitive]] [[parsing]] formalisms (such as the [[syntactic predicate]]s of [[parsing expression grammar]]s and [[ANTLR]]), as well as acting as a [[Closure (computer science)|closure]] with respect to their [[Scope (programming)|lexical scope]].<ref>{{cite web | url=https://design.raku.org/S05.html | title=Synopsis 5: Regexes and Rules | author=Wall, Larry | date=2009-05-20 }}</ref> Rules are introduced with the <code>rule</code> keyword which has a usage quite similar to subroutine definition. Anonymous rules can also be introduced with the <code>regex</code> (or <code>rx</code>) keyword, or they can simply be used inline as regexps were in Perl via the <code>m</code> (matching) or <code>s</code> (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".<ref>{{cite web | url=https://raku.org/archive/doc/design/apo/A05.html | title=Apocalypse 5: Pattern Matching | author=Wall, Larry | date=2002-06-04 }}</ref> ===Syntactic simplification===<!-- This section is linked from [[Ellipsis]] --> Some Perl constructs have been changed in Raku, optimized for different syntactic cues for the most common cases. For example, the parentheses (round [[bracket]]s) required in [[control flow]] constructs in Perl are now optional:<ref name="syn04"/> <syntaxhighlight lang="raku"> if is-true() { for @array { ... } } </syntaxhighlight> Also, the <code>,</code> (comma) operator is now a list constructor, so enclosing parentheses are no longer required around lists. The code <syntaxhighlight lang="raku"> @array = 1, 2, 3, 4; </syntaxhighlight> now makes <code>@array</code> an array with exactly the elements '1', '2', '3', and '4'. ===Chained comparisons=== Raku allows comparisons to "chain". That is, a sequence of comparisons such as the following is allowed: <syntaxhighlight lang="raku"> if 20 <= $temperature <= 25 { say "Room temperature is between 20 and 25!" } </syntaxhighlight> This is treated as if each left-to-right comparison were performed on its own, and the result is logically combined via the <code>and</code> operation. ===Lazy evaluation=== Raku uses the technique of [[lazy evaluation]] of lists that has been a feature of some [[functional programming]] languages such as [[Haskell (programming language)|Haskell]]:<ref name="syn9">{{cite web | url=https://design.raku.org/S09.html | title=Synopsis 9: Data Structures | author=Wall, Larry | date=2004-09-13 }}</ref> <syntaxhighlight lang="raku"> @integers = 0..Inf; # integers from 0 to infinity </syntaxhighlight> The code above will not crash by attempting to assign a list of infinite size to the array <code>@integers</code>, 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 <code>gather</code> and <code>take</code>, behaving somewhat like generators in languages like [[Icon (programming language)|Icon]] or [[Python (programming language)|Python]]. <syntaxhighlight lang="raku"> my $squares = lazy gather for 0..Inf { take $_ * $_; }; </syntaxhighlight> <code>$squares</code> will be an infinite list of square numbers, but lazy evaluation of the <code>gather</code> ensures that elements are only computed when they are accessed. ===Junctions=== Raku introduces the concept of ''junctions'': values that are composites of other values.<ref name="syn9"/> In their simplest form, junctions are created by combining a set of values with junctive [[Operator (programming)|operator]]s: <syntaxhighlight lang="raku"> # Example for | ("any") Junction: my $color = 'white'; unless $color eq 'white' | 'black' | 'gray' | 'grey' { die "Color printing not supported\n"; } # Example for & ("all") Junction: my $password = 'secret!123'; if $password ~~ /<:alpha>/ & /<:digit>/ & /<:punct>/ { say "Your password is reasonably secure"; } </syntaxhighlight> <code>|</code> indicates a value which is equal to either its left- ''or'' right-hand arguments. <code>&</code> indicates a value which is equal to both its left- ''and'' right-hand arguments. These values can be used in any code that would use a normal value. Operations performed on a junction act on all members of the junction equally, and combine according to the junctive operator. So, <code>("apple"|"banana") ~ "s"</code> would yield <code>"apples"|"bananas"</code>. In comparisons, junctions return a single true or false result for the comparison. "<code>any</code>" junctions return true if the comparison is true for any one of the elements of the junction. "<code>all</code>" junctions return true if the comparison is true for all of the elements of the junction. Junctions can also be used to more richly augment the type system by introducing a style of [[generic programming]] that is constrained to junctions of types: <syntaxhighlight lang="raku"> subset Color of Any where RGB_Color | CMYK_Color; sub get_tint(Color $color, Num $opacity) { ... } </syntaxhighlight> ===Macros=== In low-level languages, the concept of [[Macro (computer science)|macros]] has become synonymous with textual substitution of source-code due to the widespread use of the [[C preprocessor]]. However, high-level languages such as [[Lisp programming language|Lisp]] pre-dated C in their use of macros that were far more powerful.<ref>{{cite book | title=Successful Lisp: How to Understand and Use Common Lisp | author=Lamkins, David B. | date=2004-12-08 | publisher=bookfix.com | url=http://psg.com/~dlamkins/sl/chapter20.html | access-date=13 September 2006 | archive-date=12 September 2006 | archive-url=https://web.archive.org/web/20060912113327/http://www.psg.com/~dlamkins/sl/chapter20.html | url-status=dead }}</ref> It is this Lisp-like macro concept that Raku will take advantage of.<ref name="syn6"/> The power of this sort of macro stems from the fact that it operates on the program as a high-level [[data structure]], rather than as simple text, and has the full capabilities of the programming language at its disposal. A Raku macro definition will look like a subroutine or method definition, and it can operate on unparsed strings, an [[Abstract syntax tree|AST]] representing pre-parsed code, or a combination of the two. A macro definition would look like this:<ref name="macros">{{Cite web|url=https://github.com/Raku/old-design-docs|title=Raku/old-design-docs|date=10 September 2024|via=GitHub}}</ref> <syntaxhighlight lang="raku"> macro hello($what) { quasi { say "Hello { {{{$what}}} }" }; } </syntaxhighlight> 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 (computer science)|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]]".
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)