In [115]:
prog = "1 + 1"
Out[115]:
In [116]:
@doc parse
Out[116]:
In [117]:
ex1 = parse(prog)
Out[117]:
In [118]:
typeof(ex1)
Out[118]:
In [119]:
@doc Expr
Out[119]:
In [120]:
(ex1.head, ex1.args, ex1.typ)
Out[120]:
In [121]:
ex2 = Expr(:call, :+, 1, 1)
Out[121]:
In [122]:
ex1 == ex2
Out[122]:
The key point here is that Julia code is internally represented as a data structure that is accessible from the language itself.
In [123]:
@doc dump
Out[123]:
In [124]:
dump(ex2)
In [125]:
ex3 = parse("(4 + 4) / 2")
Out[125]:
In [126]:
dump(ex3)
In [127]:
@doc Meta.show_sexpr
Out[127]:
In [128]:
Meta.show_sexpr(ex3)
In [129]:
:foo == symbol("foo")
Out[129]:
In [130]:
@doc symbol
Out[130]:
In [131]:
symbol(:var,'_',"sym")
Out[131]:
In [132]:
wow = :(::)
Out[132]:
In [133]:
dump(wow)
In [134]:
:(a+b*c+1)
Out[134]:
In [135]:
:(a + b*c + 1) ==
parse("a + b*c + 1") ==
Expr(:call, :+, :a, Expr(:call, :*, :b, :c), 1)
Out[135]:
In [136]:
ex = quote
x = 1
y = 2
x + y
end
Out[136]:
In [137]:
a = 1
ex = :($a + b)
Out[137]:
In [138]:
ex = :(a in $:((1,2,3)) )
Out[138]:
In [139]:
dump(ex)
In [140]:
eval(ex)
Out[140]:
In [141]:
:(a in $:((1,2,3))) == :(a in $(:((1,2,3))))
Out[141]:
In [142]:
function make_expr(op, opr1, opr2)
opr1f, opr2f = map((opr1, opr2)) do x
isa(x, Number) ? 2*x : x
end
Expr(:call, op, opr1f, opr2f)
end
Out[142]:
In [143]:
make_expr(:+, 2, :x)
Out[143]:
In [144]:
macro sayhello(name)
return :( println("Hello, ", $name) )
end
In [145]:
@sayhello "Julia"
In [146]:
@doc macroexpand
Out[146]:
In [147]:
macroexpand( :(@sayhello("human")) )
Out[147]:
In [148]:
macro showarg(x)
show(x)
# ... remainder of macro, returning an expression
end
In [149]:
@showarg 1+2
In [150]:
macroexpand(:(@assert a==b))
Out[150]:
In [151]:
module MyModule
macro wrong_time(ex)
return quote
local t0 = time()
local val = $ex
local t1 = time()
println("elapsed time: ", t1-t0, " seconds")
val
end
end
macro right_time(ex)
return quote
local t0 = time()
local val = $(esc(ex))
local t1 = time()
println("elapsed time: ", t1-t0, " seconds")
val
end
end
end
Out[151]:
In [152]:
for op = (:×, :⋅, :∧)
@eval ($op)(a,b) = @sprintf "(%s %s %s)" a string($op) b
@eval ($op)(a,b,c) = ($op)(($op)(a,b),c)
end
(2 ⋅ 3, 2 × 3, 2 ∧ 3)
Out[152]:
In [153]:
@which 2 + 2
Out[153]:
In [154]:
@less 1 + 1
In [155]:
@edit 1 + 1
In [156]:
clipboard(:(1+1))
# Paste then we get
1 + 1
Out[156]:
In [157]:
apropos("IPv6")
In [158]:
methods(+)
Out[158]:
In [159]:
methodswith(Real)
Out[159]:
In [160]:
methodswith(Real, +)
Out[160]:
In [161]:
object_id(+)
Out[161]:
In [162]:
@which getfield
Out[162]:
In [181]:
@doc getfield
Out[181]:
In [163]:
type Experiment
a::Int64
b::Function
c::AbstractString
end
In [164]:
expm = Experiment(100, +, "A String")
Out[164]:
In [165]:
expm.(:c)
Out[165]:
In [166]:
expm.c
Out[166]:
In [167]:
symbolc = "c"
expm.(symbol(symbolc))
Out[167]:
In [168]:
fieldoffsets(Experiment)
Out[168]:
In [169]:
structinfo(T) = [zip(fieldoffsets(T),fieldnames(T),T.types)...]
Out[169]:
In [170]:
structinfo(Experiment)
Out[170]:
In [171]:
expm.b(1, 3)
Out[171]:
In [172]:
method_exists(+, Tuple{Real})
Out[172]:
In [173]:
applicable(+, 1)
Out[173]:
In [174]:
applicable(+, "1")
Out[174]:
In [175]:
@doc invoke
Out[175]:
In [176]:
invoke(+, (Float64, Float64), 1.0, 1.0)
Out[176]:
In [177]:
[1:5;] |> x->x.^2 |> sum |> inv == inv(sum([1:5;].^2))
Out[177]:
In [178]:
@doc call
Out[178]:
In [179]:
call(m::Experiment, s::AbstractString) = parse(s)
Out[179]:
In [180]:
expm("123")
Out[180]:
In [184]:
@doc @gensym
Out[184]:
In [195]:
@doc @elapsed
Out[195]:
In [186]:
@elapsed sleep(1)
Out[186]:
In [196]:
@doc @allocated
Out[196]:
In [187]:
@allocated [1, 2, 3]
Out[187]:
In [188]:
@allocated [1]
Out[188]:
In [189]:
@allocated 1
Out[189]:
In [194]:
(@allocated(collect(range(0, 1000))) - @allocated([]))/1000
Out[194]:
In [200]:
(ff, fl) = functionloc(+, (Real, Real))
Out[200]:
In [201]:
less(ff, fl)
In [202]:
less(+, (Real, Real))
In [204]:
methods(Experiment)
Out[204]:
In [205]:
less(Experiment, (Int64, Function, AbstractString))
In [208]:
expand(:(x + 3y))
Out[208]:
In [217]:
function af(x)
x + 1
end
expand(:(af(3)))
Out[217]:
In [226]:
@code_lowered join(["a", "b"], "#")
Out[226]:
In [227]:
@code_lowered 1 + 1
Out[227]:
In [228]:
@code_lowered af(3)
Out[228]:
In [231]:
@code_typed join(["a", "b"], "#")
Out[231]:
In [232]:
@code_typed 1 + 1
Out[232]:
In [233]:
@code_typed af(3)
Out[233]:
In [234]:
@code_warntype join(["a", "b"], "#")
In [235]:
@code_warntype 1 + 1
In [236]:
@code_warntype af(3)
In [239]:
@code_warntype (1 + 2 * af(3))
In [240]:
@code_llvm join(["a", "b"], "#")
In [241]:
@code_llvm 1 + 1
In [242]:
@code_llvm af(3)
In [243]:
@code_native join(["a", "b"], "#")
In [244]:
@code_native 1 + 1
In [245]:
@code_native af(3)
In [247]:
P = quote
a = 2
b = 3
c = 4
d = 5
e = sum([a,b,c,d])
end
Out[247]:
In [248]:
for (n, expr) in enumerate(P.args)
println(n, ": ", expr)
end
In [249]:
quote s = $(sin(1) + cos(1))
end
Out[249]:
In [250]:
macro p(n)
if typeof(n) == Expr
println(n.args)
end
eval(n)
end
In [251]:
@p 3
Out[251]:
In [252]:
@p 3 + 4 - 5 * 6 / 7 % 8
Out[252]:
In [253]:
macro f(x)
quote
s = 4
(s, $(esc(s)))
end
end
In [254]:
s = 0
@f s
Out[254]:
In [255]:
@doc esc
Out[255]:
In [263]:
macro dotimes(n, body)
quote
for i = 1:$(esc(n))
@printf "%d\t" i
$(esc(body))
end
end
end
@dotimes 3 println("......")
In [264]:
macro until(condition, block)
quote
while true
$(esc(block))
if $(esc(condition))
break
end
end
end
end
In [269]:
i = 0
@printf "|"
@until i == 10 begin
i += 1
@printf "%d|" i
end
In [1]:
@doc Base.box
Out[1]:
In [2]:
Base.box(1)
In [4]:
(Base.box)(Base.Int,(Base.add_int)(x::Int64,y::Int64))
In [5]:
(Base.box)(Base.Int,(Base.add_int)(1,1))
Out[5]:
In [6]:
varx=1;vary=2;
(Base.box)(Base.Int,(Base.add_int)(varx::Int64,vary::Int64))
Out[6]:
In [7]:
(Base.add_int)(varx::Int64,vary::Int64)
Out[7]:
In [11]:
(Base.box)(Base.Int8,(Base.add_int)(varx::Int64,vary::Int64))
In [12]:
(Base.box)(Base.Int8,(Base.add_int)(varx,vary))
In [278]:
apropos("⋅") # \cdot
In [290]:
@doc dot
Out[290]:
In [279]:
apropos("×") # \times
In [291]:
@doc cross
Out[291]:
In [292]:
@which cross
Out[292]:
In [293]:
apropos("∧") # \wedge
In [294]:
"∧" == "^"
Out[294]:
In [295]:
1^2
Out[295]:
In [296]:
1∧2
Out[296]:
In [297]:
typeof(1∧2)
Out[297]:
In [298]:
1∫2
In [299]:
∧2
In [300]:
1∧
In [302]:
@which ∧
Out[302]:
In [306]:
@doc Main.∧
Out[306]:
In [310]:
@doc Base.Operators
Out[310]:
In [313]:
Base.Operators.⋅
Out[313]:
See operator precedence table in Julia source code.
;; Operator precedence table, lowest at top
;; note: there are some strange-looking things in here because
;; the way the lexer works, every prefix of an operator must also
;; be an operator.
(define prec-assignment
'(= := += -= *= /= //= .//= .*= ./= |\\=| |.\\=| ^= .^= ÷= .÷= %= .%= |\|=| &= $= => <<= >>= >>>= ~ |.+=| |.-=|))
(define prec-conditional '(?))
(define prec-arrow '(-- --> ← → ↔ ↚ ↛ ↠ ↣ ↦ ↮ ⇎ ⇏ ⇒ ⇔ ⇴ ⇶ ⇷ ⇸ ⇹ ⇺ ⇻ ⇼ ⇽ ⇾ ⇿ ⟵ ⟶ ⟷ ⟷ ⟹ ⟺ ⟻ ⟼ ⟽ ⟾ ⟿ ⤀ ⤁ ⤂ ⤃ ⤄ ⤅ ⤆ ⤇ ⤌ ⤍ ⤎ ⤏ ⤐ ⤑ ⤔ ⤕ ⤖ ⤗ ⤘ ⤝ ⤞ ⤟ ⤠ ⥄ ⥅ ⥆ ⥇ ⥈ ⥊ ⥋ ⥎ ⥐ ⥒ ⥓ ⥖ ⥗ ⥚ ⥛ ⥞ ⥟ ⥢ ⥤ ⥦ ⥧ ⥨ ⥩ ⥪ ⥫ ⥬ ⥭ ⥰ ⧴ ⬱ ⬰ ⬲ ⬳ ⬴ ⬵ ⬶ ⬷ ⬸ ⬹ ⬺ ⬻ ⬼ ⬽ ⬾ ⬿ ⭀ ⭁ ⭂ ⭃ ⭄ ⭇ ⭈ ⭉ ⭊ ⭋ ⭌ ← →))
(define prec-lazy-or '(|\|\||))
(define prec-lazy-and '(&&))
(define prec-comparison
'(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ |.>| |.<| |.>=| |.≥| |.<=| |.≤| |.==| |.!=| |.≠| |.=| |.!| |<:| |>:| ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩴ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣)) ;; plus `in`
(define prec-pipe '(|\|>| |<\||))
(define prec-colon '(: |..|))
(define prec-plus '(+ - ⊕ ⊖ ⊞ ⊟ |.+| |.-| |++| |\|| ∪ ∨ $ ⊔ ± ∓ ∔ ∸ ≂ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣))
(define prec-bitshift '(<< >> >>> |.<<| |.>>| |.>>>|))
(define prec-times '(* / |./| ÷ |.÷| % ⋅ ∘ × |.%| |.*| |\\| |.\\| & ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗))
(define prec-rational '(// .//))
(define prec-power '(^ |.^| ↑ ↓ ⇵ ⟰ ⟱ ⤈ ⤉ ⤊ ⤋ ⤒ ⤓ ⥉ ⥌ ⥍ ⥏ ⥑ ⥔ ⥕ ⥘ ⥙ ⥜ ⥝ ⥠ ⥡ ⥣ ⥥ ⥮ ⥯ ↑ ↓))
(define prec-decl '(|::|))
(define prec-dot '(|.|))
From https://docs.python.org/2/library/operator.html#mapping-operators-to-functions :
Operation | Syntax | Function |
---|---|---|
Addition | a + b |
add(a, b) |
Concatenation | seq1 + seq2 |
concat(seq1, seq2) |
Containment Test | obj in seq |
contains(seq, obj) |
Division | a / b |
div(a, b) (without
__future__.division ) |
Division | a / b |
truediv(a, b) (with
__future__.division ) |
Division | a // b |
floordiv(a, b) |
Bitwise And | a & b |
and_(a, b) |
Bitwise Exclusive Or | a ^ b |
xor(a, b) |
Bitwise Inversion | ~ a |
invert(a) |
Bitwise Or | a | b |
or_(a, b) |
Exponentiation | a ** b |
pow(a, b) |
Identity | a is b |
is_(a, b) |
Identity | a is not b |
is_not(a, b) |
Indexed Assignment | obj[k] = v |
setitem(obj, k, v) |
Indexed Deletion | del obj[k] |
delitem(obj, k) |
Indexing | obj[k] |
getitem(obj, k) |
Left Shift | a << b |
lshift(a, b) |
Modulo | a % b |
mod(a, b) |
Multiplication | a * b |
mul(a, b) |
Negation (Arithmetic) | - a |
neg(a) |
Negation (Logical) | not a |
not_(a) |
Positive | + a |
pos(a) |
Right Shift | a >> b |
rshift(a, b) |
Sequence Repetition | seq * i |
repeat(seq, i) |
Slice Assignment | seq[i:j] = values |
setitem(seq, slice(i, j), values) |
Slice Deletion | del seq[i:j] |
delitem(seq, slice(i, j)) |
Slicing | seq[i:j] |
getitem(seq, slice(i, j)) |
String Formatting | s % obj |
mod(s, obj) |
Subtraction | a - b |
sub(a, b) |
Truth Test | obj |
truth(obj) |
Ordering | a < b |
lt(a, b) |
Ordering | a <= b |
le(a, b) |
Equality | a == b |
eq(a, b) |
Difference | a != b |
ne(a, b) |
Ordering | a >= b |
ge(a, b) |
Ordering | a > b |
gt(a, b) |
In [21]:
using Base.Meta
In [29]:
macro loop_ts(ex)
l, r = ex.args
@printf "%s, %s, %s" ex.head l r
idx =
if isexpr(l.args[2], :call)
filter(x -> isa(x, Symbol),
l.args[2].args[2:end])[1]
elseif isa(l.args[2], Symbol)
l.args[2]
end
offsets = extrema(vcat(get_offsets(l),
get_offsets(r)))
loopindex = :($(1 - offsets[1]):(length($(l.args[1]))
- $(offsets[2])))
quote
for $idx in $loopindex
$ex
end
end
end
In [24]:
function get_offsets(ex_::Expr)
isexpr(ex_,:call) &&
return [[get_offsets(a)
for a in ex_.args[2:end]]...]
isexpr(ex_,:ref) &&
return get_offset_from_ref(ex_.args[2])
warning("Not expecting to be here")
return Int64[]
end
get_offsets(x) = Int64[]
Out[24]:
In [25]:
get_offset_from_ref(s::Symbol) = 0
get_offset_from_ref(x::Number) = x
function get_offset_from_ref(ex_::Expr)
if isexpr(ex_,:call)
ex_.args[1] == :+ &&
return sum([get_offset_from_ref(a)
for a in ex_.args[2:end]])
ex_.args[1] == :- &&
return (get_offset_from_ref(ex_.args[2])
- sum([get_offset_from_ref(a)
for a in ex_.args[3:end]]))
end
warning("Didn’t expect to get here")
return(0)
end
Out[25]:
In [26]:
y = zeros(500)
e = randn(500)
@loop_ts y[t+1] = 0.8y[t] + 0.02y[t-2] + e[t+1]
In [27]:
y[500]
Out[27]:
In [30]:
macroexpand(:(@loop_ts y[t+1] = 0.8y[t] + 0.02y[t-2] + e[t+1]))
Out[30]:
In [ ]: