Meta Programming


In [115]:
prog = "1 + 1"


Out[115]:
"1 + 1"

In [116]:
@doc parse


Out[116]:
parse(str, start; greedy=true, raise=true)

Parse the expression string and return an expression (which could later be passed to eval for execution). start is the index of the first character to start parsing. If greedy is true (default), parse will try to consume as much input as it can; otherwise, it will stop as soon as it has parsed a valid expression. Incomplete but otherwise syntactically valid expressions will return Expr(:incomplete, "(error message)"). If raise is true (default), syntax errors other than incomplete expressions will raise an error. If raise is false, parse will return an expression that will raise an error upon evaluation.

parse(str; raise=true)

Parse the expression string greedily, returning a single expression. An error is thrown if there are additional characters after the first expression. If raise is true (default), syntax errors will raise an error; otherwise, parse will return an expression that will raise an error upon evaluation.

parse(type, str, [base])

Parse a string as a number. If the type is an integer type, then a base can be specified (the default is 10). If the type is a floating point type, the string is parsed as a decimal floating point number. If the string does not contain a valid number, an error is raised.


In [117]:
ex1 = parse(prog)


Out[117]:
:(1 + 1)

In [118]:
typeof(ex1)


Out[118]:
Expr

In [119]:
@doc Expr


Out[119]:

No documentation found.

Summary:

type Expr <: Any

Fields:

head :: Symbol
args :: Array{Any,1}
typ  :: Any

In [120]:
(ex1.head, ex1.args, ex1.typ)


Out[120]:
(:call,Any[:+,1,1],Any)

In [121]:
ex2 = Expr(:call, :+, 1, 1)


Out[121]:
:(1 + 1)

In [122]:
ex1 == ex2


Out[122]:
true

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]:
dump(x)

Show all user-visible structure of a value.


In [124]:
dump(ex2)


Expr 
  head: Symbol call
  args: Array(Any,(3,))
    1: Symbol +
    2: Int64 1
    3: Int64 1
  typ: Any

In [125]:
ex3 = parse("(4 + 4) / 2")


Out[125]:
:((4 + 4) / 2)

In [126]:
dump(ex3)


Expr 
  head: Symbol call
  args: Array(Any,(3,))
    1: Symbol /
    2: Expr 
      head: Symbol call
      args: Array(Any,(3,))
        1: Symbol +
        2: Int64 4
        3: Int64 4
      typ: Any
    3: Int64 2
  typ: Any

In [127]:
@doc Meta.show_sexpr


Out[127]:

No documentation found.

Base.Meta.show_sexpr is a generic Function.

# 5 methods for generic function "show_sexpr":
show_sexpr(io::IO, ex::QuoteNode, indent::Int64) at meta.jl:31
show_sexpr(io::IO, ex::Expr, indent::Int64) at meta.jl:37
show_sexpr(io::IO, ex) at meta.jl:25
show_sexpr(io::IO, ex, indent::Int64) at meta.jl:26
show_sexpr(ex) at meta.jl:24

In [128]:
Meta.show_sexpr(ex3)


(:call, :/, (:call, :+, 4, 4), 2)

In [129]:
:foo == symbol("foo")


Out[129]:
true

In [130]:
@doc symbol


Out[130]:
symbol(x...) -> Symbol

Create a Symbol by concatenating the string representations of the arguments together.


In [131]:
symbol(:var,'_',"sym")


Out[131]:
:var_sym

In [132]:
wow = :(::)


Out[132]:
:(::)

In [133]:
dump(wow)


Symbol ::

In [134]:
:(a+b*c+1)


Out[134]:
:(a + b * c + 1)

In [135]:
:(a + b*c + 1)  ==
       parse("a + b*c + 1") ==
       Expr(:call, :+, :a, Expr(:call, :*, :b, :c), 1)


Out[135]:
true

In [136]:
ex = quote
   x = 1
   y = 2
   x + y
end


Out[136]:
quote  # In[136], line 2:
    x = 1 # In[136], line 3:
    y = 2 # In[136], line 4:
    x + y
end

In [137]:
a = 1
ex = :($a + b)


Out[137]:
:(1 + b)

In [138]:
ex = :(a in $:((1,2,3)) )


Out[138]:
:($(Expr(:in, :a, :((1,2,3)))))

In [139]:
dump(ex)


Expr 
  head: Symbol in
  args: Array(Any,(2,))
    1: Symbol a
    2: Expr 
      head: Symbol tuple
      args: Array(Any,(3,))
        1: Int64 1
        2: Int64 2
        3: Int64 3
      typ: Any
  typ: Any

In [140]:
eval(ex)


Out[140]:
true

In [141]:
:(a in $:((1,2,3))) == :(a in $(:((1,2,3))))


Out[141]:
true

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]:
make_expr (generic function with 1 method)

In [143]:
make_expr(:+, 2, :x)


Out[143]:
:(4 + x)

In [144]:
macro sayhello(name)
   return :( println("Hello, ", $name) )
end

In [145]:
@sayhello "Julia"


Hello, Julia

In [146]:
@doc macroexpand


Out[146]:
macroexpand(x)

Takes the expression x and returns an equivalent expression with all macros removed (expanded).


In [147]:
macroexpand( :(@sayhello("human")) )


Out[147]:
:(println("Hello, ","human"))

In [148]:
macro showarg(x)
   show(x)
   # ... remainder of macro, returning an expression
end

In [149]:
@showarg 1+2


:(1 + 2)

In [150]:
macroexpand(:(@assert a==b))


Out[150]:
:(if a == b
        nothing
    else 
        Base.throw(Base.Main.Base.AssertionError("a == b"))
    end)

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


WARNING: replacing module MyModule
Out[151]:
MyModule

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]:
(6,"(2 cross 3)","(2 ∧ 3)")

In [153]:
@which 2 + 2


Out[153]:
+(x::Int64, y::Int64) at int.jl:8

In [154]:
@less 1 + 1


# This file is a part of Julia. License is MIT: http://julialang.org/license

## integer arithmetic ##

const IntTypes = (Int8, UInt8, Int16, UInt16, Int32, UInt32,
                  Int64, UInt64, Int128, UInt128)

+(x::Int, y::Int) = box(Int,add_int(unbox(Int,x),unbox(Int,y)))
<(x::Int, y::Int) = slt_int(unbox(Int,x),unbox(Int,y))

for T in IntTypes
    @eval begin
        -(x::$T) = box($T,neg_int(unbox($T,x)))

        if !($T === Int)  # don't overwrite definition from line 8
            +(x::$T, y::$T) = box($T, add_int(unbox($T,x),unbox($T,y)))
        end
        -(x::$T, y::$T) = box($T, sub_int(unbox($T,x),unbox($T,y)))
        *(x::$T, y::$T) = box($T, mul_int(unbox($T,x),unbox($T,y)))
    end
end

/(x::Integer, y::Integer) = float(x)/float(y)
inv(x::Integer) = float(one(x))/float(x)

isodd(n::Integer) = rem(n,2) != 0
iseven(n::Integer) = !isodd(n)

signbit(x::Integer) = x < 0
signbit(x::Unsigned) = false

for T in (Int8,Int16,Int32,Int64,Int128)
    @eval flipsign(x::$T, y::$T) = box($T,flipsign_int(unbox($T,x),unbox($T,y)))
end

flipsign(x::Signed, y::Signed)  = flipsign(promote(x,y)...)
flipsign(x::Signed, y::Float32) = flipsign(x, reinterpret(Int32,y))
flipsign(x::Signed, y::Float64) = flipsign(x, reinterpret(Int64,y))
flipsign(x::Signed, y::Real)    = flipsign(x, -oftype(x,signbit(y)))

copysign(x::Signed, y::Signed)  = flipsign(x, x$y)
copysign(x::Signed, y::Float32) = copysign(x, reinterpret(Int32,y))
copysign(x::Signed, y::Float64) = copysign(x, reinterpret(Int64,y))
copysign(x::Signed, y::Real)    = copysign(x, -oftype(x,signbit(y)))

abs(x::Unsigned) = x
abs(x::Signed) = flipsign(x,x)

~(n::Integer) = -n-1

unsigned(x::Signed) = reinterpret(typeof(convert(Unsigned,zero(x))), x)
unsigned(x::Bool) = convert(Unsigned, x)
unsigned(x) = convert(Unsigned, x)
signed(x::Unsigned) = reinterpret(typeof(convert(Signed,zero(x))), x)
signed(x) = convert(Signed, x)

div(x::Signed, y::Unsigned) = flipsign(signed(div(unsigned(abs(x)),y)),x)
div(x::Unsigned, y::Signed) = unsigned(flipsign(signed(div(x,unsigned(abs(y)))),y))

rem(x::Signed, y::Unsigned) = flipsign(signed(rem(unsigned(abs(x)),y)),x)
rem(x::Unsigned, y::Signed) = rem(x,unsigned(abs(y)))

fld(x::Signed, y::Unsigned) = div(x,y)-(signbit(x)&(rem(x,y)!=0))
fld(x::Unsigned, y::Signed) = div(x,y)-(signbit(y)&(rem(x,y)!=0))

mod(x::Signed, y::Unsigned) = rem(y+unsigned(rem(x,y)),y)
mod(x::Unsigned, y::Signed) = rem(y+signed(rem(x,y)),y)

