I am trying to convert a python script to Julia. I am checking to make sure I am doing this code in the most optimal way. Please see the following code:
julia> a = [1,2,3,4,5]
5-element Array{Int64,1}:
1
2
3
4
5
julia> if 1 in a
print("1 is in a")
end
1 is in a
julia> if 6 not in a
print("6 not in a")
end
ERROR: TypeError: non-boolean (Int64) used in boolean context
Stacktrace:
[1] top-level scope at REPL[6]:1
julia> push!(a, 6)
6-element Array{Int64,1}:
1
2
3
4
5
6
julia> if (6 in a) == true
print("6 in a")
end
6 not in a
julia> b = [1]
1-element Array{Int64,1}:
1
julia> if (6 in b) == true
print("6 in b")
end
Am I doing this "not in" check correctly?
julia> a = [1, 2, 3, 4, 5];
julia> 6 ∉ a
true
The ∉ symbol can be typed in the REPL by typing \notin and then hitting TAB. Of course, the ∈ symbol is also available as an alternative to in by typing \in and hitting TAB:
julia> 6 ∈ a
false
Sometimes you need a vectorized version:
julia> x = [2, 7];
julia> x .∉ Ref(a)
2-element BitArray{1}:
0
1
The Ref is needed in this case so that a is treated as a scalar in the broadcasting operation.
If you prefer to avoid Unicode characters, you can write !(6 in a) instead of 6 ∉ a.
Related
I would like to convert a NamedTuple to a Dict in Julia. Say I have the following NamedTuple:
julia> namedTuple = (a=1, b=2, c=3)
(a = 1, b = 2, c = 3)
I want the following:
julia> Dict(zip(keys(namedTuple), namedTuple))
Dict{Symbol, Int64} with 3 entries:
:a => 1
:b => 2
:c => 3
This works, however I would've hoped for a somewhat simpler solution - something like
julia> Dict(namedTuple)
ERROR: ArgumentError: Dict(kv): kv needs to be an iterator of tuples or pairs
would have been nice. Is there such a solution?
The simplest way to get an iterator of keys and values for any key-value collection is pairs:
julia> Dict(pairs(namedTuple))
Dict{Symbol, Int64} with 3 entries:
:a => 1
:b => 2
:c => 3
I am studying Julia static analysis, and I have the following function:
function f(x,y,z)
d=x+y
d=d*2*z
end
i use code_typed to analyze it.
julia> y=code_typed(f)
1-element Vector{Any}:
CodeInfo(
1 ─ %1 = (x + y)::Any
│ %2 = (%1 * 2)::Any
│ %3 = (%2 * z)::Any
└── return %3
) => Any
i can get slots and slot types of it.
julia> y[1].first.slotnames
5-element Vector{Symbol}:
Symbol("#self#")
:x
:y
:z
:d
julia> y[1].first.slottypes
5-element Vector{Any}:
Core.Const(f)
Any
Any
Any
Any
but do i have any way to know which is argument and which is local variables among the slots?
You can use Base.argnames to find out arguments of your function:
julia> Base.method_argnames.(methods(f))
1-element Vector{Vector{Symbol}}:
[Symbol("#self#"), :x, :y, :z]
You can extract this from the CodeInfo object as well:
julia> Base.method_argnames(y[1].first.parent.def)
4-element Vector{Symbol}:
Symbol("#self#")
:x
:y
:z
I am writing code in Julia which collects some output from a function foo (which mutates its input argument), and I'm trying to append the recursive evaluations from this function in an array A.
For instance, foo!(x) changes the value of x by adding 1 to each of its elements.
function foo!(x)
x .= x .+ 1
return(x)
end
julia> x = [1, 1];
julia> foo!(x);
julia> x
2-element Array{Int64,1}:
2
2
I want to create an array A which stores the value of x = f(x) over a fixed range. However, A just ends up containing multiple copies of the final value of f(x), e.g.,
julia> x = [1, 1];
julia> A = [x];
julia> for i=1:3
push!(A, foo!(x))
end
julia> A
4-element Array{Array{Int64,1},1}:
[4, 4]
[4, 4]
[4, 4]
[4, 4]
I'm trying to get it to get it to efficiently output something similar to
julia> B
4-element Array{Array{Int64,1},1}:
[1, 1]
[2, 2]
[3, 3]
[4, 4]
I haven't been able to find a helpful resources for a developing a solid understanding of mutations, or the order in which mutations are executed in Julia. Any help in this regard would be greatly appreciated!
The way you've written it, you repeatedly push! the same object into A, which your foo! function mutates:
julia> x = [1, 1]
2-element Vector{Int64}:
1
1
julia> A = [x]
1-element Vector{Vector{Int64}}:
[1, 1]
julia> foo!(x)
2-element Vector{Int64}:
2
2
julia> A
1-element Vector{Vector{Int64}}:
[2, 2]
One way of fixing this is to copy the elements in A before x gets mutated:
julia> for i ∈ 1:3
A[i] = copy(x)
push!(A, foo!(x))
end
julia> A
4-element Vector{Vector{Int64}}:
[1, 1]
[2, 2]
[3, 3]
[4, 4]
A classic read on values vs. bindings can be found here.
By using only push! you are just creating an array of references to a single array (ie x). This is why you see the same value repeated many times.
If you want to keep copies of the value of x across invocations of foo! you can use copy:
julia> foo!(x) = x .+= 1
foo! (generic function with 1 method)
julia> x = [0,0];
julia> A = [copy(foo!(x)) for i in 1:4]
4-element Vector{Vector{Int64}}:
[1, 1]
[2, 2]
[3, 3]
[4, 4]
I am clearly missing something fundamental here. How can I change the second method of my function to accept c? Additionally, I would really prefer to use AbstractArray instead of AbstractVector as the type so as not to restrict the dimension either, but I wanted to cut down on potential sources of error.
function f(x::AbstractVector{Int})
println(x)
end # f (generic function with 1 method)
function f(x::AbstractVector{AbstractVector{Int}})
for i in x
println(i)
end
end # f (generic function with 2 methods)
a=[1,2,3] # 3-element Array{Int64,1}:
b=[4,5,6] # 3-element Array{Int64,1}:
c=[a,b] # 2-element Array{Array{Int64,1},1}:
typeof(a) <: AbstractVector{Int} # true
typeof(c) <: AbstractVector{AbstractVector{Int}} # false
f(a) # [1, 2, 3]
f(c) # ERROR: MethodError: no method matching f(::Array{Array{Int64,1},1})
Quoting the manual:
Concrete Point types with different values of T are never subtypes of each other:
julia> struct Point{T} end
julia> Point{Float64} <: Point{Int64}
false
julia> Point{Float64} <: Point{Real}
false
This last point is very important: even though Float64 <: Real we DO NOT have Point{Float64} <: Point{Real}.
Translated to your example, as you noted,
julia> Vector{Int} <: AbstractVector{Int}
true
julia> Vector{Vector{Int}} <: AbstractVector{AbstractVector{Int}}
false
What you need here is
julia> Vector{Vector{Int}} <: AbstractVector{T} where T <: AbstractVector{Int}
true
or the convenient shorthand
julia> Vector{Vector{Int}} <: AbstractVector{<:AbstractVector{Int}}
true
I am writing a macro, that takes a function name,
and declares a couple of other version of the function.
I want to give these variations the same doc string as the original method,
with perhaps a few changes.
To do this, I need to retrieve the docstring for the orginal method.
So what I am looking for is a function:
get_docstring(functionname::Symbol, argtypes)::String
So that I could do:
julia> s=get_docstring(:values,(Associative,)) and then s would be set to:
s="""
values(a::Associative)
Return an iterator over all values in a collection.
`collect(values(d))` returns an array of values.
```jldoctest
julia> a = Dict('a'=>2, 'b'=>3)
Dict{Char,Int64} with 2 entries:
'b' => 3
'a' => 2
julia> collect(values(a))
2-element Array{Int64,1}:
3
2
```
"""
You can use the #doc macro, but instead of a string, it returns a markdown object:
julia> #doc "foo int" ->
foo(x::Int) = x
foo
julia> #doc "foo float" ->
foo(x::Float64) = x
foo
julia> #doc "foo sym" ->
foo(x::Symbol) = x
foo
julia> #doc "foo x, y" ->
function foo(x, y) x, y end
foo
julia> #doc foo
foo int
foo float
foo sym
foo x, y
julia> typeof(ans)
Base.Markdown.MD
julia> #doc foo(::Int)
foo int
julia> #doc foo(::Float64)
foo float
julia> #doc foo(::Symbol)
foo sym
julia> md = #doc foo(::Any, ::Any)
foo x, y
julia> md.content
1-element Array{Any,1}:
foo x, y
julia> md.content[1]
foo x, y
julia> md.content[1].content
1-element Array{Any,1}:
Base.Markdown.Paragraph(Any["foo x, y"])
julia> md.meta
Dict{Any,Any} with 3 entries:
:typesig => Tuple{Any,Any}
:results => Base.Docs.DocStr[Base.Docs.DocStr(svec("foo x, y"),foo x, y…
:binding => foo
julia>