Why Raku?
say 'Hello World';
# Multiple 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
}
}
Rectangle.new(width => 5, height => 7).print_area;
# OUTPUT: Area of Rectangle is 35.
# Inifinite and lazy list
my @fib = 0, 1, * + * ... ∞;
say @fib[^11];
# OUTPUT: (0 1 1 2 3 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)
my @a = 1..4;
my @b = 'a'..'d';
# Zip two lists using Z meta operator
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)
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」
# Promise
my $promise = start {
my $i = 0;
for 1 .. 10 {
$i += $_
}
$i
}
my $result = await $promise;
say $result;
# OUTPUT: 55
# Concurrency
react {
my $current-proc;
whenever $script.watch.unique(:as(*.path), :expires(1)) {
.kill with $current-proc;
$current-proc = Proc::Async.new($*EXECUTABLE, $script);
my $done = $current-proc.start;
whenever $done {
$current-proc = Nil;
}
}
}
my $modules-load = start @files
.grep(/ \.(yaml|yml) $/)
.sort(-*.s)
.race(batch => 1, degree => 6)
.map(-> $file {
my $yaml = self!load-yaml($file, $schema, $problems);
with $yaml {
Easii::Model::Module.new(parsed => $yaml, source => $file.basename)
}
})
.eager;
# 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»
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
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
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');
}
# $ script-name
# Usage:
# script-name [--size|--length=<Int>] [--verbose] [<file>]
# [<file>] an existing file to frobnicate
# --size|--length=<Int> length/size needed for frobnication
# --verbose required verbosity
# $ raku frobnicate.raku --verbose
# 24
# file.dat
# Verbosity on
# Another example with multi MAIN
multi MAIN ('install', Str $something, Bool :$force) {
say "Installing $something {'by force' if $force}";
}
multi MAIN ('run', Str $something) {
say "Running $something";
}
# $ script-name
# Usage:
# script-name [--force] install <something>
# script-name run <something>
# $ script-name --force install raku
# Installing raku by force
# 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
=begin pod
=head1 Documenting code in C<Raku>
=item L<Raku docs|https://docs.raku.org>
=end pod
=begin pod
=head1 Red
Take a look at our Documentation: L<https://fco.github.io/Red/>
=head2 Red - A **WiP** ORM for Raku
=head2 INSTALL
Install with (you need **rakudo 2018.12-94-g495ac7c00** or **newer**):
=begin code :lang<bash>
zef install Red
=end code
=head2 SYNOPSIS
=begin code :lang<raku>
use Red:api<2>;
model Person {...}
model Post is rw {
has Int $.id is serial;
has Int $!author-id is referencing{ Person.id };
has Str $.title is column{ :unique };
has Str $.body is column;
has Person $.author is relationship{ .author-id };
has Bool $.deleted is column = False;
has DateTime $.created is column .= now;
has Set $.tags is column{
:type<string>,
:deflate{ .keys.join: "," },
:inflate{ set(.split: ",") }
} = set();
method delete { $!deleted = True; self.^save }
}
model Person is rw {
has Int $.id is serial;
has Str $.name is column;
has Post @.posts is relationship{ .author-id };
method active-posts { @!posts.grep: not *.deleted }
}
my $*RED-DB = database "SQLite";
Person.^create-table;
=end code
=begin code :lang<sql>
-- Equivalent to the following query:
CREATE TABLE person(
id integer NOT NULL primary key
AUTOINCREMENT,
name varchar(255) NOT NULL
)
=end code
=begin code :lang<raku>
Post.^create-table;
=end code
=begin code :lang<sql>
-- Equivalent to the following query:
CREATE TABLE post(
id integer NOT NULL primary key AUTOINCREMENT,
author_id integer NULL references person(id),
title varchar(255) NOT NULL,
body varchar(255) NOT NULL,
deleted integer NOT NULL,
created varchar(32) NOT NULL,
tags varchar(255) NOT NULL,
UNIQUE (title)
)
=end code
=begin code :lang<raku>
my Post $post1 = Post.^load: :42id;
=end code
=begin code :lang<sql>
-- Equivalent to the following query:
SELECT
post.id,
post.author_id as "author-id",
post.title,
post.body,
post.deleted,
post.created,
post.tags
FROM
post
WHERE
post.id = 42
=end code
=end pod
use v6.c;
# TODO: Add operator, slang, macro examples
say Date.today.year;
# Output: 2020
say Date.today.later(:2years).year;
# Output: 2022
# TODO: Add more examples
sub add (Int $a, Int $b) {
$a + $b
}
add 'string';
# ===SORRY!=== Error while compiling error.raku
# Calling add(Str) will never work with declared signature (Int $a, Int $b)
# at file.raku:5
# ------> <BOL>⏏add 'string';
Resources
Guides
Courses
Examples
Books
New to programming?
Try Online
Coming from another programming language?
If you are coming from another programming language, these documentations 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