1. 37
    1. 11

      I think a better analogy for variable sigils is noun inflections. Indeed there is a direct parallel between @ and plural markers like English’s -s:

      • They can add information. For example if you say “my apples” you’re conveying the information that you have at least 2 apples. In Raku (and Perl) if you declare a variable with @ you’re saying there are multiple items (which could be 0 or 1 item).

      • When they don’t add information they are still required. For example, in “two apples” the -s adds no new information, but it is still required (“two apple” is ungrammatical). In Raku (and Perl) you always have to refer to a variable with the sigil, even when the name itself is unambiguous. (As the article said it’s possible to create sigilless variables, but the “social norm” is such that you’ll use sigils).

      I find the analogy with $day_job and #hashtag a bit flawed, because the sigils in $day_job and #hashtag definitely add information, while Raku sigils don’t always do that.

      Noun inflections are not strictly necessary, and personally, as someone building a language with the $ sigil (shameless plug for Elvish) I think sigils make much more sense in languages that also support unquoted strings (also known as barewords): you need a sigil to disambiguate echo PATH and echo $PATH.

      Perl has unquoted strings (even though long deprecated) so need sigils too. AFAIK Raku doesn’t support unquoted strings, but it inherited the sigil system from Perl (albeit a somewhat rationalized version, for example indexing @a is @a[1], not $a[1]).

      All these said, if you grow up speaking a language with noun inflections, you’ll find it weird to not have them. Indeed if you look at recent artificial languages (human languages, not programming languages) invented by Europeans, they tend to have very few inflections except for a plural suffix, despite it being more rational to do away with all inflections (and use a word meaning “multiple” to make the distinction when absolutely necessary). I feel the author and many other Raku and Perl users probably have a similar relationship with sigils. I don’t mean this in a bad way: programming languages don’t have to be 100% rational, they can have quirky cultural attributes that appeal to some but not everyone.

      1. 4

        I like this take. I would say, the justification for $a[0] is that the sigil is for the output, not the input — i.e., you get a scalar output value with $a[0], unlike @a[0, 2, 5] which gives you a list. This is analogous to “my first apple”: it’s derived from “my apples” but the noun inflection shows what is “returned”.

      2. 0

        Reminds me of Lingua Romana Perligata - maybe if you have a properly inflected language then you can abandon sigils…

    2. 9

      I feel like it’s gone on long enough without anyone mentioning that I have to jump in here. In shell, $ doesn’t signify a variable, $ is an operator which returns the value of the variable expansion. This is why, for example, you don’t pass names with a $ to unset, and why you don’t put $ in front of a variable when you declare it.

      This doesn’t apply to all the languages discussed (of course), just want to be clear that shell stands a bit apart here.

      All the best,

      1. 1

        In shell, $ doesn’t signify a variable, $ is an operator which returns the value of the variable expansion.

        That’s not quite true. An operator should combine with any type of operand, yet in most shell languages you can’t do $"PATH" or $$x (where $x is PATH). Fish supports the latter but not the former, and Elvish (shameless plug) supports the former but not the latter.

        Thinking $ as a “get variable value operator” is a good mnemonic device to remember where it is needed and where it isn’t, but it’s not correct. Instead, $name should be understood as a single unit, like how 0x1234 in C is a single unit, not a “hexification operator” 0x applied to 1234.

    3. 3

      The examples in “2. Raku with sigils” are @foo[5] %foo<key> &foo() but the reader seems to get the same context from just foo[5] foo<key> or foo(). Other languages have no problems with interpolation without sigils. I’m not going to avoid a language because it has these but they don’t seem to add much value.

      1. 1

        I agree that the sigil in @foo[5] doesn’t communicate anything. The point I was attempting to make is that the sigil in @foo communicates that I can write @foo[5] (or other code that expects to be handed an ordered, numerically-index-able collection). Does that make a bit more sense/seem more useful?

        1. 1

          As an author the IDE knows the context so the sigil is not providing much added value. As a reader the text after the variable provides the context and the IDE has it also.

          1. 4

            Regardless of the merits of sigils or not (I am not personally convinced but can see why others would hold such an opinion) it is important for conversations about languages to by upfront about whether there is a separation between the programming language from the IDE.

            For many programmers, there is no separation: languages that do not have IDE autocomplete are useless. For some programmers the IDE is fundamentally divorced from the language. C didn’t need an IDE. But then Java absolutely does. Unison takes it one step further essentially has a coding assistant running at all times that you ask questions of to figure out what you want to do.

            TL;DR I think the OP is not considering IDEs in the conversation and you are, and this leads to different conclusions neither of which is necessarily off-base.

            1. 1

              Good point. In the walled off context the author sets they make their point. Considering sigils in the wider context of programming practice includes IDEs and I don’t see as Raku an academic research project language.

          2. 2

            Even if your IDE can show you context on a mouse-over, isn’t there a little value in a compact (just a single character), mandatory (at least in Perl) type indicator which you can always see? The nice thing about sigils is that they’re there whether you use ed, print out your code, or just have your hands off the keyboard and mouse.

    4. 2

      The difference between #tag or @user to php’s $var, is that the first were intended as markup augmentation, whereas $var was only added to aid the parser and keep its implementation simple, and doesn’t provide the reader with any extra information. It can be summed up as “useful syntax is good, useless syntax is bad”.

      The problem with using sigils to distinguish types, is that it limits the user to a small number of predefined types. For some DSLs, such a limitation might even be a positive, but for a general-purpose programming language, I think a more abstract approach is necessary, to accommodate all the likely use-cases.

      1. 2

        whereas [PHP]’s $var was only added to aid the parser and keep its implementation simple, and doesn’t provide the reader with any extra information. It can be summed up as “useful syntax is good, useless syntax is bad”.

        Without commenting on PHP (I haven’t used it enough to do so), I’d agree that if a sigil “doesn’t provide the reader with any extra information”, then that sigil is unhelpful (except maybe for interpolation). Raku’s sigils do provide extra information about the variable’s interface/iteration style as detailed in the post.

        using sigils to distinguish types… limits the user to a small number of predefined types.… For a general-purpose programming language, I think a more abstract approach is necessary, to accommodate all the likely use-cases.

        100% agree. The “more abstract approach” that Raku uses is to break the link between sigil and type and instead link sigils to what interface the type provides (basically the same move that generic functions with syntax like Rust’s impl trait use). See the “How Raku uses sigils” in the post for details

        1. 2

          The “more abstract approach” that Raku uses is to break the link between sigil and type and instead link sigils to what interface the type provides

          Doesn’t change anything. Now you have a fixed number of possible interfaces and can’t add any more.

          1. 1

            That’s entirely a correct and a great point.

            However, it turns out I was mistaken aboutthe semantics of Raku’s sigils, and the actual semantics avoid that flaw. (I don’t know, but I suspect that point you raised might be the reason Raku has those semantics.)

            See the followup post for details.

      2. 1

        $var was only added to aid the parser and keep its implementation simple, and doesn’t provide the reader with any extra information.

        I’m not one for defending PHP with its many flaws, and it might have been true originally that it didn’t have any usefulness, but I remember you can do things like $$foo which would be identical to $bar if $foo contained the string "bar". So the $ is a bit like the * for pointer dereferencing in C. And of course in strings you can interpolate variables like "blabla $foo".

        1. 2

          Even if that’s the case (it’s been very long since I read php code), the first $ still wouldn’t be useful, unless you could remove it to access the pointer itself.

        2. 1

          you can do things like $$foo which would be identical to $bar if $foo contained the string “bar”. So the $ is a bit like the * for pointer dereferencing in C.

          This would make sense if foo was equivalent to "foo", but that’s not the case in PHP.

        3. 1

          Here is what this looks like in perl: https://perldoc.perl.org/perlref

    5. 2

      I don’t mind sigils. What I do mind is when language server has no support for inspecting them. When I see a new sigil, I click on it and want to read a textual description of what it does.

      let a = work()?;
      

      or

      class A {
        #name;
      }
      
    6. 2

      @codesections, a bug report about the website’s formatting, not its content:

      The spans of text with background-color: aliceblue; seem to cover more text than intended. For example, in this paragraph:

      We had that problem at  $day_job: our code was a mess, but everyone thought $framework  would magically fix it.

      This whole phrase is colored:

      $day_job: our code was a mess, but everyone thought $framework

      These colored spans always begin and end with a code element, so maybe some parser in your stack has a bug that makes it greedily select all text on a line between the first and last code delimiter.

      1. 1

        I’m glad to see the formatting bug has been fixed.

    7. 2

      I think that Raku sigils are an excellent first step to reintroducing Hungarian notation to the software development universe. Things have only gone downhill since we stopped using “m_” prefixes for all of our fields, and the fact that developers do not prepend “lpsz” to all of their string variables has led to numerous airline crashes and a failed NASA mission to Mars. /s

      In all seriousness, this has to be the least serious blog post that I’ve seen in a while. It is arguing for a return to the late 1980s, when Raku née Perl was still cool, and long before the invention of intelligent IDEs and the modern compiler.

      (And I say this as a huge proponent of Hungarian notation – back before IDEs learned how to convey information in color and with contextual helpers.)

      1. 7

        It is arguing for a return to the late 1980s, when Raku née Perl was still cool, and long before the invention of intelligent IDEs and the modern compiler.

        I’m a bit disappointed by this comment; one of my main goals with the post was to explain why sigils (implemented well) are valuable in ways that are entirely orthogonal to IDEs. If the above was your takeaway, then the post failed to communicate it’s central claim. And that’s a shame.

        (Maximally condensed argument for IDEs and sigils being orthogonal: IDEs give types; sigils enforce and express generic type constraints.

        Slightly less condensed version: IDEs give type info; sigils tell (and enforce) which interface it implements. Going from type → interface is possible, but often involves flow-breaking non-local context, especially for library types. Sigils also let you express intent about whether iterating a variable should flatten, which is otherwise hard to express at the variable level (rather than the type level).)

        1. 1

          I got that from reading the article, but it still felt unnatural to me (cost/benefit). So perhaps you’re conveying well what you wanted to convey, but I’m not appreciating the value of the result in the same way that you are. There are several possibilities as to why that could be, but it probably boils down to one of: (1) we value specific benefits differently, and (2) we have different expectations from, or assumptions about, the state of the art.

    8. 1

      I find Elixir’s use of sigils to be intuitive and helpful.

    9. 1

      I like sigils quite a lot, though they do seem rare.

      I do think they’re quite different from namespaces (and the operator-like things we use to refer to different namespaces, like LISP’s ’quote and #‘function-quote), since $foo and @foo are both meaningful for a singular foo. So it’s not quite Hungarian notation.

      I do think JavaScript has an important sigil: …list gives you the contents of the list instead of the list as a singular value. I think that counts as a sigil.

      I would also maybe argue that what Elixir calls sigils are really just a good set of reader macros.

    10. 1

      (The primary language discussed in this post is Raku, which lacks a tag. I added the apl tag because the post draws an extended contrast between APL and Raku; if that’s not APL-related enough, please let me know and I’ll remove the tag.)

      1. 4

        How about tagging it perl?

        1. 2

          I considered that, but the post only briefly mentions Perl. Also, Perl and Raku are both working hard to communicate to people outside our communities that Perl and Raku are different languages (there’s unfortunately some confusion on that point, since Raku grew out of Perl6, as you may know). Having a Raku post that’s tagged with perl (and not raku seems detrimental to that goal.

          1. 7

            There is unlikely to be a Raku tag. Minority languages are grouped into families in the tag system. #apl represents array languages like APL and its descendents (J and K). #ml represents functional languages descended from ML, such as SML, Ocaml, F# and Haskell. Raku is descended from Perl and used to be called Perl 6, so Raku fits into the Perl tag. Raku and Perl both have sigils.

            APL does not have sigils (as they are defined by you in the article), and the article is about sigils. So the Apl tag is a poor fit.

          2. 4

            Easy. Perl is not Raku, but both Perl and Raku are instances of perl, which is an ur-language…

            1. 2

              The way I’ve heard that expressed is that both Perl and Raku are Perl-family languages (or sometimes expressed as Perl and Raku being sister languages in the Perl family). Imo, “Perl family” is a clearer way to express the relationship than perl is (people are already used to analogous terms like “C-family language”). Plus, “Perl” vs “perl” is already used to distinguish between the language and the interpreter, so overloading it to also mean the ur-language seems to be asking a lot.

              But I’m open to other views/not dogmatic about it.

    11. 1

      I think this would’ve been easier to read with some examples for a few statements:

      And, as with hashtags and @mentions, the sigil isn’t there document something that’s already true: it makes something true and tells the reader. In the same way that you don’t first create a hashtag on Mastodon/Twitter and then add a  # , in Raku you aren’t required to create some object with an array-like interface and later add a  @ . Instead, using  @  gives it that interface.

      Specifically, examples of what this code looks like/does with and without the sigils would’ve been useful. By the end of the post you’ve gotten the relevant information, but it’s significantly delayed.

      1. 2

        That’s helpful feedback. FWIW, I went through a couple of revisions on that section and one of them had significantly more code – but I decided that the general point got too lost in potentially unfamiliar Raku syntax. It sounds like I may have over corrected.

    12. 1

      I wonder; Can sigils (the way you have used them in Raku) be seen as unary functions? For example, @xx returns the array representation of xx – i.e. @(xx). Does this work for others too?

      1. 1

        I think we can tweak the analogy slightly to make work even better. The syntax you showed @( ) actually is syntax in Raku: it’s the list contextualize, which treats everything inside the ( ) as a list. For example, @(5) evaluates to the list (1). And there are similar $( ) (item), %( ) (hash), and &{ } (function) contextualizers.

        The contextualizers still aren’t quite a unary function, but they’re very close. And if we think of them as functions, then @foo would be the equivalent of @( ) curried on to foo (except that we never declared a separate foo). As a unary function that’s been curried, I guess that would make @foo a ­– *tries to rember word* – niladic function? You know, if you squint.

        …except that it’s immediately invoked. So it’s an immediately invoked niladic function. And I’m pretty sure that “an immediately invoked niladic function” is just a way to “a value” with more syllables.

        Not sure if that answered your question, but it was fun to think through!

    13. 1

      Thus, if I use  @grocery-list  with a  for  loop, the body of the loop will be executed five times. But if I use  $grocery-list , the loop will get executed just once (with the list as its argument).

      Why would the second case ever be what the programmer wants? If they wanted a single body execution, they would not be writing the for loop in the first place, so isn’t it just a footgun?