cld(x::Signed, y::Unsigned) = div(x,y)+(!signbit(x)&(rem(x,y)!=0))
cld(x::Unsigned, y::Signed) = div(x,y)+(!signbit(y)&(rem(x,y)!=0))

# Don't promote integers for div/rem/mod since there no danger of overflow,
# while there is a substantial performance penalty to 64-bit promotion.
const Signed64Types = (Int8,Int16,Int32,Int64)
const Unsigned64Types = (UInt8,UInt16,UInt32,UInt64)
typealias Integer64 Union{Signed64Types...,Unsigned64Types...}

for T in Signed64Types
    @eval div(x::$T, y::$T) = box($T,sdiv_int(unbox($T,x),unbox($T,y)))
    @eval rem(x::$T, y::$T) = box($T,srem_int(unbox($T,x),unbox($T,y)))
    @eval mod(x::$T, y::$T) = box($T,smod_int(unbox($T,x),unbox($T,y)))
end
for T in Unsigned64Types
    @eval div(x::$T, y::$T) = box($T,udiv_int(unbox($T,x),unbox($T,y)))
    @eval rem(x::$T, y::$T) = box($T,urem_int(unbox($T,x),unbox($T,y)))
end

mod{T<:Unsigned}(x::T, y::T) = rem(x,y)

fld{T<:Unsigned}(x::T, y::T) = div(x,y)
fld{T<:Integer }(x::T, y::T) = div(x,y)-(signbit(x$y)&(rem(x,y)!=0))

cld{T<:Unsigned}(x::T, y::T) = div(x,y)+(rem(x,y)!=0)
cld{T<:Integer }(x::T, y::T) = div(x,y)+(!signbit(x$y)&(rem(x,y)!=0))

## integer bitwise operations ##

for T in IntTypes
    @eval begin
        ~(x::$T) = box($T,not_int(unbox($T,x)))

        (&)(x::$T, y::$T) = box($T,and_int(unbox($T,x),unbox($T,y)))
        (|)(x::$T, y::$T) = box($T, or_int(unbox($T,x),unbox($T,y)))
        ($)(x::$T, y::$T) = box($T,xor_int(unbox($T,x),unbox($T,y)))
    end
    for S in IntTypes
        (S === Int128 || S === UInt128) && continue
        @eval begin
            <<(x::$T,  y::$S) = box($T, shl_int(unbox($T,x),unbox($S,y)))
            >>>(x::$T, y::$S) = box($T,lshr_int(unbox($T,x),unbox($S,y)))
        end
        if issubtype(T,Unsigned)
            @eval >>(x::$T, y::$S) = box($T,lshr_int(unbox($T,x),unbox($S,y)))
        else
            @eval >>(x::$T, y::$S) = box($T,ashr_int(unbox($T,x),unbox($S,y)))
        end
    end
end

bswap(x::Int8)    = x
bswap(x::UInt8)   = x
bswap(x::Int16)   = box(Int16,bswap_int(unbox(Int16,x)))
bswap(x::UInt16)  = box(UInt16,bswap_int(unbox(UInt16,x)))
bswap(x::Int32)   = box(Int32,bswap_int(unbox(Int32,x)))
bswap(x::UInt32)  = box(UInt32,bswap_int(unbox(UInt32,x)))
bswap(x::Int64)   = box(Int64,bswap_int(unbox(Int64,x)))
bswap(x::UInt64)  = box(UInt64,bswap_int(unbox(UInt64,x)))
bswap(x::Int128)  = box(Int128,bswap_int(unbox(Int128,x)))
bswap(x::UInt128) = box(UInt128,bswap_int(unbox(UInt128,x)))

for T in IntTypes
    @eval begin
        count_ones(x::$T)     = Int(box($T,ctpop_int(unbox($T,x))))
        leading_zeros(x::$T)  = Int(box($T,ctlz_int(unbox($T,x))))
        trailing_zeros(x::$T) = Int(box($T,cttz_int(unbox($T,x))))
    end
end
count_zeros(  x::Integer) = count_ones(~x)
leading_ones( x::Integer) = leading_zeros(~x)
trailing_ones(x::Integer) = trailing_zeros(~x)

## integer comparisons ##

for T in IntTypes
    if issubtype(T,Signed)
        if !(T === Int)  # don't overwrite definition from line 9
            @eval <( x::$T, y::$T) = slt_int(unbox($T,x),unbox($T,y))
        end
        @eval <=(x::$T, y::$T) = sle_int(unbox($T,x),unbox($T,y))
    else
        @eval <( x::$T, y::$T) = ult_int(unbox($T,x),unbox($T,y))
        @eval <=(x::$T, y::$T) = ule_int(unbox($T,x),unbox($T,y))
    end
end

==(x::Signed,   y::Unsigned) = (x >= 0) & (unsigned(x) == y)
==(x::Unsigned, y::Signed  ) = (y >= 0) & (x == unsigned(y))
<( x::Signed,   y::Unsigned) = (x <  0) | (unsigned(x) <  y)
<( x::Unsigned, y::Signed  ) = (y >  0) & (x <  unsigned(y))
<=(x::Signed,   y::Unsigned) = (x <= 0) | (unsigned(x) <= y)
<=(x::Unsigned, y::Signed  ) = (y >= 0) & (x <= unsigned(y))

## integer conversions ##

for to in tuple(IntTypes...), from in tuple(IntTypes...,Bool)
    if !(to === from)
        if to.size < from.size
            if issubtype(to, Signed)
                if issubtype(from, Unsigned)
                    @eval convert(::Type{$to}, x::($from)) = box($to,checked_trunc_sint($to,check_top_bit(unbox($from,x))))
                else
                    @eval convert(::Type{$to}, x::($from)) = box($to,checked_trunc_sint($to,unbox($from,x)))
                end
            else
                @eval convert(::Type{$to}, x::($from)) = box($to,checked_trunc_uint($to,unbox($from,x)))
            end
            @eval rem(x::($from), ::Type{$to}) = box($to,trunc_int($to,unbox($from,x)))
        elseif from.size < to.size || from === Bool
            if issubtype(from, Signed)
                if issubtype(to, Unsigned)
                    @eval convert(::Type{$to}, x::($from)) = box($to,sext_int($to,check_top_bit(unbox($from,x))))
                else
                    @eval convert(::Type{$to}, x::($from)) = box($to,sext_int($to,unbox($from,x)))
                end
                @eval rem(x::($from), ::Type{$to}) = box($to,sext_int($to,unbox($from,x)))
            else
                @eval convert(::Type{$to}, x::($from)) = box($to,zext_int($to,unbox($from,x)))
                @eval rem(x::($from), ::Type{$to}) = convert($to,x)
            end
        else
            if !(issubtype(from,Signed) === issubtype(to,Signed))
                # raise InexactError if x's top bit is set
                @eval convert(::Type{$to}, x::($from)) = box($to,check_top_bit(unbox($from,x)))
            else
                @eval convert(::Type{$to}, x::($from)) = box($to,unbox($from,x))
            end
            @eval rem(x::($from), ::Type{$to}) = box($to,unbox($from,x))
        end
    end
end

rem{T<:Integer}(x::T, ::Type{T}) = x
rem(x::Integer, ::Type{Bool}) = ((x&1)!=0)
mod{T<:Integer}(x::Integer, ::Type{T}) = rem(x, T)

for to in (Int8, Int16, Int32, Int64)
    @eval begin
        convert(::Type{$to}, x::Float32) = box($to,checked_fptosi($to,unbox(Float32,x)))
        convert(::Type{$to}, x::Float64) = box($to,checked_fptosi($to,unbox(Float64,x)))
    end
end

for to in (UInt8, UInt16, UInt32, UInt64)
    @eval begin
        convert(::Type{$to}, x::Float32) = box($to,checked_fptoui($to,unbox(Float32,x)))
        convert(::Type{$to}, x::Float64) = box($to,checked_fptoui($to,unbox(Float64,x)))
    end
end

for Ti in (Int128,UInt128)
    for Tf in (Float32,Float64)
        @eval function convert(::Type{$Ti},x::$Tf)
            isinteger(x) || throw(InexactError())
            trunc($Ti,x)
        end
    end
end

convert(::Type{Signed}, x::UInt8  ) = convert(Int8,x)
convert(::Type{Signed}, x::UInt16 ) = convert(Int16,x)
convert(::Type{Signed}, x::UInt32 ) = convert(Int32,x)
convert(::Type{Signed}, x::UInt64 ) = convert(Int64,x)
convert(::Type{Signed}, x::UInt128) = convert(Int128,x)
convert(::Type{Signed}, x::Float32) = convert(Int,x)
convert(::Type{Signed}, x::Float64) = convert(Int,x)
convert(::Type{Signed}, x::Bool)    = convert(Int,x)

convert(::Type{Unsigned}, x::Int8   ) = convert(UInt8,x)
convert(::Type{Unsigned}, x::Int16  ) = convert(UInt16,x)
convert(::Type{Unsigned}, x::Int32  ) = convert(UInt32,x)
convert(::Type{Unsigned}, x::Int64  ) = convert(UInt64,x)
convert(::Type{Unsigned}, x::Int128 ) = convert(UInt128,x)
convert(::Type{Unsigned}, x::Float32) = convert(UInt,x)
convert(::Type{Unsigned}, x::Float64) = convert(UInt,x)
convert(::Type{Unsigned}, x::Bool)    = convert(UInt,x)

