Julia Macro Summary

Julia code is represented by objects that can be created and manipulated from within the language.
Macro is used to generate code.

Expr

Abstract syntax tree

Julia code will be parsed into Expr,
eg:

 julia> dump(r)
 Expr
   head: Symbol =
   args: Array(Any,(2,))
     1: Symbol a
     2: Int64 1
   typ: Any

The expr works like other code.

Fields

head: identifying the kind of expression. eg: :call, :+, :block
args, an array of subexpressions.
typ, field is used by type inference to store type annotations,
isn't used for most time

Usage

Quoting

   ex = :(a+b*c+1)
   ex2 = quote x=1
               y=2
               x+y
        end
   ex2.head
 # block
 #+END_SRC

Use Expr

   a, b, c = 1, 2, 3
   ex1 = Expr(:call)
   ex1.args = [:*, :b, :c]

   ex = Expr(:call)
   ex.args = [:+, :a, ex1]

   eval(ex)
   7

   Meta.show_sexpr(ex)

Macro

How it works

Julia macro
A macro is a way of generating a new output expression, given an unevaluated input expression.
When your Julia program runs, it first parses and evaluates the macro,
and the processed code produced by the macro is eventually evaluated like an ordinary expression.

  macro foo()
    println("macro foo is evalued")
    :("foo")
  end


  function f()
    println("f is execulated")
    @foo()
  end

  # got 'macro foo is evalued' in REPL,
  # so this means, f is compiled and the macro generate the code.

  'f.env.defs.func.code '
  will got
  AST(:($(Expr(:lambda, Any[], Any[Any[],Any[],Any[]], :(begin  # none, line 2:
                                                           println("f is execulated") # line 3:
                                                           return "foo"
                                                         end)))))
  f()
  # f is execulated
  # "foo"

Why we need macro?

Allow the programmer to generate and include fragments of customized code before the full program is run

Methods: eval, $, :, esc

1. eval
   eval expression in top level
2. $
   will eval in a quote
3. :
   quote
4. esc
   escape
   Do not let Julia generates new symbol for a variable.

   The Clojure works in the opposite way, Clojure use variable# to generate symbol.

'$' vs 'eval'

 |       | $             | eval     |
 |-------+---------------+----------|
 | usage | :($a)         | eval(:a) |
 | scope | current place | global   |

More useful methods

 dump: dump expression
 Meta.show_sexpr: print an AST as an S-expression
 parse: parse string to expresion
 macroexpand: macroexpand(:(@macro(a)))

Tricks

Macro syntax sugar for string

   macro p_str(s)
     println(s)
   end

   p"abc"

macro with multiple lines

 @my_macro begin
    ...
    ...
 end

How to create a macro for creating a symbol in Julia

 macro s_str(p)
   :(symbol($p))
 end

 r = s"c"

 # another way
 macro s(p)
  QuoteNode(p)
 end
 r = @s(a)

你可能感兴趣的:(Julia Macro Summary)