Variables and Sigils
If you have programmed in Perl, you already know about sigils: those little symbols at the start of variable names. Raku takes the concept and refines it. If you are new to sigils altogether, do not worry. They are one of Raku's most practical features, and once they click, you will wonder how you ever lived without them.What Are Sigils?
A sigil is the symbol prefix on a variable name. In Raku, there are three main sigils:$for scalars (single values)@for arrays (ordered lists)%for hashes (key-value mappings)
The sigil tells you at a glance what kind of container a variable is. This is not just decoration; it affects how Raku handles the variable in context.my $name = "Alice"; # scalar: a single string my @colors = <red green blue>; # array: a list of values my %ages = alice => 30, bob => 25; # hash: key-value pairs
Scalars ($)
A scalar holds a single value of any type: a string, a number, an object, even another array or hash (as a single reference).Raku allows hyphens and apostrophes in identifier names (as long as they are followed by a letter). This means you can write natural-looking names:my $greeting = "Hello, World!"; my $answer = 42; my $pi = 3.14159; my $is-raku = ; # Boolean (yes, hyphens are allowed in names!) say $greeting; # Hello, World! say $answer * 2; # 84
my $first-name = "Grace"; my $don't-panic = "Keep calm"; say $first-name; # Grace say $don't-panic; # Keep calm
Arrays (@)
Arrays hold ordered sequences of values. You can create them in several ways:The angle-bracket syntaxmy @nums = 1, 2, 3, 4, 5; my @words = <hello world foo bar>; # quote-words syntax (splits on whitespace) my @mixed = "text", 42, , 3.14; # mixed types are fine say @words[0]; # hello say @words[1]; # world say @nums.elems; # 5
< > is a convenient shorthand for creating a list of strings without needing quotes and commas.
Sigil Invariance
Here is a key difference from Perl 5. In Raku, the sigil does not change when you access a single element. A single element of@array is still accessed with @array[0], not $array[0]:
In Perl 5, you would writemy @fruits = <apple banana cherry>; say @fruits[0]; # apple (still uses @, not $) say @fruits[1]; # banana
$fruits[0]. Raku keeps the sigil consistent with the variable declaration. This is called sigil invariance and it makes code easier to read because the sigil always tells you which variable you are working with.
Hashes (%)
Hashes store key-value pairs. Keys are strings by default:Notice we usemy %config = host => "localhost", port => 8080, debug => ; say %config<host>; # localhost say %config<port>; # 8080
< > for string keys (not { } like Perl 5, though { } also works for computed keys):
my %data = name => "Bob", score => 95; # String key with < > say %data<name>; # Bob # Computed key with { } my $key = "score"; say %data{$key}; # 95
Declaration with my, our, and has
my declares a lexically scoped variable (visible only in the current block):
my $x = 10; if { my $y = 20; say $x + $y; # 30 } # say $y; # ERROR: $y is not defined here
our declares a package-scoped variable (visible to other code in the same package):
our $version = "1.0";
has is used inside classes for attributes (we will cover classes in a later tutorial).
Binding with :=
Raku distinguishes between assignment (=) and binding (:=).
Assignment copies a value into a container:
Binding makes one variable an alias for another:my $a = 42; my $b = $a; # $b gets a copy of 42 $b = 99; say $a; # still 42
Binding is also used to create constants and for some advanced patterns. You will see it more as you progress.my $a = 42; my $b := $a; # $b is now the same container as $a $b = 99; say $a; # 99 (because $b and $a are the same thing)
Twigils
Twigils are secondary sigils that appear between the main sigil and the variable name. They indicate the variable's scope or origin:Let us look at a couple of practical examples:$*PROGRAM # * = dynamic/global variable (the current program name) $?FILE # ? = compile-time variable (current file) $.attribute # . = public attribute accessor (in classes) $!private # ! = private attribute (in classes) $^param # ^ = placeholder parameter (in blocks) $:named # : = named parameter (in blocks)
# Dynamic variables with * say $*PROGRAM; # path to the current script say $*CWD; # current working directory say $*USER; # current user (on supported platforms) # Compile-time variables with ? say $?FILE; # current file name say $?LINE; # current line number
Placeholder Parameters (^)
The^ twigil creates implicit parameters for blocks, sorted alphabetically:
my @nums = 3, 1, 4, 1, 5; my @sorted = @nums.sort({ $^a <=> $^b }); say @sorted; # [1 1 3 4 5] # $^a and $^b become the first and second parameters # because a comes before b alphabetically
Type Constraints
You can optionally constrain what type of value a variable holds:This is completely optional. Raku is gradually typed: you can add types where you want safety and leave them off where you want flexibility.my $count = 0; my $name = "Raku"; my $pi = 3.14e0; # $count = "hello"; # ERROR: Type check failed $count = 42; # fine
Undefined Values and Any
A declared but unassigned variable holds a type object, which is undefined:You can check for definedness withmy $x; say $x.defined; # False say $x.WHAT; # (Any) $x = 42; say $x.defined; # True
.defined or the with keyword (covered in the control flow tutorial).
Putting It All Together
Output:#!/usr/bin/env raku # Scalars my $project = "Raku Tutorial"; my $version = 1; # Array my @topics = <variables sigils twigils binding>; # Hash my %metadata = author => "Your Name", lang => "Raku", level => "beginner"; say "Project: $project v$version"; say "Topics: @topics.join(', ')"; say "Author: %metadata<author>"; say "We will cover { @topics.elems } topics today.";
Project: Raku Tutorial v1 Topics: variables, sigils, twigils, binding Author: Your Name We will cover 4 topics today.