convert(::Type{Integer}, x::Integer) = x
convert(::Type{Integer}, x::Real) = convert(Signed,x)

round(x::Integer) = x
trunc(x::Integer) = x
floor(x::Integer) = x
 ceil(x::Integer) = x

round{T<:Integer}(::Type{T},x::Integer) = convert(T,x)
trunc{T<:Integer}(::Type{T},x::Integer) = convert(T,x)
floor{T<:Integer}(::Type{T},x::Integer) = convert(T,x)
 ceil{T<:Integer}(::Type{T},x::Integer) = convert(T,x)

## integer construction ##

macro int128_str(s)
    parse(Int128,s)
end

macro uint128_str(s)
    parse(UInt128,s)
end

macro big_str(s)
    n = tryparse(BigInt,s)
    !isnull(n) && return get(n)
    n = tryparse(BigFloat,s)
    !isnull(n) && return get(n)
    message = "invalid number format $s for BigInt or BigFloat"
    :(throw(ArgumentError($message)))
end

## system word size ##

const WORD_SIZE = Int(Int.size)*8

## integer promotions ##

promote_rule(::Type{Int16},  ::Type{Int8} ) = Int16
promote_rule(::Type{Int32},  ::Type{Int8} ) = Int32
promote_rule(::Type{Int32},  ::Type{Int16}) = Int32
promote_rule(::Type{Int64},  ::Type{Int8} ) = Int64
promote_rule(::Type{Int64},  ::Type{Int16}) = Int64
promote_rule(::Type{Int64},  ::Type{Int32}) = Int64
promote_rule(::Type{Int128}, ::Type{Int8} ) = Int128
promote_rule(::Type{Int128}, ::Type{Int16}) = Int128
promote_rule(::Type{Int128}, ::Type{Int32}) = Int128
promote_rule(::Type{Int128}, ::Type{Int64}) = Int128

promote_rule(::Type{UInt16},  ::Type{UInt8} ) = UInt16
promote_rule(::Type{UInt32},  ::Type{UInt8} ) = UInt32
promote_rule(::Type{UInt32},  ::Type{UInt16}) = UInt32
promote_rule(::Type{UInt64},  ::Type{UInt8} ) = UInt64
promote_rule(::Type{UInt64},  ::Type{UInt16}) = UInt64
promote_rule(::Type{UInt64},  ::Type{UInt32}) = UInt64
promote_rule(::Type{UInt128}, ::Type{UInt8} ) = UInt128
promote_rule(::Type{UInt128}, ::Type{UInt16}) = UInt128
promote_rule(::Type{UInt128}, ::Type{UInt32}) = UInt128
promote_rule(::Type{UInt128}, ::Type{UInt64}) = UInt128

promote_rule(::Type{UInt8}, ::Type{Int8}  ) = Int
promote_rule(::Type{UInt8}, ::Type{Int16} ) = Int
promote_rule(::Type{UInt8}, ::Type{Int32} ) = Int
promote_rule(::Type{UInt8}, ::Type{Int64} ) = Int64
promote_rule(::Type{UInt8}, ::Type{Int128}) = Int128

promote_rule(::Type{UInt16}, ::Type{Int8}  ) = Int
promote_rule(::Type{UInt16}, ::Type{Int16} ) = Int
promote_rule(::Type{UInt16}, ::Type{Int32} ) = Int
promote_rule(::Type{UInt16}, ::Type{Int64} ) = Int64
promote_rule(::Type{UInt16}, ::Type{Int128}) = Int128

if WORD_SIZE == 64
    promote_rule(::Type{UInt32}, ::Type{Int8} ) = Int
    promote_rule(::Type{UInt32}, ::Type{Int16}) = Int
    promote_rule(::Type{UInt32}, ::Type{Int32}) = Int
else
    promote_rule(::Type{UInt32}, ::Type{Int8} ) = UInt
    promote_rule(::Type{UInt32}, ::Type{Int16}) = UInt
    promote_rule(::Type{UInt32}, ::Type{Int32}) = UInt
end
promote_rule(::Type{UInt32}, ::Type{Int64} ) = Int64
promote_rule(::Type{UInt32}, ::Type{Int128}) = Int128

promote_rule(::Type{UInt64}, ::Type{Int8}  ) = UInt64
promote_rule(::Type{UInt64}, ::Type{Int16} ) = UInt64
promote_rule(::Type{UInt64}, ::Type{Int32} ) = UInt64
promote_rule(::Type{UInt64}, ::Type{Int64} ) = UInt64
promote_rule(::Type{UInt64}, ::Type{Int128}) = Int128

promote_rule(::Type{UInt128}, ::Type{Int8}  ) = UInt128
promote_rule(::Type{UInt128}, ::Type{Int16} ) = UInt128
promote_rule(::Type{UInt128}, ::Type{Int32} ) = UInt128
promote_rule(::Type{UInt128}, ::Type{Int64} ) = UInt128
promote_rule(::Type{UInt128}, ::Type{Int128}) = UInt128

## traits ##

typemin(::Type{Int8  }) = Int8(-128)
typemax(::Type{Int8  }) = Int8(127)
typemin(::Type{UInt8 }) = UInt8(0)
typemax(::Type{UInt8 }) = UInt8(255)
typemin(::Type{Int16 }) = Int16(-32768)
typemax(::Type{Int16 }) = Int16(32767)
typemin(::Type{UInt16}) = UInt16(0)
typemax(::Type{UInt16}) = UInt16(65535)
typemin(::Type{Int32 }) = Int32(-2147483648)
typemax(::Type{Int32 }) = Int32(2147483647)
typemin(::Type{UInt32}) = UInt32(0)
typemax(::Type{UInt32}) = UInt32(4294967295)
typemin(::Type{Int64 }) = -9223372036854775808
typemax(::Type{Int64 }) = 9223372036854775807
typemin(::Type{UInt64}) = UInt64(0)
typemax(::Type{UInt64}) = 0xffffffffffffffff
@eval typemin(::Type{UInt128}) = $(UInt128(0))
@eval typemax(::Type{UInt128}) = $(box(UInt128,unbox(Int128,convert(Int128,-1))))
@eval typemin(::Type{Int128} ) = $(convert(Int128,1)<<127)
@eval typemax(::Type{Int128} ) = $(box(Int128,unbox(UInt128,typemax(UInt128)>>1)))

widen(::Type{Int8}) = Int
widen(::Type{Int16}) = Int
widen(::Type{Int32}) = Int64
widen(::Type{Int64}) = Int128
widen(::Type{UInt8}) = UInt
widen(::Type{UInt16}) = UInt
widen(::Type{UInt32}) = UInt64
widen(::Type{UInt64}) = UInt128

# a few special cases,
# Int64*UInt64 => Int128
# |x|<=2^(k-1), |y|<=2^k-1   =>   |x*y|<=2^(2k-1)-1
widemul(x::Signed,y::Unsigned) = widen(x)*signed(widen(y))
widemul(x::Unsigned,y::Signed) = signed(widen(x))*widen(y)
# multplication by Bool doesn't require widening
widemul(x::Bool,y::Bool) = x*y
widemul(x::Bool,y::Number) = x*y
widemul(x::Number,y::Bool) = x*y


## wide multiplication, Int128 multiply and divide ##

