Error in Julia: LoadError: MethodError: no method matching isless(::Vector{Int64}, ::Int64) - function

I am writing a code in julia but I am getting this error: LoadError: MethodError: no method matching isless(::Vector{Int64}, ::Int64). The part of mu code is:
X = []
function form(;a, b, c, d,e)
if a == 1 && b == 0
#assert c <= 1000 "error."
else
#error failed"
end
.....
push!(x, form(a=2, b=5, c=[0,0], d=[0,1], e=[0,0]))

The error is telling you that there is no method for checking if a vector is less than an integer. You can write .<= to broadcast the less-than comparison, which will perform the comparison element by element, but then you will want any or all or some other logic to transform that comparison output into a single true/false.
julia> [0, 0] <= 1000
ERROR: MethodError: no method matching isless(::Vector{Int64}, ::Int64)
Closest candidates are:
isless(::AbstractVector, ::AbstractVector) at abstractarray.jl:2612
isless(::AbstractFloat, ::Real) at operators.jl:186
isless(::Real, ::Real) at operators.jl:434
...
Stacktrace:
[1] <(x::Vector{Int64}, y::Int64)
# Base .\operators.jl:356
[2] <=(x::Vector{Int64}, y::Int64)
# Base .\operators.jl:405
[3] top-level scope
# REPL[1]:1
julia> [0, 0] .<= 1000
2-element BitVector:
1
1
julia> any([0, 1003] .<= 1000)
true
julia> all([0, 0] .<= 1000)
true

Related

How to get variable names inside a function in julia

