The following code works as intended:
x = 1
exp = Expr(:(=), :x, 4) # :(x = 4)
eval(exp) # x is now equal to 4 as expected
The following code fails:
x = 1
exp = Expr(:(==), :x, 4) # Got :($(Expr(:(==), :x, 4))) instead of the expected :(x == 4)
eval(exp) # ERROR: syntax: invalid syntax (== (outerref x) 4)
== is a function, so you have:
julia> dump(:(x==4))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ==
2: Symbol x
3: Int64 4
but
julia> dump(:(x=4))
Expr
head: Symbol =
args: Array{Any}((2,))
1: Symbol x
2: Int64 4
so in particular the following works:
julia> x = 1
1
julia> exp = Expr(:call, :(==), :x, 4)
:(x == 4)
julia> dump(exp)
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ==
2: Symbol x
3: Int64 4
julia> eval(exp)
false
Related
Suppose that you have a vector a tuple $a$, I want to define a function p(x)=x^a in julia.
For example, if a=(1,2,3), the resultant function would be x^1 *y^2 * z^3.
I would like to have a general method for any tuple, however I don't know the appropiate notation. In my code, I have an array of tuples and I want to define a monomial for each tuple in the array.
Thank you very much for your collaboration.
Is this what you want?
julia> function genmonomial(t::Tuple{Vararg{Integer}})
#assert !isempty(t) && all(>=(0), t)
return (x...) -> begin
#assert length(x) == length(t)
return mapreduce(x -> x[1]^x[2], *, zip(x, t))
end
end
genmonomial (generic function with 1 method)
julia> f = genmonomial((2,3,4))
#1 (generic function with 1 method)
julia> f(2, 1, 1)
4
julia> f(1, 2, 1)
8
julia> f(1, 1, 2)
16
julia> f(2, 2, 2)
512
julia> f(1, 1)
ERROR: AssertionError: length(x) == length(t)
julia> genmonomial(())
ERROR: AssertionError: !(isempty(t)) && all((>=)(0), t)
julia> genmonomial((1.5,))
ERROR: MethodError: no method matching genmonomial(::Tuple{Float64})
Closest candidates are:
genmonomial(::Tuple{Vararg{Integer}}) at REPL[1]:1
I am new to Julia and was working on some example problems from here as a way of getting a handle on the language. To describe the specific issue I'm facing. I am trying to write some code for question 11 in the programming problems which requires me to compute a summation. I am reproducing my code below. I set a variable k to 1 and the formula needs to find the value of -1 to the power of k + 1. When k = 1, it should compute the result as -1 squared which should be 1 but it returns -1. Not sure what is going wrong here. Help me understand my error?
function computeequation()
result = 0
for k = 1:1000000
result = result + ((-1^(k+1))/((2 * k) - 1))
end
return 4 * result
end
This is common to several programming languages, not just Julia: exponentiation has a higher precedence than subtraction or negation. For Julia, you can see the list table of operator precedence here: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1.
For this reason, -1^2 doesn't produce what you may naively expect:
julia> -1^2
-1
In order to override the default precedence, just use parentheses as appropriate:
julia> (-1)^2
1
As suggested by Lyndon White in a comment, a nice way to visualise the precedence of operations in an expression is to quote it
julia> :(-1 ^ 2)
:(-(1 ^ 2))
julia> :((-1) ^ 2)
:((-1) ^ 2)
and dump it to see the full AST:
julia> dump(:(-1 ^ 2))
Expr
head: Symbol call
args: Array{Any}((2,))
1: Symbol -
2: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ^
2: Int64 1
3: Int64 2
julia> dump(:((-1) ^ 2))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ^
2: Int64 -1
3: Int64 2
Here you can note that in the first case the exponentiation is done before the negation, in the second case where parentheses are used, negation comes before exponentiation.
Another neat way to see how an expression is lowered in Julia is to use the Meta.lower function:
julia> Meta.lower(Main, :(-1 ^ 2) )
:($(Expr(:thunk, CodeInfo(
# none within `top-level scope'
1 ─ %1 = Core.apply_type(Base.Val, 2)
│ %2 = (%1)()
│ %3 = Base.literal_pow(^, 1, %2)
│ %4 = -%3
└── return %4
))))
julia> Meta.lower(Main, :((-1) ^ 2) )
:($(Expr(:thunk, CodeInfo(
# none within `top-level scope'
1 ─ %1 = Core.apply_type(Base.Val, 2)
│ %2 = (%1)()
│ %3 = Base.literal_pow(^, -1, %2)
└── return %3
))))
For your particular problem you can do
function computeequation()
result = 0
for k = 1:1000_000
result = result + ((-1) ^ (k + 1))/((2 * k) - 1)
end
return 4 * result
end
Answering my own question. Looks like adding braces around the -1 solves the problem.
function computeequation()
result = 0
for k = 1:1000000
result = result + (((-1)^(k+1))/((2 * k) - 1))
end
return 4 * result
end
How can I define an outer constructor that has same number of arguments as the field values? What I want to do is something like this:
struct data
x
y
end
function data(x, y)
return data(x-y, x*y)
end
But it obviously causes stackoverflow.
Based on the various helpful comments, thanks to all, I changed my answer. Here is an example in Julia 1.0.0 of what you may be after. I am learning Julia myself, so maybe further comments can improve this example code.
# File test_code2.jl
struct Data
x
y
Data(x, y) = new(x - y, x * y)
end
test_data = Data(105, 5)
println("Constructor example: test_data = Data(105, 5)")
println("test_data now is...: ", test_data)
#= Output
julia> include("test_code2.jl")
Constructor example: test_data = Data(105, 5)
test_data now is...: Data(100, 525)
=#
This works for me
julia> struct datatype
x
y
end
julia> function datatype_create(a,b)
datatype(a - b, a * b)
end
datatype_create (generic function with 1 method)
julia> methods(datatype_create)
# 1 method for generic function "datatype_create":
[1] datatype_create(a, b) in Main at none:2
julia> methods(datatype)
# 1 method for generic function "(::Type)":
[1] datatype(x, y) in Main at none:2
julia> a = datatype_create(105,5)
datatype(100, 525)
julia> b = datatype_create(1+2im,3-4im)
datatype(-2 + 6im, 11 + 2im)
julia> c = datatype_create([1 2;3 4],[4 5;6 7])
datatype([-3 -3; -3 -3], [16 19; 36 43])
julia> d = datatype_create(1.5,0.2)
datatype(1.3, 0.30000000000000004)
If you are absolutely Ideologically Hell Bent on using an outer constructor, then you can do something like this
julia> datatype(a,b,dummy) = datatype(a - b,a * b)
datatype
julia> e = datatype(105,5,"dummy")
datatype(100, 525)
Antman's solution using the power of MACRO
julia> macro datatype(a,b)
return :( datatype($a - $b , $a * $b) )
end
#datatype (macro with 1 method)
julia> f = #datatype( 105 , 5 )
datatype(100, 525)
Is there a way to get the surface syntax AST of a method?
according to the docs http://docs.julialang.org/en/stable/devdocs/reflection/ there is a function/macro for everything below surface AST, starting with code_lowered for lowered AST.
it would be great to have something like
f(a,b) = 2*a + b
#code_surface f(1,2)
# :(2a + b)
where code_surface shall return f's definition in form of a standard Expr abstract syntax tree.
#code_expr from CodeTracking.jl returns the Expr of the method definition (needs the Revise.jl package to also be installed).
julia> f(a,b) = 2*a + b
f (generic function with 1 method)
julia> using CodeTracking
julia> #code_expr f(1, 2)
:(f(a, b) = begin
#= REPL[65]:1 =#
2a + b
end)
julia> #code_string f(1, 2)
"f(a,b) = 2*a + b"
(There was discussion about adding a similar feature to base Julia, but it seems unlikely to happen at this point.)
Having the LHS of the method definition in the result helps with knowing which method was applied to the given arguments
julia> f(a::String,b::String) = a * b
f (generic function with 2 methods)
julia> #code_expr f("hi", " friend")
:(f(a::String, b::String) = begin
#= REPL[74]:1 =#
a * b
end)
julia> #code_expr f(2, 5)
:(f(a, b) = begin
#= REPL[65]:1 =#
2a + b
end)
But if you only need the Expr of the function body, you can extract that part of the expression from the result (ex = #code_expr(f(2, 5)); ex.args[2]).
You can easily pass "normal" (i.e. non-keyword) variable values to a function via a Tuple with an ellipsis, like e.g.:
julia> f(x, y, z) = x + y + z;
julia> f(0, 1, 2)
3
julia> varvalues = 0, 1, 2
(0,1,2)
julia> f(varvalues...)
3
But for keyword variables, how do you pass both the keywords and the corresponding variable values via variables? Like e.g. (forgive the silly example):
julia> function g(x, y, z; operation = "add", format = "number")
operation == "add" && format == "number" && return x + y + z
operation == "add" && format == "string" && return string(x + y + z)
operation == "times" && format == "number" && return x * y * z
operation == "times" && format == "string" && return string(x * y * z)
end; # yep, I know this not type-stable
julia> g(0, 1, 2, operation = "times", format = "string")
"0"
julia> g(varvalues..., operation = "times", format = "string") # varvalues = (0,1,2)
"0"
So I would like to define two variables, analogous to varvalues above: keywords with the keywords and keywordvarvalues with the corresponding variable values, that can be passed to function g. Something like this, but that works:
julia> keywords = :operation, :format
(:operation,:format)
julia> keywordvarvalues = "times", "string"
("times","string")
julia> g(varvalues..., keywords... = keywordvarvalues...)
ERROR: MethodError: no method matching broadcast!...
I suppose I can always compose this String from keywords and keywordvarvalues:
expressionstring = """g(varvalues..., operation = "times", format = "string")"""
and then parse-eval it, but that's prolly bad practice, no?
This works:
julia> keywords = :operation, :format
(:operation,:format)
julia> keywordvarvalues = 10, 20
(10,20)
julia> g(; operation=1, format=2) = (operation, format)
g (generic function with 1 method)
julia> g(; zip(keywords, keywordvarvalues)...)
(10,20)
You can also use dictionaries:
julia> g(; keywords...) = keywords
julia> g(a=3, b=4)
2-element Array{Any,1}:
(:a,3)
(:b,4)
julia> d = Dict(:c=>5, :d=>6)
Dict{Symbol,Int64} with 2 entries:
:c => 5
:d => 6
julia> g(; d...)
2-element Array{Any,1}:
(:c,5)
(:d,6)