do: run text as statements
xTalk can run xTalk it has just put together. do takes text and runs it as statements, one line or many, as if they were written where the do is, with the same variables:
put "put 6 * 7" into tCode
do tCode
put 5 into tA
do "put tA * 2 into tB" & return & "add 1 to tB"
put tB
42 11
Text that is not xTalk is an error when the do runs it, which a try catches like any other (Handling errors):
try
do "put 1 +"
catch tError
put "That was not a statement xTalk could run."
end try
That was not a statement xTalk could run.
value: work out an expression
value is do for expressions: it works out the text as an expression and returns its value. With an object as its second parameter, the expression is worked out as if in that object's script, so me and its handlers are the object's:
put value("3 + 4 * 2")
put value("the length of" && quote & "hello" & quote)
create button "Greeter"
set the script of it to "function greet pWho" & return & \
"return " & quote & "Hello, " & quote & " & pWho" & return & "end greet"
put value("greet(" & quote & "Ada" & quote & ")", button "Greeter")
11 5 Hello, Ada
Calling a handler by its name
Most of the time, what you want is not to run any code at all, but to call a handler whose name you work out as the program runs: the handler for a menu item, a command typed by the user, a step in a list. send and dispatch take the message as text, so the name can come from anywhere. dispatch leaves handled or unhandled in it, so a name with no handler is easy to spot:
on sayHello
put "hello"
end sayHello
on sayGoodbye
put "goodbye"
end sayGoodbye
repeat for each item tWhat in "Hello,Goodbye,Thanks"
dispatch "say" & tWhat to me
if it is "unhandled" then put "nobody says" && tWhat
end repeat
hello goodbye nobody says Thanks
For a function, dispatch function calls it with the parameters after with, and leaves what it returned in the result:
function double pN
return pN * 2
end double
function square pN
return pN * pN
end square
repeat for each item tName in "double,square"
dispatch function tName to me with 9
put tName && "of 9 is" && the result
end repeat
double of 9 is 18 square of 9 is 81
merge with code in it
merge (Formatting) also runs code written between <? and ?>: whatever the code returns takes its place. It suits a template with a decision in it:
put 3 into tCount
put merge("<?return tCount * 2?> eggs")
put merge("<?if tCount > 2 then return " & quote & "Lots of" & quote & " else return " & quote & "A few" & quote & "?> eggs")
6 eggs Lots of eggs
Never run text you did not write
do, value and merge run whatever they are given, with all the power of your program: they can delete files, send data anywhere, or change any object. Never give them text that came from outside the program (a field the user typed in, a file, a web page) as it is. A calculator that works out what the user types must first make sure it is only a sum:
function calculate pExpression
if not matchText(pExpression, "^[0-9+*/(). -]+$") then
return "not a sum I will work out"
end if
try
return value(pExpression)
catch tError
return "not a sum I can work out"
end try
end calculate
put calculate("(2 + 3) * 4")
put calculate("1 / 8")
put calculate("delete file myNotes")
put calculate("2 +")
20 0.125 not a sum I will work out not a sum I can work out
The pattern (Patterns) lets through only digits, the four signs of arithmetic, brackets, points and spaces, so nothing the user types can be a command. Check what is let in, not what is kept out: a list of forbidden words always misses one.
Try it yourself
Write a tiny command interpreter: for each line of add 5, add 10, times 3, shout and add 1, call the handler named cmd followed by the line's first word (so cmdAdd, cmdTimes), with the line's second word as its parameter. The handlers change a running total. A line with no handler puts unknown command: and the line. Put the total at the end.
Show a solution
local sTotal
on cmdAdd pN
add pN to sTotal
end cmdAdd
on cmdTimes pN
multiply sTotal by pN
end cmdTimes
put 0 into sTotal
put "add 5" & return & "add 10" & return & "times 3" & return & "shout" & return & "add 1" into tProgram
repeat for each line tLine in tProgram
dispatch ("cmd" & word 1 of tLine) to me with word 2 of tLine
if it is "unhandled" then put "unknown command:" && tLine
end repeat
put "total:" && sTotal
unknown command: shout total: 46
Words in this lesson
Each one finds every lesson that uses it. The Dictionary has the whole story of each, with its syntax and more examples.