Skip to content

YS Symbols

Today I'd like to show you why I love how YS handles symbols.

Symbols are used to represent variables, functions, and other names in the language.

All the shorties I showed you yesterday were symbols. Symbols that resolved to functions.

Clojure / Lisp Symbols🔗

In languages like Python, symbols are generally strings composed of alphanumeric characters and _. They generally can't start with a number.

In Clojure, like most Lisps, the rules accept many more characters. They still can't start with a number.

From the Clojure Language Reference External link :

Symbols begin with a non-numeric character and can contain alphanumeric characters and *, +, !, -, _, ', ?, <, > and = (other characters may be allowed eventually).

That's a lot of possibilities!!

Should +<*@?=! be a symbol? Apparantly!

YS Symbols🔗

If you look through the Clojure core library source code External link , you'll see that that almost every symbol is made of alphanumeric characters and the - character. A few end with !, ?, * and a few use + instead of - to separate words. There's a handful of other weirdos, but for the most part, it's a very sane subset of what is actually allowed.

YS chose to only allow the sane subset; even stricter that what I just described.

YS symbols are alphanumeric words separated by a single - character and start with an alphabetic character. They may end with ?, ! or +.

Even with this very simple rule, YS can still access all the things it needs from Clojure.

Any Symbol, Any Time🔗

One of the aspects of both YS and Clojure that I love is that you can use any word you want to as a variable name. YS and Clojure have no concept of "keywords" or "reserved words".

Imagine using if as a variable name in Python:

$ python -c 'if = 42'
  File "<string>", line 1
    if = 42
       ^
SyntaxError: invalid syntax

No way!

You need to make up a new name for your variable. Something like if_ is common when it's important to use the name if.

In YS, you can use if as a variable name.

$ ys -e 'if =: 42' -e 'say: if'
42

You just can't use the if function after that within the same scope.

$ ys -e 'if =: 42' -e 'if if: say(if)'
42

Wait, what?

It actually worked!

I honestly did not expect that to work. I've figured it out but I can't explain why right now. Let's just say that if is special External link .

Let's try something else.

$ ys -e 'r =: range(65 70).map(C)' -e 'say: zipmap(r range())'
{A 0, B 1, C 2, D 3, E 4}

Neato, but r is bad name. Let's change it to range!

$ ys -e 'range =: range(65 70).map(C)' -e 'say: zipmap(range range())'
Error: Attempting to call unbound fn: #'main/range

Yep, that's what I expected. We changed range for a function to a list of characters, so we can't just use it as a function again.

Symbols inside functions🔗

Functions provide a better scope to use whatever you want as a variable name.

Imagine we've written a dice-roll function and we want t call it and save the dice roll. What should we call the variable? Well most of the time, I'd want to call it what it is: dice-roll!

!YS-v0

defn main():
  dice-roll =: dice-roll()
  say:
    if dice-roll.0 == dice-roll.1:
      then: "Dice numbers match: $dice-roll"
      else: "Dice numbers are different: $dice-roll"

defn dice-roll(): +
  [rand-int(6).++ rand-int(6).++]

Running this, we get:

$ ys dice.ys 
Dice numbers match: [6 6]
$ ys dice.ys 
Dice numbers are different: [6 4]

When you need to make up a name for something in YS, just use whatever makes sense!

Comments