if WORD_SIZE == 32
    function widemul(u::Int64, v::Int64)
        local u0::UInt64, v0::UInt64, w0::UInt64
        local u1::Int64, v1::Int64, w1::UInt64, w2::Int64, t::UInt64

        u0 = u&0xffffffff; u1 = u>>32
        v0 = v&0xffffffff; v1 = v>>32
        w0 = u0*v0
        t = reinterpret(UInt64,u1)*v0 + (w0>>>32)
        w2 = reinterpret(Int64,t) >> 32
        w1 = u0*reinterpret(UInt64,v1) + (t&0xffffffff)
        hi = u1*v1 + w2 + (reinterpret(Int64,w1) >> 32)
        lo = w0&0xffffffff + (w1 << 32)
        Int128(hi)<<64 + Int128(lo)
    end

    function widemul(u::UInt64, v::UInt64)
        local u0::UInt64, v0::UInt64, w0::UInt64
        local u1::UInt64, v1::UInt64, w1::UInt64, w2::UInt64, t::UInt64

        u0 = u&0xffffffff; u1 = u>>>32
        v0 = v&0xffffffff; v1 = v>>>32
        w0 = u0*v0
        t = u1*v0 + (w0>>>32)
        w2 = t>>>32
        w1 = u0*v1 + (t&0xffffffff)
        hi = u1*v1 + w2 + (w1 >>> 32)
        lo = w0&0xffffffff + (w1 << 32)
        UInt128(hi)<<64 + UInt128(lo)
    end

    function *(u::Int128, v::Int128)
        u0 = u % UInt64; u1 = Int64(u>>64)
        v0 = v % UInt64; v1 = Int64(v>>64)
        lolo = widemul(u0, v0)
        lohi = widemul(reinterpret(Int64,u0), v1)
        hilo = widemul(u1, reinterpret(Int64,v0))
        t = reinterpret(UInt128,hilo) + (lolo>>>64)
        w1 = reinterpret(UInt128,lohi) + (t&0xffffffffffffffff)
        Int128(lolo&0xffffffffffffffff) + reinterpret(Int128,w1)<<64
    end

    function *(u::UInt128, v::UInt128)
        u0 = u % UInt64; u1 = UInt64(u>>>64)
        v0 = v % UInt64; v1 = UInt64(v>>>64)
        lolo = widemul(u0, v0)
        lohi = widemul(u0, v1)
        hilo = widemul(u1, v0)
        t = hilo + (lolo>>>64)
        w1 = lohi + (t&0xffffffffffffffff)
        (lolo&0xffffffffffffffff) + UInt128(w1)<<64
    end

    div(x::Int128, y::Int128) = Int128(div(BigInt(x),BigInt(y)))
    div(x::UInt128, y::UInt128) = UInt128(div(BigInt(x),BigInt(y)))

    rem(x::Int128, y::Int128) = Int128(rem(BigInt(x),BigInt(y)))
    rem(x::UInt128, y::UInt128) = UInt128(rem(BigInt(x),BigInt(y)))

    mod(x::Int128, y::Int128) = Int128(mod(BigInt(x),BigInt(y)))

    <<( x::Int128,  y::Int) = y == 0 ? x : box(Int128,shl_int(unbox(Int128,x),unbox(Int,y)))
    <<( x::UInt128, y::Int) = y == 0 ? x : box(UInt128,shl_int(unbox(UInt128,x),unbox(Int,y)))
    >>( x::Int128,  y::Int) = y == 0 ? x : box(Int128,ashr_int(unbox(Int128,x),unbox(Int,y)))
    >>( x::UInt128, y::Int) = y == 0 ? x : box(UInt128,lshr_int(unbox(UInt128,x),unbox(Int,y)))
    >>>(x::Int128,  y::Int) = y == 0 ? x : box(Int128,lshr_int(unbox(Int128,x),unbox(Int,y)))
    >>>(x::UInt128, y::Int) = y == 0 ? x : box(UInt128,lshr_int(unbox(UInt128,x),unbox(Int,y)))
else
    *(x::Int128,  y::Int128)  = box(Int128,mul_int(unbox(Int128,x),unbox(Int128,y)))
    *(x::UInt128, y::UInt128) = box(UInt128,mul_int(unbox(UInt128,x),unbox(UInt128,y)))

    div(x::Int128,  y::Int128)  = box(Int128,sdiv_int(unbox(Int128,x),unbox(Int128,y)))
    div(x::UInt128, y::UInt128) = box(UInt128,udiv_int(unbox(UInt128,x),unbox(UInt128,y)))

    rem(x::Int128,  y::Int128)  = box(Int128,srem_int(unbox(Int128,x),unbox(Int128,y)))
    rem(x::UInt128, y::UInt128) = box(UInt128,urem_int(unbox(UInt128,x),unbox(UInt128,y)))

    mod(x::Int128, y::Int128) = box(Int128,smod_int(unbox(Int128,x),unbox(Int128,y)))
end

## checked +, - and *

# requires int arithmetic defined, for the loops to work

for T in (Int8,Int16,Int32,Int64)#,Int128) ## FIXME: #4905
    @eval begin
        checked_add(x::$T, y::$T) = box($T,checked_sadd(unbox($T,x),unbox($T,y)))
        checked_sub(x::$T, y::$T) = box($T,checked_ssub(unbox($T,x),unbox($T,y)))
    end
end
for T in (Int16,Int32)
    @eval begin
        checked_mul(x::$T, y::$T) = box($T,checked_smul(unbox($T,x),unbox($T,y)))
    end
end
for T in (UInt8,UInt16,UInt32,UInt64)#,UInt128) ## FIXME: #4905
    @eval begin
        checked_add(x::$T, y::$T) = box($T,checked_uadd(unbox($T,x),unbox($T,y)))
        checked_sub(x::$T, y::$T) = box($T,checked_usub(unbox($T,x),unbox($T,y)))
    end
end
for T in (UInt16,UInt32)
    @eval begin
        checked_mul(x::$T, y::$T) = box($T,checked_umul(unbox($T,x),unbox($T,y)))
    end
end

# checked mul is broken for 8-bit types (LLVM bug?) ## FIXME: #4905

for T in (Int8,UInt8)
    @eval function checked_mul(x::$T, y::$T)
        xy = widemul(x,y)
        (typemin($T) <= xy <= typemax($T)) || throw(OverflowError())
        return xy % $T
    end
end

if WORD_SIZE == 32
    for T in (Int64,UInt64)
        @eval function checked_mul(x::$T, y::$T)
            xy = Int128(x)*Int128(y)
            (typemin($T) <= xy <= typemax($T)) || throw(OverflowError())
            return xy % $T
        end
    end
else
    checked_mul(x::Int64, y::Int64)   = box(Int64,checked_smul(unbox(Int64,x),unbox(Int64,y)))
    checked_mul(x::UInt64, y::UInt64) = box(UInt64,checked_umul(unbox(UInt64,x),unbox(UInt64,y)))
end

# checked ops are broken for 128-bit types (LLVM bug) ## FIXME: #4905

checked_add(x::Int128, y::Int128) = x + y
checked_sub(x::Int128, y::Int128) = x - y
checked_mul(x::Int128, y::Int128) = x * y

checked_add(x::UInt128, y::UInt128) = x + y
checked_sub(x::UInt128, y::UInt128) = x - y
checked_mul(x::UInt128, y::UInt128) = x * y

In [155]:
@edit 1 + 1


Unknown editor: no line number information passed.
The method is defined at line 8.

In [156]:
clipboard(:(1+1))
# Paste then we get
1 + 1


Out[156]:
2

In [157]:
apropos("IPv6")


parseip
IPv6
listen
recvfrom

In [158]:
methods(+)


Out[158]:
171 methods for generic function +:

In [159]:
methodswith(Real)


Out[159]:
326-element Array{Method,1}:

In [160]:
methodswith(Real, +)


Out[160]:
4-element Array{Method,1}:

In [161]:
object_id(+)


Out[161]:
0x489bea67662baecd

In [162]:
@which getfield


Out[162]:
Core

In [181]:
@doc getfield


Out[181]:
getfield(value, name::Symbol)

Extract a named field from a value of composite type. The syntax a.b calls getfield(a, :b), and the syntax a.(b) calls getfield(a, b).


In [163]:
type Experiment
    a::Int64
    b::Function
    c::AbstractString
end

In [164]:
expm = Experiment(100, +, "A String")


Out[164]:
Experiment(100,+,"A String")

In [165]:
expm.(:c)


Out[165]:
"A String"

In [166]:
expm.c


Out[166]:
"A String"

In [167]:
symbolc = "c"
expm.(symbol(symbolc))


Out[167]:
"A String"

In [168]:
fieldoffsets(Experiment)


Out[168]:
3-element Array{Int64,1}:
  0
  8
 16

In [169]:
structinfo(T) = [zip(fieldoffsets(T),fieldnames(T),T.types)...]


Out[169]:
structinfo (generic function with 1 method)

In [170]:
structinfo(Experiment)


Out[170]:
3-element Array{Tuple{Int64,Symbol,DataType},1}:
 (0,:a,Int64)          
 (8,:b,Function)       
 (16,:c,AbstractString)

In [171]:
expm.b(1, 3)


Out[171]:
4

In [172]:
method_exists(+, Tuple{Real})


Out[172]:
true

In [173]:
applicable(+, 1)


Out[173]:
true

In [174]:
applicable(+, "1")


Out[174]:
false

In [175]:
@doc invoke


Out[175]:
invoke(f, (types...), args...)

Invoke a method for the given generic function matching the specified types (as a tuple), on the specified arguments. The arguments must be compatible with the specified types. This allows invoking a method other than the most specific matching method, which is useful when the behavior of a more general definition is explicitly needed (often as part of the implementation of a more specific method of the same function).


In [176]:
invoke(+, (Float64, Float64), 1.0, 1.0)


Out[176]:
2.0

In [177]:
[1:5;] |> x->x.^2 |> sum |> inv == inv(sum([1:5;].^2))


Out[177]:
true

In [178]:
@doc call


Out[178]:
call(x, args...)

If x is not a Function, then x(args...) is equivalent to call(x, args...). This means that function-like behavior can be added to any type by defining new call methods.


In [179]:
call(m::Experiment, s::AbstractString) = parse(s)


Out[179]:
call (generic function with 1087 methods)

In [180]:
expm("123")


Out[180]:
123

In [184]:
@doc @gensym


Out[184]:
@gensym

Generates a gensym symbol for a variable. For example, @gensym x y is transformed into x = gensym("x"); y = gensym("y").


In [195]:
@doc @elapsed


Out[195]:
@elapsed

A macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute as a floating-point number.


In [186]:
@elapsed sleep(1)


Out[186]:
1.046363498

In [196]:
@doc @allocated


Out[196]:
@allocated

A macro to evaluate an expression, discarding the resulting value, instead returning the total number of bytes allocated during evaluation of the expression. Note: the expression is evaluated inside a local function, instead of the current context, in order to eliminate the effects of compilation, however, there still may be some allocations due to JIT compilation. This also makes the results inconsistent with the @time macros, which do not try to adjust for the effects of compilation.


In [187]:
@allocated [1, 2, 3]


Out[187]:
96

