Your own keywords
Here’s the part I promised. PRINT is a function that this tutorial
bound to a word. You can do exactly the same.
BIND
BIND gives a function a keyword of one to four words. A keyword is called
without parentheses, at the start of a line.
FUNCTION say(text, ending = ".")
PRINT text + ending
END FUNCTION
BIND SAY say
BIND SAY HELLO say("Hello there")
SAY "Keywords are just functions"
SAY HELLO
Keywords are just functions.
Hello there.
The second BIND pins a value to the first parameter, so SAY HELLO needs
nothing after it. When a line could start with either keyword, I take the
longer one.
Modifiers
Remember FOR i = 0 ... 20 !! step(5), and the WOMT operator — Wait! One
more thing!? The part after !! is a modifier:
a function that returns a map of parameter names and values, which I fill in
for you. ALLOW says which ones a keyword takes.
FUNCTION say(text, ending = ".", times = 1)
PRINT (text + ending + " ") * times
END FUNCTION
FUNCTION loudly()
RETURN {ending: "!!!"}
END FUNCTION
FUNCTION again(count)
RETURN {times: count}
END FUNCTION
BIND SAY say ALLOW(loudly, again)
SAY "hello"
SAY "hello" !! loudly
SAY "hello" !! again(3) loudly
hello.
hello!!!
hello!!! hello!!! hello!!!
Modifiers let a statement read like a sentence with options on the end, without a pile of positional arguments nobody can remember.
Those two modifiers are plain functions, though, which means nobody else can
have a variable called again. Put them in a namespace and ALLOW the whole
namespace: the short names then only mean something after !!.
FUNCTION say(text, ending = ".", times = 1)
PRINT (text + ending + " ") * times
END FUNCTION
NAMESPACE Saying
FUNCTION loudly()
RETURN {ending: "!!!"}
END FUNCTION
FUNCTION again(count)
RETURN {times: count}
END FUNCTION
END NAMESPACE
BIND SAY say ALLOW(Saying)
again = 2 // free to be a variable
SAY "hello" !! again(again) loudly
hello!!! hello!!!
Modifiers on a function
A function can take modifiers too. Put ALLOW on the end of its FUNCTION
line, and a call of it takes them after !!, just as a keyword does. That’s
how you ask for a value with options.
NAMESPACE Brewing
FUNCTION strong()
RETURN {scoops: 3}
END FUNCTION
FUNCTION iced()
RETURN {ice: TRUE}
END FUNCTION
END NAMESPACE
FUNCTION coffee(size, scoops = 1, ice = FALSE) ALLOW(Brewing)
LOCAL made = size + ", " + scoops + " scoops"
IF ice THEN made = made + ", iced"
RETURN made
END FUNCTION
PRINT coffee("small")
cup = coffee("large") !! strong iced
PRINT cup
small, 1 scoops
large, 3 scoops, iced
The modifiers go with the call that starts the line, or the one right after
the =. In PRINT coffee("large") !! strong, the modifier would be
PRINT’s, and PRINT doesn’t know it.
Sometimes a function can’t list its modifiers in advance, because the words
depend on something only it knows. Name one of its parameters in ALLOW
with ... after it, and every other word after !! lands in that parameter
as a map.
FUNCTION order(dish, extras = NULL) ALLOW(extras...)
RETURN dish + " with " + extras
END FUNCTION
lunch = order("noodles") !! chili(2) egg
PRINT lunch
noodles with {chili: 2, egg: 1}
I can’t check those words for you before the program runs, so use this only when you have to.
A function that reads like a variable
Mark a function !value in its doc comment and it’s read without
parentheses, worked out afresh each time.
lives = 3
/// Whether the game is still going.
/// !value
FUNCTION alive()
RETURN lives > 0
END FUNCTION
PRINT alive
lives = 0
PRINT alive
1
0
From BASIC: This is how things like
TIMERandPIare made now, and how every statement you remember —LINE,PLAY— gets its word.
From Python, JavaScript and Lua: There’s nothing quite like this where you came from. The nearest is a function call without the brackets — but these are checked before the program runs, show up in the editor’s suggestions, and document themselves.
Crash-tan’s Tip: A keyword’s word is taken for the whole program. Once
SAYis bound, a line can’t beginsay = 3. Choose words you won’t want for variables.