REBOL 3 Docs | Guide | Concepts | Functions | Datatypes | Errors |
TOC < Back Next > | Updated: 20-Oct-2009 Edit History |
Scripts don't always work the way you want. This section helps you to figure out why, and understand some common problems that can occur.
Many years of debugging REBOL code have shown us some of the best ways to debug code. Here are the main ideas.
Quite often, you can simply insert a print to see what your code is doing:
data: copy "test" loop 3 [print append data random 10] test3 test38 test382
The ?? function will print the variable name, followed by its value.
a: 10
?? a
a: 10
In addition, it also returns the result, so it can be inserted inline with code:
b: 20
c: a + ?? b
b: 20
If a block is provided as the argument, then each variable and value will be shown:
?? [a b]
a: 10 b: 20
The probe function will mold a value into source format and display it. It also returns the value as a result.
word: 'here
if probe find [where here there] word []
[here there]
Unlike print, probe does not evaluate the contents of blocks.
probe [1 + 2]
[1 + 2]
print [2 + 2]
3
If you really need to know what's going on, you can use trace.
You can specify a number of levels to trace
trace 3 ; only trace top three levels
or you can trace everything:
trace on
To disable trace
trace off
The output of trace is very detailed.
Tracing:
print 123 1: print : native! [value] 2: 123 --> print 123 <-- print => unset!
The ==> indicates entry into a function, and <== is the return, with the return value following it.
Although we try to make error messages clear, new users may still find them to be frustrating until you understand REBOL at a deeper level.
This example shows the general format of error messages:
either abc [this] [that] ** Script error: abc has no value ** Where: either catch case applier do ** Near: either abc [this] [that]
The first line tells you the general type of error (script error) and provides a few specifics (abc has no value, it is undefined.)
The second line provides the back-trace of functions that were called before the error occurred. The first name is where the error happened. Some of these are functions in your code; others are system functions that called your code.
The third line shows you the code where the error happened. This is an approximate location, because the error may span several values.
More on the details of errors can be found in the errors section.
Here we point out some of the most common mistakes users make in their code.
If you miss a beginning or ending bracket, parenthesis, or quote, when you load the code, you'll see an error message.
For example, if the test.r file is missing its final bracket, you will see this error message:
Evaluating: test.r ** Syntax error: missing "]" at "end-of-script" ** Where: to unless either if load either either do begin do ** Near: (line 3) loop 3 [
The system will attempt to tell you where the problem started, or the matching position for the missing item. However, they can be difficult to find.
If this is a common problem for you, we suggest that you use a code editor that includes a feature for finding matching brackets, braces, and parentheses. For example the VI(M) editor on Linux or XCode on OSX.
Don't forget to provide all required arguments to each function.
For example, either takes three arguments as shown with here:
? either USAGE: EITHER condition true-block false-block
The code below forgets to provide the third argument, and you see an error:
either a > 10 [a: 1]
print "done"
** Script error: either does not allow unset! for its false-block argument
This error occurs because print returns unset!, which is then passed to either as its second block. That's not valid, and the error occurs.
If you're not sure about the number of arguments, use help to check. You can also use this technique: enclose the problematic expression in a do block.
For example, this will better show an error:
do [ either cond [a: 1] ]
** Script error: either is missing its false-block argument
If you provide too many arguments, they may be ignored.
For example, the if takes two arguments as shown with here:
? if USAGE: IF condition then-block
If you write:
if a > 10 [a: 1] [b: 2]
The second block is never used, because if does not require it. Although it does not cause an error, your code will not produce the correct results when the if condition is false.
Conditional functions provide a shortcut that lets you use values other than logic! as their condition. This done quite often.
In such cases, the condition is only false when it returns false or none!, and they are true when they return any other value.
Below, all of the conditional expressions act like true, even the zero and empty block values.
if true [print "yep"]
yep
if 1 [print "yep"]
yep
if 0 [print "yep"] ; C programmers - watch out!
yep
if [] [print "yep"]
yep
Here the expressions are false :
if false [print "yep"] if none [print "yep"]
So, be sure never to enclose the conditional in a block. The block is not evaluated, it just acts like a value, which will be TRUE:
if [false] [print "yep"]
yep
The blocks act like true is simple. This style of coding is used quite often:
if find block item [print "found"]
This is an example of two functions (if and find) being "compounded" together. Let's break that compound set of functions down.
When the find function finds the item, it turns a block! series (at the location of the item). If it fails to find the item, it returns none.
When find block item is resolved to a value, it then becomes the condition argument for the if function, and [print "found"] will become the then-block argument.
The use of compound functions is one of the strengths of Rebol. It is easier and more efficient to code that way than to use temporary arguments like this:
temp: find block item if temp [print "found"]
TOC < Back Next > | REBOL.com - WIP Wiki | Feedback Admin |