Why Raku?
Say hello to the world!
# human-readable string with newline. Calls the gist method.
say 'Hello World';
# string representation without newline. Calls the Str method.
print 'Hello, World!', "\n";
# hybrid of say (adds newline) and print (calls Str method).
put 'Hello, World';
Using multi-dispatch, classes, and roles with a nice and familiar syntax.
# Multi-dispatch
multi sub fib( 0 --> 0 ) {}
multi sub fib( 1 --> 1 ) {}
multi sub fib( \n where * > 1 ) {
fib(n - 1) + fib(n - 2)
}
say fib 10; # OUTPUT: «55»
# Roles and classes
role Shape {
method area { ... }
method print-area {
say "Area of {self.^name} is {self.area}.";
}
}
class Rectangle does Shape {
has $.width is required;
has $.height is required;
method area {
$!width * $!height
}
}
my $obj = Rectangle.new(width => 5, height => 7);
$obj.print-area; # OUTPUT: «Area of Rectangle is 35.»
Lazy lists, infinite sequences, junctions and feed, function composition, meta and hyper operators.
# Infinite and lazy list
my @fib = 0, 1, * + * ... ∞;
say @fib[^6]; # OUTPUT: «(5 8 13 21 34 55)»
# Feed operator
@fib[^20]
==> grep(&is-prime)
==> say(); # OUTPUT: «(2 3 5 13 89 233 1597)»
# Function composition
my &reverse-primes = &reverse ∘ &grep.assuming(&is-prime);
say reverse-primes ^20; # OUTPUT: «(19 17 13 11 7 5 3 2)»
# Zip two lists using Z meta operator
my @a = 1..4;
my @b = 'a'..'d';
say @a Z @b; # OUTPUT: «((1 a) (2 b) (3 c) (4 d))»
say @a Z=> @b; # OUTPUT: «(1 => a 2 => b 3 => c 4 => d)»
# Hyper Operators
say @b «~» @a; # OUTPUT: «[a1 b2 c3 d4]»
# Junctions
say 'Find all the words starting with a lowercase vowel'
.words.grep: *.starts-with: any <a e i o u>; # OUTPUT: «(all a)»
Grammars for easily parsing data with new re-thought regular expressions.
grammar INIParser {
token TOP { <block> <section>* }
token section { <header> <block> }
token header { '[' ~ ']' \w+ \n+ }
token block { [<pair> | <comment>]* }
rule pair { <key> '=' <value> }
token comment { ';' \N* \n+ }
token key { \w+ }
token value { <-[\n ;]>+ }
}
my $match = INIParser.parse: q:to/END/;
; Comment
key1=value1
key2 = value2
; Section 1
[section1]
key3=value3
END
say $match<block><pair>[0]<value>; # OUTPUT: «「value1」»
say $match<section>[0]<block><pair>[0]<value>; # OUTPUT: «「value3」»
Using Promise, Supply, Channel types and supply, react and whenever blocks.
# Promise
my $promise = start {
my $i = 0;
for 1 .. 10 {
$i += $_
}
$i
}
my $result = await $promise;
say $result;
# OUTPUT: 55
# Supply
my $bread-supplier = Supplier.new;
my $vegetable-supplier = Supplier.new;
my $supply = supply {
whenever $bread-supplier.Supply {
emit("We've got bread: " ~ $_);
};
whenever $vegetable-supplier.Supply {
emit("We've got a vegetable: " ~ $_);
};
}
$supply.tap(-> $v { say "$v" });
$vegetable-supplier.emit("Radish");
# OUTPUT: «We've got a vegetable: Radish»
$bread-supplier.emit("Thick sliced");
# OUTPUT: «We've got bread: Thick sliced»
$vegetable-supplier.emit("Lettuce");
# OUTPUT: «We've got a vegetable: Lettuce»
Full Grapheme based unicode support.
say '🦋'.chars; # OUTPUT: «1»
say '🦋'.codes; # OUTPUT: «1»
say '🦋'.encode.bytes; # OUTPUT: «4»
my $raku = 'راکو';
say $raku.chars; # OUTPUT: «4»
say $raku.uninames; # OUTPUT: «(ARABIC LETTER REH ARABIC LETTER ALEF ARABIC LETTER KEHEH ARABIC LETTER WAW)»
say $raku.comb; # OUTPUT: «(ر ا ک و)»
say +$raku.comb; # OUTPUT: «4»
Optional gradual typing and native data types.
sub static( Int $a, Int $b -> Int ) {
$a + $b
}
sub dynamic( $a, $b ) {
$a + $b
}
say static(2, 5); # OUTPUT: «7»
static(2, 'oops'); # ERROR: ... will never work with declared signature ...
say dynamic(<a b>, <c d>); # OUTPUT: «4»
dynamic(2, 'oops'); # ERROR: Cannot convert string to number ...
# Subsets
subset ℕ of Int where * > 0;
sub f( ℕ $a, ℕ $b --> Array of ℕ ) {
Array[ℕ].new: $a², $b²;
}
say f 1, 2; # OUTPUT: «[1 4]»
# Native types
my int @a = ^10_000_000;
say [+] @a; # OUTPUT: «49999995000000»
Easy command-line interface, accessible by MAIN subroutine with multiple dispatch and automated usage message generation.
# An example with a single subroutine MAIN
sub MAIN(
Str $file where *.IO.f = 'file.dat', #= an existing file to frobnicate
Int :size(:$length) = 24, #= length/size needed for frobnication
Bool :$verbose, #= required verbosity
) {
say $length if $length.defined;
say $file if $file.defined;
say 'Verbosity ', ($verbose ?? 'on' !! 'off');
}
=begin comment
# Usage message:
$ script-name
Usage:
script-name.raku [--size|--length=<Int>] [--verbose] [<file>]
[<file>] an existing file to frobnicate
--size|--length=<Int> length/size needed for frobnication
--verbose required verbosity
# Usage:
$ raku script-name.raku --verbose
24
file.dat
Verbosity on
=end comment
# An example with multiple subroutines MAIN
multi MAIN(
'install',
Str $something,
Bool :$force
) {
say "Installing $something {'by force' if $force}";
}
multi MAIN(
'run',
Str $something
) {
say "Running $something";
}
=begin comment
# Usage message:
$ script-name.raku
Usage:
script-name [--force] install <something>
script-name run <something>
# Usage:
$ script-name.raku --force install raku
Installing raku by force
=end comment
Interfacing with C/C++ via NativeCall. Also use other languages within Raku via Inline::* modules.
# Using NativeCall to access libnotify and show a notification
use NativeCall;
sub notify_init( str $appname --> int32 ) is native('notify') { * }
sub notify_uninit is native( 'notify' ) { * }
class NotifyNotification is repr('CPointer') { * }
sub notify_notification_new(
str $summary, str $body, str $icon --> NotifyNotification
) is native('notify') { * }
sub notify_notification_show( NotifyNotification ) is native('notify') { * }
if notify_init 'MyApp' {
notify_notification_show
notify_notification_new 'My Notification', 'Notification Body', Str;
notify_uninit;
}
# Using Inline::Python to access python and its libraries
use Inline::Python;
my $py = Inline::Python.new();
$py.run('print("hello world")'); # OUTPUT: «hello world»
# Or
say EVAL('1+3', :lang<Python>); # OUTPUT: «4»
use string:from<Python>;
say string::capwords('foo bar'); # OUTPUT: «Foo Bar»
Specify which version of the language to use.
# Language version
use v6.c;
# Module version
Define your own functions, operators, traits and data-types.
# TODO: Add operator, slang, macro examples
Large selection of available data-types and operators.
say Date.today.year;
# Output: 2020
say Date.today.later(:2years).year;
# Output: 2022
# TODO: Add more examples
Nice compile-time and run-time error messages.
sub add (Int $a, Int $b) {
$a + $b
}
add 'string';
# ===SORRY!=== Error while compiling error.p6
# Calling add(Str) will never work with declared signature (Int $a, Int $b)
# at file.p6:5
# ------> <BOL>⏏add 'string';
File-related input/output operations via the IO::Handle and IO::Path types.
# Reading from a file
# get a file handle for reading
my $fh = open "testfile", :r;
# get a file's contents
my $contents = $fh.slurp;
# close the file handle
$fh.close;
# alternatively, do everything at once by letting
# `slurp` to open and close the file for you
$contents = slurp "testfile"
# Writing to a file
# get the file handle for writing
$fh = open "testfile", :w;
# print content into file
$fh.say("New content with newline.");
# close the file handle
$fh.close;
# alternatively, do everything at once by letting
# `spurt` to open and close the file for you.
spurt "testfile", "More data\n", :append;
Resources
Guides
Books
New to programming?
Coming from another programming language?
If you are coming from another programming language, the Migration guides may be of help to you:
Python,
JavaScript,
Ruby,
Haskell,
Perl
If you want to use other programming languages and their libraries inside Raku, you can use Inline::* modules, such as:
Inline::Python,
Inline::Perl,
Inline::Go,
Inline::Ruby,
Inline::Lua
Community
- IRC: #raku, logs
- Matrix:
- Room: #freenode_#raku:matrix.org
- Community: +raku:matrix.org
- Proprietary:
- Discord: Raku server
Social Media