Chapter 3

Names

So far every program has been one long line of words. This chapter gives things names: values you want to keep, and lists you want to run as new words.

Naming a value

= takes the value on top and binds it to the word that comes after it. From then on, that word pushes the value.

# 5 = x
x debug
x x * debug
5
25
values: ( )

Binding the same name again replaces the old value. This is how a program keeps a counter:

# 1 = count
count ++ = count
count ++ = count
count debug
3
values: ( )

++ adds one to the number on top, and -- subtracts one.

Naming a list: new words

=> binds a list as a word: running the name runs the list.

{ dup * } => square
# 3 square debug
# 3 square square debug
9
81
values: ( )

Compare the two arrows. With = the name pushes the list; with => the name runs it.

{ dup * } = keep
{ dup * } => run
# 4 keep
# 4 run
values: ( 16 ( "dup" "*" ) 4 )

Mixing up the two is a common mistake: a word bound with = when you meant => pushes its list instead of running it, and the error comes later, from whichever word receives the list.

A word you define this way is a macro, exactly like the words built into Ether, and the step rule cannot tell them apart. A word can use any word that exists when it runs, including words defined later and itself.

The macro table

macros pushes the macro table, the table the step rule looks words up in. \ pushes the next word without running it, which is how you talk about a word instead of using it. Together they answer "is this word defined?":

\ square macros has debug
{ dup * } => square
\ square macros has debug
false
true
values: ( )

A word may already be taken. Ether comes with 176 words, and some have short, ordinary names: one, zero, null, key, object, words, table, string. A word you meant as plain data runs instead if it has a definition:

apple one pear
values: ( "pear" 1 "apple" )

one pushed the number 1. Escape such a word with \ when you mean the word itself: \ one. macros keys lists every defined word: 176 with the native words, and more when the language is written in Ether, whose definitions keep private helper words in the table too.

176
values: ( )

Scope

Names are global: a name bound anywhere is visible everywhere afterwards, and binding it again changes it for everyone. scope runs a list and then puts the macro table back as it was, so names made inside it do not escape.

# 1 = x
{ # 2 = x x debug } scope
x debug
2
1
values: ( )

Exercise 3.1

Define a word square and use it to print 12 × 12.

A correct answer prints:

144
values: ( )
One answer
{ dup * } => square
# 12 square debug
144
values: ( )

Exercise 3.2

Define square, then define cube using square, and print the cube of 5.

A correct answer prints:

125
values: ( )
One answer
{ dup * } => square
{ dup square * } => cube
# 5 cube debug
125
values: ( )

Exercise 3.3

Bind total to 10, then add 5 to it and subtract 2 from it, binding the result to total each time, and print total.

A correct answer prints:

13
values: ( )
One answer
# 10 = total
total # 5 + = total
# 2 total - = total
total debug
13
values: ( )

Exercise 3.4

Bind greeting to the text hello. Then, inside a scope, bind it to goodbye and print it. After the scope, print it again.

A correct answer prints:

goodbye
hello
values: ( )
One answer
" hello " = greeting
{ " goodbye " = greeting greeting debug } scope
greeting debug
goodbye
hello
values: ( )