In [188]:
@allocated [1]


Out[188]:
80

In [189]:
@allocated 1


Out[189]:
0

In [194]:
(@allocated(collect(range(0, 1000))) - @allocated([]))/1000


Out[194]:
8.048

In [200]:
(ff, fl) = functionloc(+, (Real, Real))


Out[200]:
("/opt/homebrew-cask/Caskroom/julia/0.4.5/Julia-0.4.5.app/Contents/Resources/julia/bin/../share/julia/base/promotion.jl",211)

In [201]:
less(ff, fl)


# This file is a part of Julia. License is MIT: http://julialang.org/license

## type join (closest common ancestor, or least upper bound) ##

typejoin() = Bottom
typejoin(t::ANY) = t
typejoin(t::ANY, ts...) = typejoin(t, typejoin(ts...))
function typejoin(a::ANY, b::ANY)
    if isa(a,TypeConstructor); a = a.body; end
    if isa(b,TypeConstructor); b = b.body; end
    if a <: b
        return b
    elseif b <: a
        return a
    end
    if isa(a,TypeVar)
        return typejoin(a.ub, b)
    end
    if isa(b,TypeVar)
        return typejoin(a, b.ub)
    end
    if isa(a,Union) || isa(b,Union)
        u = Union{a, b}
        if !isa(u,Union)
            return u
        end
        return reduce(typejoin, Bottom, u.types)
    end
    if a <: Tuple
        if !(b <: Tuple)
            return Any
        end
        ap, bp = a.parameters, b.parameters
        la = length(ap)::Int; lb = length(bp)::Int
        if la==0 || lb==0
            return Tuple
        end
        if la < lb
            if isvarargtype(ap[la])
                c = cell(la)
                c[la] = Vararg{typejoin(ap[la].parameters[1], tailjoin(bp,la))}
                n = la-1
            else
                c = cell(la+1)
                c[la+1] = Vararg{tailjoin(bp,la+1)}
                n = la
            end
        elseif lb < la
            if isvarargtype(bp[lb])
                c = cell(lb)
                c[lb] = Vararg{typejoin(bp[lb].parameters[1], tailjoin(ap,lb))}
                n = lb-1
            else
                c = cell(lb+1)
                c[lb+1] = Vararg{tailjoin(ap,lb+1)}
                n = lb
            end
        else
            c = cell(la)
            n = la
        end
        for i = 1:n
            ai = ap[i]; bi = bp[i]
            ci = typejoin(unwrapva(ai),unwrapva(bi))
            c[i] = isvarargtype(ai) || isvarargtype(bi) ? Vararg{ci} : ci
        end
        return Tuple{c...}
    elseif b <: Tuple
        return Any
    end
    while !is(b,Any)
        if a <: b.name.primary
            while a.name !== b.name
                a = super(a)
            end
            # join on parameters
            n = length(a.parameters)
            p = cell(n)
            for i = 1:n
                ai, bi = a.parameters[i], b.parameters[i]
                if ai === bi || (isa(ai,Type) && isa(bi,Type) && typeseq(ai,bi))
                    p[i] = ai
                else
                    p[i] = a.name.primary.parameters[i]
                end
            end
            return a.name.primary{p...}
        end
        b = super(b)
    end
    return Any
end

# reduce typejoin over A[i:end]
function tailjoin(A, i)
    t = Bottom
    for j = i:length(A)
        t = typejoin(t, unwrapva(A[j]))
    end
    return t
end

## promotion mechanism ##

promote_type()  = Bottom
promote_type(T) = T
promote_type(T, S, U, V...) = promote_type(T, promote_type(S, U, V...))

promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom
promote_type{T}(::Type{T}, ::Type{T}) = T
promote_type{T}(::Type{T}, ::Type{Bottom}) = T
promote_type{T}(::Type{Bottom}, ::Type{T}) = T

# Try promote_rule in both orders. Typically only one is defined,
# and there is a fallback returning Bottom below, so the common case is
#   promote_type(T, S) =>
#   promote_result(T, S, result, Bottom) =>
#   typejoin(result, Bottom) => result
promote_type{T,S}(::Type{T}, ::Type{S}) =
    promote_result(T, S, promote_rule(T,S), promote_rule(S,T))

promote_rule(T, S) = Bottom

promote_result(t,s,T,S) = promote_type(T,S)
# If no promote_rule is defined, both directions give Bottom. In that
# case use typejoin on the original types instead.
promote_result{T,S}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) = typejoin(T, S)

promote() = ()
promote(x) = (x,)
function promote{T,S}(x::T, y::S)
    (convert(promote_type(T,S),x), convert(promote_type(T,S),y))
end
promote_typeof(x) = typeof(x)
promote_typeof(x, xs...) = promote_type(typeof(x), promote_typeof(xs...))
function promote(x, y, z)
    (convert(promote_typeof(x,y,z), x),
     convert(promote_typeof(x,y,z), y),
     convert(promote_typeof(x,y,z), z))
end
function promote(x, y, zs...)
    (convert(promote_typeof(x,y,zs...), x),
     convert(promote_typeof(x,y,zs...), y),
     convert(Tuple{Vararg{promote_typeof(x,y,zs...)}}, zs)...)
end
# TODO: promote{T}(x::T, ys::T...) here to catch all circularities?

## promotions in arithmetic, etc. ##

# Because of the promoting fallback definitions for Number, we need
# a special case for undefined promote_rule on numeric types.
# Otherwise, typejoin(T,S) is called (returning Number) so no conversion
# happens, and +(promote(x,y)...) is called again, causing a stack
# overflow.
promote_result{T<:Number,S<:Number}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) =
    promote_to_super(T, S, typejoin(T,S))

# promote numeric types T and S to typejoin(T,S) if T<:S or S<:T
# for example this makes promote_type(Integer,Real) == Real without
# promoting arbitrary pairs of numeric types to Number.
promote_to_super{T<:Number          }(::Type{T}, ::Type{T}, ::Type{T}) = T
promote_to_super{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type{T}) = T
promote_to_super{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type{S}) = S
promote_to_super{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type) =
    error("no promotion exists for ", T, " and ", S)

+(x::Number, y::Number) = +(promote(x,y)...)
*(x::Number, y::Number) = *(promote(x,y)...)
-(x::Number, y::Number) = -(promote(x,y)...)
/(x::Number, y::Number) = /(promote(x,y)...)
^(x::Number, y::Number) = ^(promote(x,y)...)

fma(x::Number, y::Number, z::Number) = fma(promote(x,y,z)...)
muladd(x::Number, y::Number, z::Number) = muladd(promote(x,y,z)...)

(&)(x::Integer, y::Integer) = (&)(promote(x,y)...)
(|)(x::Integer, y::Integer) = (|)(promote(x,y)...)
($)(x::Integer, y::Integer) = ($)(promote(x,y)...)

==(x::Number, y::Number) = (==)(promote(x,y)...)
<( x::Real, y::Real)     = (< )(promote(x,y)...)
<=(x::Real, y::Real)     = (<=)(promote(x,y)...)

div(x::Real, y::Real) = div(promote(x,y)...)
fld(x::Real, y::Real) = fld(promote(x,y)...)
cld(x::Real, y::Real) = cld(promote(x,y)...)
rem(x::Real, y::Real) = rem(promote(x,y)...)
mod(x::Real, y::Real) = mod(promote(x,y)...)

mod1(x::Real, y::Real) = mod1(promote(x,y)...)
rem1(x::Real, y::Real) = rem1(promote(x,y)...)
fld1(x::Real, y::Real) = fld1(promote(x,y)...)

max(x::Real, y::Real) = max(promote(x,y)...)
min(x::Real, y::Real) = min(promote(x,y)...)
minmax(x::Real, y::Real) = minmax(promote(x, y)...)

checked_add(x::Integer, y::Integer) = checked_add(promote(x,y)...)
checked_sub(x::Integer, y::Integer) = checked_sub(promote(x,y)...)
checked_mul(x::Integer, y::Integer) = checked_mul(promote(x,y)...)

# "Promotion" that takes a Functor into account. You can override this
# as needed. For example, if you need to provide a custom result type
# for the multiplication of two types,
#   promote_op{R<:MyType,S<:MyType}(::MulFun, ::Type{R}, ::Type{S}) = MyType{multype(R,S)}
promote_op{R,S}(::Any, ::Type{R}, ::Type{S}) = promote_type(R, S)

## catch-alls to prevent infinite recursion when definitions are missing ##

no_op_err(name, T) = error(name," not defined for ",T)
+{T<:Number}(x::T, y::T) = no_op_err("+", T)
*{T<:Number}(x::T, y::T) = no_op_err("*", T)
-{T<:Number}(x::T, y::T) = no_op_err("-", T)
/{T<:Number}(x::T, y::T) = no_op_err("/", T)
^{T<:Number}(x::T, y::T) = no_op_err("^", T)

fma{T<:Number}(x::T, y::T, z::T) = no_op_err("fma", T)
fma(x::Integer, y::Integer, z::Integer) = x*y+z
muladd{T<:Number}(x::T, y::T, z::T) = x*y+z

(&){T<:Integer}(x::T, y::T) = no_op_err("&", T)
(|){T<:Integer}(x::T, y::T) = no_op_err("|", T)
($){T<:Integer}(x::T, y::T) = no_op_err("\$", T)

