“all day I sit here and make function calls”
When you are writing programs in Rye, almost all that you actually do is make function calls. Well, you do that in every language, but in Rye, this statement is much more true than in most of them. More on that in the next page.
Many functions are already built into Rye runtime, they are written in it’s host language Go. We call them builtin functions or builtins for short. Other functions, just functions, are written, or you write in Rye. You call both the same way.
One such builin function is print. It prints a value to standard output and goes to the next line.
print "Hello!"
; prints: Hello!
print "Hello World!"
; prints: Hello World!
Print function takes one value (an argument) and prints it. We call it by naming it and provide an argument, in this case a text to print.
Print or some variant of it (println, echo, …) exists in almost every language, but most functions in Rye are not like print. We don’t call them for effect, but for their return value.
Inc (increment) accepts one integer value and returns a value that is an increment of the accepted value. It doesn’t change anything and at the same input (the argument) it always returns the same result.
; Functions taking one argument
inc 99
;returns 100
first { 1 2 3 }
; returns: 1
avg { 8 9 11 12 }
; returns: 10.0
join { "Hello" "World" }
; returns: "HelloWorld"
As we said, big part of builtin functions are like that. And many of them take more than one argument.
; Functions taking two arguments
_+ 123 123
; returns 246
factor-of 10 2
; returns 1
tail { 1 2 3 4 5 } 2
; returns: { 4 5 }
intersection { 1 2 3 4 5 } { 0 2 4 6 }
; returns: { 2 4 }
join\with { "Hello" "World" } " "
; returns: "Hello World"
All the lines above are expressions, because they return results and have no side effects. We then combine expressions to get the desired result.
In the previous page we learned that we can assign values to words. Invoking a word is the simplest expression, if the value is not a function it returns the assigned value.
name: "Jane"
; we assigned text "Jane" to word name
name
; returns: "Jane"
print name
; prints: Jane
Since functions calls produce a result we can compose them together. A result of one function call can be an argument to another.
print inc 999
; prints: 1000
Let me tell you a story:
name: "bob"
print capitalize name
; prints: Bob
In Rye (like in REBOL) all functions have a fixed number of arguments. REBOL had something called refinements to remedy this, the idea was good on the first level, but you couldn’t elegantly pass refinements to next calls. Refinements also clashed syntatctically with context navigation. So Rye doesn’t have this concept.
It has a naming convention. Where there is a primary function, but you need more variations or specialisations of it, we use “\” character in the naming of function denote that. You saw one example above with join and join\with. Remember these are two different functions, it’s just a naming convention.
; join & variants
join { "I" "am" 100 "%" "sure" }
; returns: "Iam100%sure"
join\with { "I" "am" 100 "%" "sure" } " "
; returns: "I am 100 % sure"
; print & variants
print { "Jane" "Bob" "Anne" }
; prints: { Jane Bob Anne }
print\csv { "Jane" "Bob" "Anne" }
; prints: Jane,Bob,Anne
print\json { "Jane" "Bob" "Anne" }
; prints: [ "Jane", "Bob", "Anne" ]
; map & variants
map { 9 99 999 } { + 33 }
; returns: { 42 132 1032 }
map\idx { 10 100 1000 } 'i { * i } ; Rye distinguishes between index (offset)
; returns: { 0 100 2000 }
map\pos { 10 100 1000 } 'i { * i } ; and position (first, second, ... )
; returns: { 10 200 3000 }