Evaluation and interpolation

With the definition of type Expr from the preceding section, we can also build expressions directly from the constructor for Expr. For example: e1 = Expr(:call, *, 3, 4) returns :((*)(3, 4)) (follow along with the code in Chapter 7eval.jl).

The result of an expression can be computed with the eval function, eval(e1), which returns 12 in this case. At the time an expression is constructed, not all the symbols have to be defined, but they have to be defined at the time of evaluation, otherwise an error occurs.

For example, e2 = Expr(:call, *, 3, :a) returns :((*)(3, a)), and eval(e2) then gives ERROR: UndefVarError: a not defined. Only after we say, for example, a = 4 does eval(e2) return 12.

Expressions can also change the state of the execution environment, for example, the expression e3 = :(b = 1) assigns a value to b when evaluated, and even defines b, if it doesn't exist already.

To make writing expressions a bit simpler, we can use the $ operator to do interpolation in expressions, as with $ in strings, and this will evaluate immediately when the expression is made. The expressions a = 4 and b = 1, e4 = :(a + b) return :(a + b), and e5 = :($a + b) returns :(4 + b); both expressions evaluate to 5. So, there are two kinds of evaluation here:

  • Expression interpolation (with $) evaluates when the expression is constructed (at parse time)
  • Quotation (with : or quote) evaluates only when the expression is passed to eval at runtime

We now have the capability to build code programmatically. Inside a Julia program, we can construct arbitrary code while it is running, and then evaluate this with eval. So, Julia can generate the code from inside itself during the normal program execution.

This happens all the time in Julia and it is used, for example, to do things such as generating bindings for external libraries, to reducing the repetitive boilerplate code needed to bind big libraries, or generating lots of similar routines in other situations. Also, in the field of robotics, the ability to generate another program and then run it is very useful. For example: a chirurgical robot learns how to move by perceiving a human surgeon demonstrating a procedure. Then, the robot generates the program code from that perception, so that it is able to perform the procedure by itself.

One of the most powerful Julia tools emerging from what we discussed before is macros, which exist in all the languages of the Lisp family.

Julia version 1.0 also introduces the concept of generated functions: such functions are prefixed by the @generated macro and, instead of normal values, they return expressions. We won't discuss this advanced concept here in this book.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.227.9