=={T<:Number}(x::T, y::T) = x === y
 <{T<:Real}(x::T, y::T) = no_op_err("<" , T)
<={T<:Real}(x::T, y::T) = no_op_err("<=", T)

div{T<:Real}(x::T, y::T) = no_op_err("div", T)
fld{T<:Real}(x::T, y::T) = no_op_err("fld", T)
cld{T<:Real}(x::T, y::T) = no_op_err("cld", T)
rem{T<:Real}(x::T, y::T) = no_op_err("rem", T)
mod{T<:Real}(x::T, y::T) = no_op_err("mod", T)

mod1{T<:Real}(x::T, y::T) = no_op_err("mod1", T)
rem1{T<:Real}(x::T, y::T) = no_op_err("rem1", T)
fld1{T<:Real}(x::T, y::T) = no_op_err("fld1", T)

max{T<:Real}(x::T, y::T) = ifelse(y < x, x, y)
min{T<:Real}(x::T, y::T) = ifelse(y < x, y, x)
minmax{T<:Real}(x::T, y::T) = y < x ? (y, x) : (x, y)

checked_add{T<:Integer}(x::T, y::T) = no_op_err("checked_add", T)
checked_sub{T<:Integer}(x::T, y::T) = no_op_err("checked_sub", T)
checked_mul{T<:Integer}(x::T, y::T) = no_op_err("checked_mul", T)

In [202]:
less(+, (Real, Real))


# This file is a part of Julia. License is MIT: http://julialang.org/license

## type join (closest common ancestor, or least upper bound) ##

typejoin() = Bottom
typejoin(t::ANY) = t
typejoin(t::ANY, ts...) = typejoin(t, typejoin(ts...))
function typejoin(a::ANY, b::ANY)
    if isa(a,TypeConstructor); a = a.body; end
    if isa(b,TypeConstructor); b = b.body; end
    if a <: b
        return b
    elseif b <: a
        return a
    end
    if isa(a,TypeVar)
        return typejoin(a.ub, b)
    end
    if isa(b,TypeVar)
        return typejoin(a, b.ub)
    end
    if isa(a,Union) || isa(b,Union)
        u = Union{a, b}
        if !isa(u,Union)
            return u
        end
        return reduce(typejoin, Bottom, u.types)
    end
    if a <: Tuple
        if !(b <: Tuple)
            return Any
        end
        ap, bp = a.parameters, b.parameters
        la = length(ap)::Int; lb = length(bp)::Int
        if la==0 || lb==0
            return Tuple
        end
        if la < lb
            if isvarargtype(ap[la])
                c = cell(la)
                c[la] = Vararg{typejoin(ap[la].parameters[1], tailjoin(bp,la))}
                n = la-1
            else
                c = cell(la+1)
                c[la+1] = Vararg{tailjoin(bp,la+1)}
                n = la
            end
        elseif lb < la
            if isvarargtype(bp[lb])
                c = cell(lb)
                c[lb] = Vararg{typejoin(bp[lb].parameters[1], tailjoin(ap,lb))}
                n = lb-1
            else
                c = cell(lb+1)
                c[lb+1] = Vararg{tailjoin(ap,lb+1)}
                n = lb
            end
        else
            c = cell(la)
            n = la
        end
        for i = 1:n
            ai = ap[i]; bi = bp[i]
            ci = typejoin(unwrapva(ai),unwrapva(bi))
            c[i] = isvarargtype(ai) || isvarargtype(bi) ? Vararg{ci} : ci
        end
        return Tuple{c...}
    elseif b <: Tuple
        return Any
    end
    while !is(b,Any)
        if a <: b.name.primary
            while a.name !== b.name
                a = super(a)
            end
            # join on parameters
            n = length(a.parameters)
            p = cell(n)
            for i = 1:n
                ai, bi = a.parameters[i], b.parameters[i]
                if ai === bi || (isa(ai,Type) && isa(bi,Type) && typeseq(ai,bi))
                    p[i] = ai
                else
                    p[i] = a.name.primary.parameters[i]
                end
            end
            return a.name.primary{p...}
        end
        b = super(b)
    end
    return Any
end

# reduce typejoin over A[i:end]
function tailjoin(A, i)
    t = Bottom
    for j = i:length(A)
        t = typejoin(t, unwrapva(A[j]))
    end
    return t
end

## promotion mechanism ##

promote_type()  = Bottom
promote_type(T) = T
promote_type(T, S, U, V...) = promote_type(T, promote_type(S, U, V...))

promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom
promote_type{T}(::Type{T}, ::Type{T}) = T
promote_type{T}(::Type{T}, ::Type{Bottom}) = T
promote_type{T}(::Type{Bottom}, ::Type{T}) = T

# Try promote_rule in both orders. Typically only one is defined,
# and there is a fallback returning Bottom below, so the common case is
#   promote_type(T, S) =>
#   promote_result(T, S, result, Bottom) =>
#   typejoin(result, Bottom) => result
promote_type{T,S}(::Type{T}, ::Type{S}) =
    promote_result(T, S, promote_rule(T,S), promote_rule(S,T))

promote_rule(T, S) = Bottom

promote_result(t,s,T,S) = promote_type(T,S)
# If no promote_rule is defined, both directions give Bottom. In that
# case use typejoin on the original types instead.
promote_result{T,S}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) = typejoin(T, S)

promote() = ()
promote(x) = (x,)
function promote{T,S}(x::T, y::S)
    (convert(promote_type(T,S),x), convert(promote_type(T,S),y))
end
promote_typeof(x) = typeof(x)
promote_typeof(x, xs...) = promote_type(typeof(x), promote_typeof(xs...))
function promote(x, y, z)
    (convert(promote_typeof(x,y,z), x),
     convert(promote_typeof(x,y,z), y),
     convert(promote_typeof(x,y,z), z))
end
function promote(x, y, zs...)
    (convert(promote_typeof(x,y,zs...), x),
     convert(promote_typeof(x,y,zs...), y),
     convert(Tuple{Vararg{promote_typeof(x,y,zs...)}}, zs)...)
end
# TODO: promote{T}(x::T, ys::T...) here to catch all circularities?

## promotions in arithmetic, etc. ##

# Because of the promoting fallback definitions for Number, we need
# a special case for undefined promote_rule on numeric types.
# Otherwise, typejoin(T,S) is called (returning Number) so no conversion
# happens, and +(promote(x,y)...) is called again, causing a stack
# overflow.
promote_result{T<:Number,S<:Number}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) =
    promote_to_super(T, S, typejoin(T,S))

# promote numeric types T and S to typejoin(T,S) if T<:S or S<:T
# for example this makes promote_type(Integer,Real) == Real without
# promoting arbitrary pairs of numeric types to Number.
promote_to_super{T<:Number          }(::Type{T}, ::Type{T}, ::Type{T}) = T
promote_to_super{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type{T}) = T
promote_to_super{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type{S}) = S
promote_to_super{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type) =
    error("no promotion exists for ", T, " and ", S)

+(x::Number, y::Number) = +(promote(x,y)...)
*(x::Number, y::Number) = *(promote(x,y)...)
-(x::Number, y::Number) = -(promote(x,y)...)
/(x::Number, y::Number) = /(promote(x,y)...)
^(x::Number, y::Number) = ^(promote(x,y)...)

fma(x::Number, y::Number, z::Number) = fma(promote(x,y,z)...)
muladd(x::Number, y::Number, z::Number) = muladd(promote(x,y,z)...)

(&)(x::Integer, y::Integer) = (&)(promote(x,y)...)
(|)(x::Integer, y::Integer) = (|)(promote(x,y)...)
($)(x::Integer, y::Integer) = ($)(promote(x,y)...)

==(x::Number, y::Number) = (==)(promote(x,y)...)
<( x::Real, y::Real)     = (< )(promote(x,y)...)
<=(x::Real, y::Real)     = (<=)(promote(x,y)...)

div(x::Real, y::Real) = div(promote(x,y)...)
fld(x::Real, y::Real) = fld(promote(x,y)...)
cld(x::Real, y::Real) = cld(promote(x,y)...)
rem(x::Real, y::Real) = rem(promote(x,y)...)
mod(x::Real, y::Real) = mod(promote(x,y)...)

mod1(x::Real, y::Real) = mod1(promote(x,y)...)
rem1(x::Real, y::Real) = rem1(promote(x,y)...)
fld1(x::Real, y::Real) = fld1(promote(x,y)...)

max(x::Real, y::Real) = max(promote(x,y)...)
min(x::Real, y::Real) = min(promote(x,y)...)
minmax(x::Real, y::Real) = minmax(promote(x, y)...)

checked_add(x::Integer, y::Integer) = checked_add(promote(x,y)...)
checked_sub(x::Integer, y::Integer) = checked_sub(promote(x,y)...)
checked_mul(x::Integer, y::Integer) = checked_mul(promote(x,y)...)

# "Promotion" that takes a Functor into account. You can override this
# as needed. For example, if you need to provide a custom result type
# for the multiplication of two types,
#   promote_op{R<:MyType,S<:MyType}(::MulFun, ::Type{R}, ::Type{S}) = MyType{multype(R,S)}
promote_op{R,S}(::Any, ::Type{R}, ::Type{S}) = promote_type(R, S)

## catch-alls to prevent infinite recursion when definitions are missing ##