For example
function f(x)
# do something
# then I assigned the outside variable name of 'x' to y
println(y)
end
f(1)
I will get
# something and
1
then,
a = 1
f(a)
I will get
# something and
"a"
Is it possible in julia? If not, how can I get my function operation log?
The most idiomatic way would be to slightly change your interface of f and require a keyword argument:
julia> function f(;kwargs...)
for (k, v) in kwargs
println("$k = $v")
end
end
f (generic function with 1 method)
julia> f(a = 1)
a = 1
Alternatively (short of inspecting stack traces), you need something macro-based:
julia> struct Quot
expr
value
end
julia> macro quot(e)
return :($Quot($(QuoteNode(e)), $e))
end
#quot (macro with 1 method)
julia> function f2(x::Quot)
println(x)
end
f2 (generic function with 1 method)
julia> x = 2
2
julia> f2(#quot x)
Quot(:x, 2)
Depending on what you need a simples macro that dumps function calls that still get executed could be:
macro logs(expr)
#info expr
expr
end
And this can be used as:
julia> a = π/2;
julia> #logs sin(a)
[ Info: sin(a)
1.0

Declare a Julia function that returns a function with a specific signature

How can I declare a Julia function that returns a function with a specific signature. For example, say I want to return a function that takes an Int and returns an Int:
function buildfunc()::?????
mult(x::Int) = x * 2
return mult
end
What should the question marks be replaced with?
One thing needs to be made clear.
Adding a type declaration on the returned parameter is just an assertion, not part of function definition. To understand what is going on look at the lowered (this is a pre-compilation stage) code of a function:
julia> f(a::Int)::Int = 2a
f (generic function with 1 method)
julia> #code_lowered f(5)
CodeInfo(
1 ─ %1 = Main.Int
│ %2 = 2 * a
│ %3 = Base.convert(%1, %2)
│ %4 = Core.typeassert(%3, %1)
└── return %4
)
In this case since the returned type is obvious this assertion will be actually removed during the compilation process (try #code_native f(5) to see yourself).
If you want for some reason to generate functions I recommend to use the #generated macro. Be warned: meta-programming is usually an overkill for solving any Julia related problem.
#generated function f2(x)
if x <: Int
quote
2x
end
else
quote
10x
end
end
end
Now we have a function f2 where the source code of f2 is going to depend on the parameter type:
julia> f2(3)
6
julia> f2(3.)
30.0
Note that this function generation is actually happening during the compile time:
julia> #code_lowered f2(2)
CodeInfo(
# REPL[34]:1 within `f2'
┌ # REPL[34]:4 within `macro expansion'
1 ─│ %1 = 2 * x
└──│ return %1
└
)
Hope that clears things out.
You can use Function type for this purpose. From Julia documentation:
Function is the abstract type of all functions
function b(c::Int64)::Int64
return c+2;
end
function a()::Function
return b;
end
Which prints:
julia> println(a()(2));
4
Julia will throw exception for Float64 input.
julia> println(a()(2.0));
ERROR: MethodError: no method matching b(::Float64) Closest candidates are: b(::Int64)

Order of method definition gives different results

Why does the order of the method definition differ in this case? It doesn't make much sense in my opinion.
julia> f() = 1
f (generic function with 1 method)
julia> f(;arg) = 1
f (generic function with 1 method)
julia> f()
ERROR: UndefKeywordError: keyword argument arg not assigned
Stacktrace:
[1] f() at ./REPL[2]:1
[2] top-level scope at REPL[3]:1
julia> f() = 1
f (generic function with 1 method)
julia> f()
1
julia> f(arg=1)
1
The order of method definition gives different result because of how function
with keyword arguments fits into the mechanics of method dispatch in Julia 1.x.
As pointed in the comments above, the short answer is: because the second definition completely overwrites the other.
But I think this is not completely exact, lets see.
Case 1: with the order:
julia> f() = 2
f (generic function with 1 method)
julia> f(;arg) = 1
f (generic function with 1 method)
julia> f()
ERROR: UndefKeywordError: keyword argument arg not assigned
The user defined function f() is overridden.
Case 2: reversing the order both methods are visible:
julia> f(;arg) = 1
f (generic function with 1 method)
julia> f() = 2
f (generic function with 1 method)
julia> f()
2
julia> f(arg=3)
1
When f(;arg) is lowered the compiler produces the method f(), without keyword arguments,
to handle the case where no keyword arguments are passed.
This produce two different outcomes:
Case 1: the produced method f() overrides the user defined f().
Case 2: the user defined f() overrides the produced method f() but f(;args) remains visible.
Note that from both cases it seems that as final result
we get a function f with 1 method, but indeed in the second case we have effectively 2 functions with 1 method each,
one that manage the user defined f() and one that manages the keyword arguments version f(;arg).
The full details of how keyword arguments method definition is lowered is detailed
in the docs

Julia: creating a method for Any vector with missing values

I would like to create a function that deals with missing values. However, when I tried to specify the missing type Array{Missing, 1}, it errors.
function f(x::Array{<:Number, 1})
# do something complicated
println("no missings.")
println(sum(x))
end
function f(x::Array{Missing, 1})
x = collect(skipmissing(x))
# do something complicated
println("removed missings.")
f(x)
end
f([2, 3, 5])
f([2, 3, 5, missing])
I understand that my type is not Missing but Array{Union{Missing, Int64},1}
When I specify this type, it works in the case above. However, I would like to work with all types (strings, floats etc., not only Int64).
I tried
function f(x::Array{Missing, 1})
...
end
But it errors again... Saying that
f (generic function with 1 method)
ERROR: LoadError: MethodError: no method matching f(::Array{Union{Missing, Int64},1})
Closest candidates are:
f(::Array{Any,1}) at ...
How can I say that I wand the type to be union missings with whatever?
EDIT (reformulation)
Let's have these 4 vectors and two functions dealing with strings and numbers.
x1 = [1, 2, 3]
x2 = [1, 2, 3, missing]
x3 = ["1", "2", "3"]
x4 = ["1", "2", "3", missing]
function f(x::Array{<:Number,1})
println(sum(x))
end
function f(x::Array{String,1})
println(join(x))
end
f(x) doesn't work for x2 and x3, because they are of type Array{Union{Missing, Int64},1} and Array{Union{Missing, String},1}, respectively.
It is possible to have only one function that detects whether the vector contains missings, removes them and then deals appropriately with it.
for instance:
function f(x::Array{Any, 1})
x = collect(skipmissing(x))
print("removed missings")
f(x)
end
But this doesn't work because Any indicates a mixed type (e.g., strings and nums) and does not mean string OR numbers or whatever.
EDIT 2 Partial fix
This works:
function f(x::Array)
x = collect(skipmissing(x))
print("removed missings")
f(x)
end
[But how, then, to specify the shape (number of dimensions) of the array...? (this might be an unrelated topic though)]
You can do it in the following way:
function f(x::Vector{<:Number})
# do something complicated
println("no missings.")
println(sum(x))
end
function f(x::Vector{Union{Missing,T}}) where {T<:Number}
x = collect(skipmissing(x))
# do something complicated
println("removed missings.")
f(x)
end
and now it works:
julia> f([2, 3, 5])
no missings.
10
julia> f([2, 3, 5, missing])
removed missings.
no missings.
10
EDIT:
I will try to answer the questions raised (if I miss something please add a comment).
First Vector{Union{Missing, <:Number}} is the same as Vector{Union{Missing, Number}} because of the scoping rules as tibL indicated as Vector{Union{Missing, <:Number}} translates to Array{Union{Missing, T} where T<:Number,1} and where clause is inside Array.
Second (here I am not sure if this is what you want). I understand you want the following behavior:
julia> g(x::Array{>:Missing,1}) = "$(eltype(x)) allows missing"
g (generic function with 2 methods)
julia> g(x::Array{T,1}) where T = "$(eltype(x)) does not allow missing"
g (generic function with 2 methods)
julia> g([1,2,3])
"Int64 does not allow missing"
julia> g([1,2,missing])
"Union{Missing, Int64} allows missing"
julia> g(["a",'a'])
"Any allows missing"
julia> g(Union{String,Char}["a",'a'])
"Union{Char, String} does not allow missing"
Note the last two line - although ["a", 'a'] does not contain missing the array has Any element type so it might contain missing. The last case excludes it.
Also you can see that you could change the second parameter of Array{T,N} to something else to get a different dimensionality.
Also this example works because the first method, as more specific, catches all cases that allow Missing and a second method, as more general, catches what is left (i.e. essentially what does not allow Missing).

Loop in clojure with or condition

I'm trying to write a function in clojure that calls a condition for each value in a vector; the function should return the OR of the result of the condition applied to each value. Eg I have a vector [1 2 3 4] and a condition (>= x 3) where x is an element in the vector, then the function should return true (similary [0 1 0 1] should return false).
I wrote the method
(defn contains-value-greater-or-equal-to-three [values]
(or (for [x values] (>= x 3)))
)
but for the vector [1 2 3 4] this just yields (false false true true); what I want instead is the 'or' function applied to these values.
I'm quite new to functional programming and clojure, let me know if I'm thinking about this the wrong way.
Have a look at the function some, that takes a predicate and a collection as arguments, and returns true iff the predicate returns true for some item in the collection.
(some #(>= % 3) [1 2 3 4]) ; => true
(some #(>= % 3) [0 1 0 1]) ; => false
The problem with your method is that for returns a sequence of true/false values, while or expects a number of individual arguments. Given only one argument, or will return that. What you could have done is to reduce the sequence returned by for, like this:
(reduce #(or %1 %2) (for [x values] (>= x 3)))
(since or is a macro, not a function, (reduce or ...) will not work.