← History

The Sigil Lineage: Perl, Raku, and guji

How the $, @, % sigils travelled from Perl's variant punctuation to Raku's invariant names to guji's shape-typed bindings.

PerlRakuguji

The Sigil Lineage: Perl, Raku, and guji

A sigil is the little glyph in front of a variable name — $, @, % — that tells you, at a glance, what kind of thing you are looking at. Three languages in one family treat those glyphs very differently, and the differences turn out to be a tidy parable about how language design learns from itself. This is the story of the sigil from Perl to Raku to guji.

Perl: sigils that shimmer

Larry Wall released Perl 1.0 to the comp.sources.misc Usenet newsgroup on December 18, 1987. He borrowed the sigil idea from the Unix shell — $var was already how sh and awk named values — but Perl extended it into a small type system you wear on your sleeve: $ for scalars, @ for arrays, % for hashes (plus & for subs and * for typeglobs).

The catch, and the thing that made Perl famous and infamous in equal measure, is that in Perl 5 the sigil describes the access, not the container. The sigil shimmers depending on what you pull out:

my @array = (10, 20, 30);
my %hash  = (ada => 30);

print "$array[0]\n";   # 10   — a SCALAR element, so the sigil is $
print "$hash{ada}\n";  # 30   — a SCALAR element, so the sigil is $
print "@array\n";      # 10 20 30 — the whole ARRAY, so the sigil is @

Read that twice: you index into @array, but you write $array[0], because the single thing you get back is a scalar. The reasoning is internally consistent — "any one value is a scalar, so it wears $" — but it means you cannot tell from the sigil alone which variable a fragment refers to; you have to read the brackets too. The sigil tells you the shape of the result, and the brackets tell you the shape of the source, and you reconcile them in your head.

Perl leaned into this expressive density on purpose. As Wall wrote in the glossary of the first Programming Perl (1991):

"The three chief virtues of a programmer are: Laziness, Impatience and Hubris."

Variant sigils are a very lazy-in-the-good-sense idea: one symbol, $, marks "a single value" no matter where it came from. But the cognitive bill comes due when you read other people's code.

Raku: the sigil becomes part of the name

When the language that became Raku was designed (begun in 2000 as "Perl 6," and formally renamed to Raku in October 2019, with Larry Wall's blessing), one of the deliberate corrections was to make the sigil invariant. In Raku the sigil is part of the variable's name and never changes, however you access it:

my @array = 10, 20, 30;
my %hash  = ada => 30;

say @array[0];   # 10  — the container is @array, so the sigil stays @
say %hash<ada>;  # 30  — the container is %hash, so the sigil stays %
say @array;      # [10 20 30]

The container keeps its sigil whether you take the whole thing or one element. @array[0] instead of $array[0]; %hash<ada> instead of $hash{ada}. You can now read a sigil-name as a single token and know exactly which binding it points to. Raku kept the vocabulary of Perl's sigils but fixed their grammar: the glyph stopped being a description of the result and became a stable label on the declaration. Everything else about the family resemblance — the punctuation, the data-type trinity — stayed put.

guji: sigils as a shape type

guji is a statically-typed, functional-first, compiled language whose signature strength is first-class text processing — regular expressions and PEG grammars are language primitives, not libraries. It inherits the three sigils directly, and it inherits Raku's invariance rule and sharpens it into a type-system idea.

In guji the sigil declares the broad shape of a binding and is, in the spec's word, "invariant: it never changes regardless of how the value is accessed." There are exactly three, and only three:

Sigil Shape Example
$ scalar $count = 3
@ list @items = [1, 2, 3]
% map %ages = {"ada": 30}

Crucially, accessing an element keeps the container's sigil, exactly as in Raku — but guji adds a separate static type underneath the sigil:

@items = [10, 20, 30]
@items[0]            # 10  — sigil stays @, and the type is Int
%ages = {"ada": 30}
%ages{"ada"}         # 30  — sigil stays %, and the type is Int

The sigil and the type are two different layers doing two different jobs. The sigil says "this is a list"; the inferred static type says "…of Int," i.e. @items : List[Int], so @items[0] : Int. A Perl programmer used to the sigil being the type information will find this liberating: the sigil now carries only the coarse shape, and a real, checked type system carries the precision.

That separation pays off in string interpolation, which all three languages share as a sigil-driven feature. In guji a sigil-name interpolates directly, and { … } interpolates an arbitrary expression:

$name = "ada"
@scores = [10, 20]
"hi $name, scores: @scores, total: { @scores.sum() }"
# => "hi ada, scores: [10, 20], total: 30"

(Every line above is real; guji's v0 evaluator prints exactly that string.)

Because guji is functional-first and immutable-by-default, the sigil also quietly reinforces the language's "one obvious way" principle. Lists and maps are the only two compound bindings that get their own sigil; everything else — an Int, a Str, a class instance, an Option, even a function value — is a scalar $. So the data-first method chains that guji favours read with a single, stable list sigil from start to finish:

@nums = [1, 2, 3, 4, 5, 6]
@nums.filter({ $_ % 2 == 0 }).map({ $_ * 2 }).sum()
# => 24

The @ never wavers as the pipeline transforms the list, and the topic variable $_ inside each lambda is a scalar, so it wears $. The same discipline shows up in match, guji's exhaustive pattern-matching expression, where bound captures are scalars:

$desc = match $n {
    0            { "zero" }
    $x if $x < 0 { "negative" }
    _            { "positive" }
}

What the lineage teaches

Trace the $ across thirty-odd years and you watch one idea get progressively disambiguated:

The glyphs are nearly unchanged from 1987. What changed is the promise they make. Perl's sigil whispered "here is the shape of what you're about to get." Raku's and guji's sigils declare, plainly and permanently, "here is what this binding is." That is the whole arc of the lineage: the same three marks, asked to mean exactly one thing each.