no_op_err(name, T) = error(name," not defined for ",T)
+{T<:Number}(x::T, y::T) = no_op_err("+", T)
*{T<:Number}(x::T, y::T) = no_op_err("*", T)
-{T<:Number}(x::T, y::T) = no_op_err("-", T)
/{T<:Number}(x::T, y::T) = no_op_err("/", T)
^{T<:Number}(x::T, y::T) = no_op_err("^", T)

fma{T<:Number}(x::T, y::T, z::T) = no_op_err("fma", T)
fma(x::Integer, y::Integer, z::Integer) = x*y+z
muladd{T<:Number}(x::T, y::T, z::T) = x*y+z

(&){T<:Integer}(x::T, y::T) = no_op_err("&", T)
(|){T<:Integer}(x::T, y::T) = no_op_err("|", T)
($){T<:Integer}(x::T, y::T) = no_op_err("\$", T)

=={T<:Number}(x::T, y::T) = x === y
 <{T<:Real}(x::T, y::T) = no_op_err("<" , T)
<={T<:Real}(x::T, y::T) = no_op_err("<=", T)

div{T<:Real}(x::T, y::T) = no_op_err("div", T)
fld{T<:Real}(x::T, y::T) = no_op_err("fld", T)
cld{T<:Real}(x::T, y::T) = no_op_err("cld", T)
rem{T<:Real}(x::T, y::T) = no_op_err("rem", T)
mod{T<:Real}(x::T, y::T) = no_op_err("mod", T)

mod1{T<:Real}(x::T, y::T) = no_op_err("mod1", T)
rem1{T<:Real}(x::T, y::T) = no_op_err("rem1", T)
fld1{T<:Real}(x::T, y::T) = no_op_err("fld1", T)

max{T<:Real}(x::T, y::T) = ifelse(y < x, x, y)
min{T<:Real}(x::T, y::T) = ifelse(y < x, y, x)
minmax{T<:Real}(x::T, y::T) = y < x ? (y, x) : (x, y)

checked_add{T<:Integer}(x::T, y::T) = no_op_err("checked_add", T)
checked_sub{T<:Integer}(x::T, y::T) = no_op_err("checked_sub", T)
checked_mul{T<:Integer}(x::T, y::T) = no_op_err("checked_mul", T)

In [204]:
methods(Experiment)


Out[204]:
4-element Array{Any,1}:
 call(::Type{Experiment}, a::Int64, b::Function, c::AbstractString) at In[163]:2
 call(::Type{Experiment}, a, b, c) at In[163]:2                                 
 call{T}(::Type{T}, arg) at essentials.jl:56                                    
 call{T}(::Type{T}, args...) at essentials.jl:57                                

In [205]:
less(Experiment, (Int64, Function, AbstractString))


LoadError: could not find source file for function
while loading In[205], in expression starting on line 1

 in less at interactiveutil.jl:76
 in less at interactiveutil.jl:75

In [208]:
expand(:(x + 3y))


Out[208]:
:(x + 3y)

In [217]:
function af(x)
    x + 1
end
expand(:(af(3)))


Out[217]:
:(af(3))

In [226]:
@code_lowered join(["a", "b"], "#")


Out[226]:
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:(args::Any...)], Any[Any[Any[:args,:Any,0]],Any[],0,Any[]], :(begin  # strings/io.jl, line 104:
        return (top(_apply))((top(getfield))(Base,:call),Base.sprint,(top(tuple))(Base.print_joined),args)
    end))))

In [227]:
@code_lowered 1 + 1


Out[227]:
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:x,:y], Any[Any[Any[:x,:Any,0],Any[:y,:Any,0]],Any[],0,Any[]], :(begin  # int.jl, line 8:
        return (Base.box)(Base.Int,(Base.add_int)((Base.unbox)(Base.Int,x),(Base.unbox)(Base.Int,y)))
    end))))

In [228]:
@code_lowered af(3)


Out[228]:
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:x], Any[Any[Any[:x,:Any,0]],Any[],0,Any[]], :(begin  # In[217], line 2:
        return x + 1
    end))))

In [231]:
@code_typed join(["a", "b"], "#")


Out[231]:
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:(args::Any...)], Any[Any[Any[:args,Tuple{Array{ASCIIString,1},ASCIIString},0],Any[symbol("##args#8826"),Tuple{Array{ASCIIString,1},ASCIIString},0]],Any[],Any[],Any[]], :(begin  # strings/io.jl, line 104:
        return (Base.sprint)(0,Base.print_joined,(top(getfield))(args::Tuple{Array{ASCIIString,1},ASCIIString},1)::Array{ASCIIString,1},(top(getfield))(args::Tuple{Array{ASCIIString,1},ASCIIString},2)::ASCIIString)::Union{ASCIIString,UTF8String}
    end::Union{ASCIIString,UTF8String}))))

In [232]:
@code_typed 1 + 1


Out[232]:
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:x,:y], Any[Any[Any[:x,Int64,0],Any[:y,Int64,0]],Any[],Any[],Any[]], :(begin  # int.jl, line 8:
        return (Base.box)(Base.Int,(Base.add_int)(x::Int64,y::Int64))
    end::Int64))))

In [233]:
@code_typed af(3)


Out[233]:
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:x], Any[Any[Any[:x,Int64,0]],Any[],Any[],Any[]], :(begin  # In[217], line 2:
        return (Base.box)(Base.Int,(Base.add_int)(x::Int64,1))
    end::Int64))))

In [234]:
@code_warntype join(["a", "b"], "#")


Variables:
  args::Tuple{Array{ASCIIString,1},ASCIIString}
  ##args#8826::Tuple{Array{ASCIIString,1},ASCIIString}

Body:
  begin  # strings/io.jl, line 104:
      return (Base.sprint)(0,Base.print_joined,(top(getfield))(args::Tuple{Array{ASCIIString,1},ASCIIString},1)::Array{ASCIIString,1},(top(getfield))(args::Tuple{Array{ASCIIString,1},ASCIIString},2)::ASCIIString)::UNION{ASCIISTRING,UTF8STRING}
  end::UNION{ASCIISTRING,UTF8STRING}

In [235]:
@code_warntype 1 + 1


Variables:
  x::Int64
  y::Int64

Body:
  begin  # int.jl, line 8:
      return (Base.box)(Base.Int,(Base.add_int)(x::Int64,y::Int64))
  end::Int64

In [236]:
@code_warntype af(3)


Variables:
  x::Int64

Body:
  begin  # In[217], line 2:
      return (Base.box)(Base.Int,(Base.add_int)(x::Int64,1))
  end::Int64

In [239]:
@code_warntype (1 + 2 * af(3))


Variables:
  x::Int64
  y::Int64

Body:
  begin  # int.jl, line 8:
      return (Base.box)(Base.Int,(Base.add_int)(x::Int64,y::Int64))
  end::Int64

In [240]:
@code_llvm join(["a", "b"], "#")


define %jl_value_t* @julia_join_23846(%jl_value_t*, %jl_value_t**, i32) {
ifcont:
  %3 = alloca [7 x %jl_value_t*], align 8
  %.sub = getelementptr inbounds [7 x %jl_value_t*]* %3, i64 0, i64 0
  %4 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 2
  %5 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 3
  store %jl_value_t* inttoptr (i64 10 to %jl_value_t*), %jl_value_t** %.sub, align 8
  %6 = load %jl_value_t*** @jl_pgcstack, align 8
  %7 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 1
  %.c = bitcast %jl_value_t** %6 to %jl_value_t*
  store %jl_value_t* %.c, %jl_value_t** %7, align 8
  store %jl_value_t** %.sub, %jl_value_t*** @jl_pgcstack, align 8
  store %jl_value_t* null, %jl_value_t** %4, align 8
  store %jl_value_t* null, %jl_value_t** %5, align 8
  %8 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 4
  store %jl_value_t* null, %jl_value_t** %8, align 8
  %9 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 5
  store %jl_value_t* null, %jl_value_t** %9, align 8
  %10 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 6
  store %jl_value_t* null, %jl_value_t** %10, align 8
  %11 = call %jl_value_t* @jl_f_tuple(%jl_value_t* null, %jl_value_t** %1, i32 %2)
  store %jl_value_t* %11, %jl_value_t** %4, align 8
  %12 = load %jl_value_t** inttoptr (i64 4505050840 to %jl_value_t**), align 8
  store %jl_value_t* %12, %jl_value_t** %5, align 8
  %13 = load %jl_value_t** inttoptr (i64 4503813048 to %jl_value_t**), align 8
  store %jl_value_t* %13, %jl_value_t** %8, align 8
  %14 = load %jl_value_t** inttoptr (i64 4486815064 to %jl_value_t**), align 8
  %15 = call %jl_value_t* @jl_gc_alloc_1w()
  %16 = getelementptr inbounds %jl_value_t* %15, i64 -1, i32 0
  store %jl_value_t* inttoptr (i64 4471812976 to %jl_value_t*), %jl_value_t** %16, align 8
  %17 = getelementptr inbounds %jl_value_t* %15, i64 0, i32 0
  store %jl_value_t* %14, %jl_value_t** %17, align 8
  store %jl_value_t* %15, %jl_value_t** %9, align 8
  %18 = load %jl_value_t** %4, align 8
  store %jl_value_t* %18, %jl_value_t** %10, align 8
  %19 = call %jl_value_t* @jl_f_apply(%jl_value_t* null, %jl_value_t** %5, i32 4)
  %20 = load %jl_value_t** %7, align 8
  %21 = getelementptr inbounds %jl_value_t* %20, i64 0, i32 0
  store %jl_value_t** %21, %jl_value_t*** @jl_pgcstack, align 8
  ret %jl_value_t* %19
}

