Perhaps I'm just use to C-esque styled languages but having a sigil in front of a variable (e.g. $VAR) always strikes me as weird.


Why do some languages such as Perl and shell scripting have sigils in front of the variable names?

I can see it making sense for older languages like Basic (1960s) where the interpreter might not be smart enough to know what type of variable we are referring to. Looking at C in the 1970s, we see that is all but gone. In the 1980s, shell and Perl appeared and use the sigil notation yet Tcl, Erlang and others like C++ don't. In the 1990s, we see Python and Ruby not having sigils at all. Perhaps they do exist, but I haven't seen a recently developed programming language use sigils. I have, however, seen language do other stuff such as decorators from python @staticmethod that can look like sigils but is used in a different context.

I don't code a lot in Perl but for bash, printf is a function and wrapped in a command substitution, $(printf ...) creates sprintf from C. With both of these options, I don't see gains of say using "This ${magic}String" over printf "This %sString" "$magic" especially when strings get really long. Similarly, ${#STR} is confusing, especially to newer programmers that don't know what that piece of code does, whereas len str is easier to read. Perhaps I'm just nitpicking over something that doesn't matter and everyone just accepts and moves on.

  • 1
    For one, it eliminates conflicts between variable names and language reserved words. It also makes it very clear what is a variable and what is not when reading code. For languages with very few variable types, like perl, it even tells you the (guaranteed) type of the variable. – xaxxon Mar 24 '16 at 6:58
  • To make also the difference between the name (x as a symbol or string) of a variable and the value of a variable ($x the value of x) – Pascal Fares Mar 24 '16 at 8:23
  • 1
    In the case of shell scripts, the name of an executable file is also the command to run it. Given the token foo in a shell script, it's really helpful to know if it's a variable or command name. – Simon B Mar 24 '16 at 9:05
  • if you type 'ls foobar' at a command prompt, how else would bash know whether foobar is a variable or the name of a file, particularly in the case where both a variable and a file of that name exists? – Bryan Oakley Mar 24 '16 at 11:13
  • @BryanOakley As for filenames you could add ./ to clarity that it's a file. As for commands, you could use $(cmd) to clarify them but I suppose that in other languages, it's not as clear, or requires some call like cmd(...). Both require more typing which I suppose takes more effort than a sigil character. – unsignedzero Mar 24 '16 at 19:49

In the 1990s, we see Python and Ruby not having sigils at all.

Ruby doesn't have sigils? Ruby is the king of sigils!

  • $ is a global or pseudo-global variable,
  • @ is an instance variable,
  • @@ is a class hierarchy variable, and
  • (not technically a sigil, but similar in spirit) an uppercase letter is a constant variable.

And in the two cases where there isn't a sigil, there is an ambiguity between variables and methods:


is that a method call or a variable? Ruby says: both! If it has parsed (not executed) an assignment before, it assumes, it's local variable, otherwise it assumes, it's a method call. So:

foo # method call

if false
  foo = 42 # it doesn't matter that this isn't executed, only parsed

foo # local variable
# => nil
# un-initialized local variables evaluate to nil

Okay, and what if I want to call a method named foo now? Well, I need to make it clear to Ruby that I intend to call a method:

foo() # pass an argument list, only methods can take arguments

self.foo # provide an explicit receiver, however doesn't work for private methods

This poses another problem: if I have a function assigned to a variable, how do I call that function? I can't do it with foo(), because that calls a method named foo, I have to say foo.().

For constants, the situation is similar. Foo is always interpreted as a constant, in order to treat it as a method call, you have to say Foo() or self.Foo.

In Python, this ambiguity is resolved by always requiring an explicit receiver for anything which isn't a variable, and always requiring parentheses for calls. So, a local variable is always foo, a method call is always self.foo(), and calling a function stored in a local variable is always foo(). An instance variable is always self.foo.

ECMAScript solves it by having a single namespace for functions and variables, so that it is impossible to have both a function and a variable named foo:

let foo = 42;

function foo() {};
// TypeError: Identifier 'foo' has already been declared
  • I guess I should use RUby a bit more and learn about that. – unsignedzero Mar 24 '16 at 19:38

In shell, where you have shell scripts, with an environment that can be manipulated by the caller of the script, it's really really useful if you can distinguish between "this is a variable reference" and "this is text" without having to consult the environment.

If any "defined variable" would be substituted for its value, the following would not be safe in a shell script:

ls /tmp/*

Because if you wanted that to become harmful, all you would need would be to do the following:

export ls

So having some sort of distinct signal saying "yes, this is fetching the value of a variable" is very useful.

Perl (probably) got this from shell, but extended it to use various prefix symbols to denote data types, so $foo is a scalar variable, but @foo is an array variable.

  • Even more evil: ls=rm; tmp="/"; – Jörg W Mittag Mar 24 '16 at 11:50
  • I don't believe this is one of the reasons variables are prepended with "$". Simply because you CAN replace commands with "alias". Example "alias ls=rm". – user161778 Mar 28 '16 at 3:18
  • @user161778: Note that an alias is NOT inherited through the normal environment (thus the need to define them in .bashrc). – Vatine Mar 29 '16 at 16:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.