-
Notifications
You must be signed in to change notification settings - Fork 195
Phrases, Sentences and Blocks
Tinymoe has three kinds of functions: phrase, sentence and block.
Phrases are functions that can return a value. Tinymoe wants you to process every return values of function calls, so calling a phrase cannot be a statement, it should be an expression. If you don't understand the difference between expressions and statements, you can read Expressions and Statements.
Let's begin with a phrase without any argument:
phrase pi
set the result to 3.14
end
Then you can use the following code to call this phrase and print the result:
print pi
Then you will get 3.14
.
So how about a phrase with one argument? Let's define one:
phrase the number after (the number)
set the result to the number + 1
end
Now we have a phrase for calculating "x+1". Calling this phrase is very similar to the definition:
print the number after 1
Then you will get 2
.
So what about more arguments? Tinymoe still enable you to do that:
phrase sum from (first number) to (last number)
set the result to 0
repeat with the current number from first number to last number
add the current number to the result
end
end
This is a sample which has already appeared several times before, which calculates first number + (first number + 1) + ... + (last number - 1) + last number
. You may know how to call this phrase:
print sum from 1 to 100
Then you will get 5050
.
You can put argument in wherever you want inside a pharse, but you cannot make an argument just following another one, like:
phrase this is wrong (a) (b)
In some situation we need to deal with arguments but we don't know how many of them. Tinymoe offered a simple way to do that:
phrase sum of (list those numbers)
set the result to 0
repeat with the number in those numbers
add the number to the result
end
end
If an argument begins with list
, it becomes an argument that can receive a list. So calling to this kind of phrase is a little different:
print sum of (1, 2, 3, 4, 5)
Then you will get 15
.
The argument becomes an array inside the phrase. You can use the techniques in Manipulating Arrays to deal with it:
phrase the second number in (list numbers)
set the result of item 2 of array numbers
end
So when you call:
print the second number in (6, 7, 8, 9, 10)
Then you will get 7
.
Arguments in phrases can also be functions. Tinymoe is not designed to be a functional programming language, so Tinymoe don't provide lambda expressions. But Tinymoe still have closure for doing Coroutine. Besides of closure, you can still pass a function as an argument to another function.
First, you need to define an alias to a phrase:
phrase (x) is odd : odd number
set the result to x % 2 = 1
end
When you use odd number
in your code, it will no longer call the function, it is the function itself. Now you can design a phrase whose argument receives a function:
phrase sum of all (phrase (x) satisfies the condition) in (list those numbers)
set the result to 0
repeat with the number in those numbers
if the number satisfies the condition
add the number to the result
end
end
end
When an argument begins with phrase
or sentence
, you can use it as a function. You can call these two phrases together like this:
print sum of all odd number in (1, 2, 3, 4, 5)
Then you will get 9
.
Sentences are very similar to phrases, but calling a sentence can be a statement, because sentences are functions that don't return a value.
And besides of list
, sentences can use two kinds of new argument: expression
and assignable
.
If an argument begins with expression
, it becomes a deferred argument. That means, the argument is evaluated when the code inside the called sentence read this argument. For example:
phrase one
print "one"
set the result to 1
end
sentence print double (x)
print "double1"
print x + x
end
sentence print deferred double (expression x)
print "double2
print x + x
end
When you call print double one
, you will get
one
double1
2
But when you call print deferred double one
, you will get
double2
one
one
2
Because in print deferred double one
, the argument receiving one
is declared as (expression x)
, so when you call this sentence, the evaluation of one
has not started yet. The evaluation is passed to the sentence as an argument.
Then in the print deferred double
sentence, it read the argument x
twice, so the expression one
is evaluated twice.
If you don't read the deferred argument inside a sentence, the argument will never be evaluated. This feature is useful when you need to decide the timing of the evaluation of arguments.
If an argument begins with assignable
, it becomes a reference argument. A reference argument can receive a variable. When you change the argument inside the sentence, the variable will also be changed. If the passed variable does not exist, a new variable will be created and initialized to null
:
sentence add (value) to (assignable target)
set target to target + value
end
phrase main
set x to 10
add 20 to x
print x
end
You will get 30
.
Blocks are a kind of sentences that can additionaly bring a block of code as one of the argument.
To define a block, the block name should begin with an normal argument receiving the body of the code as a function. For example:
block (sentence do it) repeat (number) times
repeat with i from 1 to number
do it
end
end
This is a block called repeat N times
, which will repeat the body of the code for N times. Calling a block is similar to a sentence, except that you should provide several lines of code ending with end
to be the block body:
repeat 3 times
print "I love Tinymoe!"
end
Then you will get
I love Tinymoe!
I love Tinymoe!
I love Tinymoe!
Tinymoe allow you to provide arguments when calling the block body. For example:
block (sentence deal with (it)) repeat (number) times with (argument counter)
repeat with i from 1 to numbers
deal with i
end
end
When an argument begins with argument
, it means there is a room for the user to name one of the argument for the block body. This is not a real argument, this is a definition. So the code in the block cannot actually see counter
.
At the mean time, when you defined the body argument sentence deal with (it)
, you are respponsible to keep the number of the arguments equals to the number of all argument
arguments.
Calling this block is similar as before, except that the caller need to define the name of the argument and embed it inside the calling code:
repeat 3 times with the counter
print "I love Tinymoe " & the counter & " times!"
end
repeat 3 times with the counter
calls the block, with 3
passed to the number
argument, and the counter
defines the argument name of the body code print "I love Tinymoe " & the counter & " times!"
.
Then you will get
I love Tinymoe 1 times!
I love Tinymoe 2 times!
I love Tinymoe 3 times!