In [241]:
@code_llvm 1 + 1


define i64 @"julia_+_23847"(i64, i64) {
top:
  %2 = add i64 %1, %0
  ret i64 %2
}

In [242]:
@code_llvm af(3)


define i64 @julia_af_23848(i64) {
top:
  %1 = add i64 %0, 1
  ret i64 %1
}

In [243]:
@code_native join(["a", "b"], "#")


	.section	__TEXT,__text,regular,pure_instructions
Filename: strings/io.jl
Source line: 104
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 104
	pushq	%r14
	pushq	%rbx
	subq	$64, %rsp
	movq	$10, -72(%rbp)
	movabsq	$jl_pgcstack, %r14
	movq	(%r14), %rax
	movq	%rax, -64(%rbp)
	leaq	-72(%rbp), %rax
	movq	%rax, (%r14)
	xorps	%xmm0, %xmm0
	movups	%xmm0, -56(%rbp)
	movups	%xmm0, -40(%rbp)
	movq	$0, -24(%rbp)
	movabsq	$jl_f_tuple, %rax
	xorl	%edi, %edi
	callq	*%rax
Source line: 104
	movabsq	$jl_gc_alloc_1w, %rcx
	movabsq	$4486815064, %rdx       ## imm = 0x10B6F5D58
	movabsq	$4503813048, %rsi       ## imm = 0x10C72BBB8
	movabsq	$4505050840, %rdi       ## imm = 0x10C859ED8
Source line: 104
	movq	%rax, -56(%rbp)
Source line: 104
	movq	(%rdi), %rax
	movq	%rax, -48(%rbp)
	movq	(%rsi), %rax
	movq	%rax, -40(%rbp)
	movq	(%rdx), %rbx
	callq	*%rcx
Source line: 104
	leaq	-48(%rbp), %rsi
Source line: 104
	movabsq	$jl_f_apply, %rcx
	movabsq	$4471812976, %rdx       ## imm = 0x10A8A7370
	movq	%rdx, -8(%rax)
	movq	%rbx, (%rax)
	movq	%rax, -32(%rbp)
	movq	-56(%rbp), %rax
	movq	%rax, -24(%rbp)
	xorl	%edi, %edi
	movl	$4, %edx
	callq	*%rcx
	movq	-64(%rbp), %rcx
	movq	%rcx, (%r14)
	addq	$64, %rsp
	popq	%rbx
	popq	%r14
	popq	%rbp
	ret

In [244]:
@code_native 1 + 1


	.section	__TEXT,__text,regular,pure_instructions
Filename: int.jl
Source line: 8
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 8
	addq	%rsi, %rdi
	movq	%rdi, %rax
	popq	%rbp
	ret

In [245]:
@code_native af(3)


	.section	__TEXT,__text,regular,pure_instructions
Filename: In[217]
Source line: 2
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 2
	leaq	1(%rdi), %rax
	popq	%rbp
	ret

In [247]:
P = quote
     a = 2
     b = 3
     c = 4
     d = 5
     e = sum([a,b,c,d])
end


Out[247]:
quote  # In[247], line 2:
    a = 2 # In[247], line 3:
    b = 3 # In[247], line 4:
    c = 4 # In[247], line 5:
    d = 5 # In[247], line 6:
    e = sum([a,b,c,d])
end

In [248]:
for (n, expr) in enumerate(P.args)
  println(n, ": ", expr)
end


1:  # In[247], line 2:
2: a = 2
3:  # In[247], line 3:
4: b = 3
5:  # In[247], line 4:
6: c = 4
7:  # In[247], line 5:
8: d = 5
9:  # In[247], line 6:
10: e = sum([a,b,c,d])

In [249]:
quote s = $(sin(1) + cos(1))
end


Out[249]:
quote  # In[249], line 1:
    s = 1.3817732906760363
end

In [250]:
macro p(n)
    if typeof(n) == Expr 
       println(n.args)
    end
    eval(n)
end

In [251]:
@p 3


Out[251]:
3

In [252]:
@p 3 + 4 - 5 * 6 / 7 % 8


Any[:-,:(3 + 4),:(((5 * 6) / 7) % 8)]
Out[252]:
2.7142857142857144

In [253]:
macro f(x)
    quote
       s = 4
       (s, $(esc(s)))
    end
end

In [254]:
s = 0
@f s


Out[254]:
(4,0)

In [255]:
@doc esc


Out[255]:
..  esc(e::ANY)

Only valid in the context of an ``Expr`` returned from a macro. Prevents the macro hygiene pass from turning embedded variables into gensym variables. See the :ref:`man-macros`
section of the Metaprogramming chapter of the manual for more details and examples.

In [263]:
macro dotimes(n, body)
    quote
        for i = 1:$(esc(n))
            @printf "%d\t" i
            $(esc(body))
        end
    end
end
@dotimes 3 println("......")


1	......
2	......
3	......

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


|1|2|3|4|5|6|7|8|9|10|

In [1]:
@doc Base.box


Out[1]:

No documentation found.

Core.Intrinsics.box is of type IntrinsicFunction:

Summary:

immutable IntrinsicFunction <: Any

In [2]:
Base.box(1)


LoadError: error compiling anonymous: box: wrong number of arguments
while loading In[2], in expression starting on line 1

In [4]:
(Base.box)(Base.Int,(Base.add_int)(x::Int64,y::Int64))


LoadError: UndefVarError: x not defined
while loading In[4], in expression starting on line 1

 in anonymous at no file

In [5]:
(Base.box)(Base.Int,(Base.add_int)(1,1))


Out[5]:
2

In [6]:
varx=1;vary=2;
(Base.box)(Base.Int,(Base.add_int)(varx::Int64,vary::Int64))


Out[6]:
3

In [7]:
(Base.add_int)(varx::Int64,vary::Int64)


Out[7]:
3

In [11]:
(Base.box)(Base.Int8,(Base.add_int)(varx::Int64,vary::Int64))


LoadError: box: argument is of incorrect size
while loading In[11], in expression starting on line 1

 in anonymous at no file

In [12]:
(Base.box)(Base.Int8,(Base.add_int)(varx,vary))


LoadError: auto_unbox: unable to determine argument type
while loading In[12], in expression starting on line 1

 in anonymous at no file

In [278]:
apropos("⋅") # \cdot


At_mul_Bt
Ac_mul_B
At_mul_B
A_mul_B!
A_mul_Bt
A_mul_Bc
dot

In [290]:
@doc dot


Out[290]:
dot(x, y)
⋅(x,y)

Compute the dot product. For complex vectors, the first vector is conjugated.


In [279]:
apropos("×") # \times


cross

In [291]:
@doc cross


Out[291]:
cross(x, y)
×(x,y)

Compute the cross product of two 3-vectors.


In [292]:
@which cross


Out[292]:
Base.LinAlg

In [293]:
apropos("∧") # \wedge

In [294]:
"∧" == "^"


Out[294]:
false

In [295]:
1^2


Out[295]:
1

In [296]:
12


Out[296]:
"(1 ∧ 2)"

In [297]:
typeof(12)


Out[297]:
UTF8String

In [298]:
1∫2


LoadError: UndefVarError: ∫2 not defined
while loading In[298], in expression starting on line 1

In [299]:
2


LoadError: syntax: "∧" is not a unary operator
while loading In[299], in expression starting on line 1

In [300]:
1


LoadError: syntax: incomplete: premature end of input
while loading In[300], in expression starting on line 1

In [302]:
@which 


Out[302]:
Main

In [306]:
@doc Main.∧


Out[306]:

No documentation found.

is a generic Function.

# 2 methods for generic function "∧":
(a, b) at In[152]:2
(a, b, c) at In[152]:3

In [310]:
@doc Base.Operators


Out[310]:

No documentation found.

Base.Operators is of type Module:

Summary:

type Module <: Any

Fields:

name   :: Symbol
parent :: Any

In [313]:
Base.Operators.⋅


Out[313]:
dot (generic function with 7 methods)

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]:
get_offsets (generic function with 2 methods)

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]:
get_offset_from_ref (generic function with 3 methods)

In [26]:
y = zeros(500)
e = randn(500)
@loop_ts y[t+1] = 0.8y[t] + 0.02y[t-2] + e[t+1]


y[t + 1], 0.8 * y[t] + 0.02 * y[t - 2] + e[t + 1]

In [27]:
y[500]


Out[27]:
2.1795152868696506

In [30]:
macroexpand(:(@loop_ts y[t+1] = 0.8y[t] + 0.02y[t-2] + e[t+1]))


=, y[t + 1], 0.8 * y[t] + 0.02 * y[t - 2] + e[t + 1]
Out[30]:
quote  # In[29], line 16:
    for #92#t = 3:length(y) - 1 # In[29], line 17:
        y[#92#t + 1] = 0.8 * y[#92#t] + 0.02 * y[#92#t - 2] + e[#92#t + 1]
    end
end

In [ ]: