1

I'm very new to Julia, and I'm trying to just pass an array of numbers into a function and count the number of zeros in it. I keep getting the error:

ERROR: UndefVarError: array not defined

I really don't understand what I am doing wrong, so I'm sorry if this seems like such an easy task that I can't do.

function number_of_zeros(lst::array[])

    count = 0

   for e in lst

    if e == 0

        count + 1

    end

end

println(count)

end 

lst = [0,1,2,3,0,4]

number_of_zeros(lst)
1
  • 1
    ::array[] not needed in function definition. Just function number_of_zeros(lst) enough. Arrays in julia can be of any dimension, so lists are usually called vectors, and written Vector{Int} in this case. Commented Nov 9, 2022 at 1:56

2 Answers 2

5

There are two issues with your function definition:

  1. As noted in Shayan's answer and Dan's comment, the array type in Julia is called Array (capitalized) rather than array. To see:
julia> array
ERROR: UndefVarError: array not defined

julia> Array
Array
  1. Empty square brackets are used to instantiate an array, and if preceded by a type, they specifically instantiate an array holding objects of that type:
julia> x = Int[]
Int64[]

julia> push!(x, 3); x
1-element Vector{Int64}:
 3

julia> push!(x, "test"); x
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64

Thus when you do Array[] you are actually instantiating an empty vector of Arrays:

julia> y = Array[]
Array[]

julia> push!(y, rand(2)); y
1-element Vector{Array}:
 [0.10298669573927233, 0.04327245960128345]

Now it is important to note that there's a difference between a type and an object of a type, and if you want to restrict the types of input arguments to your functions, you want to do this by specifying the type that the function should accept, not an instance of this type. To see this, consider what would happen if you had fixed your array typo and passed an Array[] instead:

julia> f(x::Array[])
ERROR: TypeError: in typeassert, expected Type, got a value of type Vector{Array}

Here Julia complains that you have provided a value of the type Vector{Array} in the type annotation, when I should have provided a type.

More generally though, you should think about why you are adding any type restrictions to your functions. If you define a function without any input types, Julia will still compile a method instance specialised for the type of input provided when first call the function, and therefore generate (most of the time) machine code that is optimal with respect to the specific types passed.

That is, there is no difference between

number_of_zeros(lst::Vector{Int64})

and

number_of_zeros(lst)

in terms of runtime performance when the second definition is called with an argument of type Vector{Int64}. Some people still like type annotations as a form of error check, but you also need to consider that adding type annotations makes your methods less generic and will often restrict you from using them in combination with code other people have written. The most common example of this are Julia's excellent autodiff capabilities - they rely on running your code with dual numbers, which are a specific numerical type enabling automatic differentiation. If you strictly type your functions as suggested (Vector{Int}) you preclude your functions from being automatically differentiated in this way.

Finally just a note of caution about the Array type - Julia's array's can be multidimensional, which means that Array{Int} is not a concrete type:

julia> isconcretetype(Array{Int})
false

to make it concrete, the dimensionality of the array has to be provided:

julia> isconcretetype(Array{Int, 1})
true
Sign up to request clarification or add additional context in comments.

Comments

2

First, it might be better to avoid variable names similar to function names. count is a built-in function of Julia. So if you want to use the count function in the number_of_zeros function, you will undoubtedly face a problem.
Second, consider returning the value instead of printing it (Although you didn't write the print function in the correct place).
Third, You can update the value by += not just a +!
Last but not least, Types in Julia are constantly introduced with the first capital letter! So we don't have an array standard type. It's an Array. Here is the correction of your code.

function number_of_zeros(lst::Array{Int64})

    counter = 0
    for e in lst
        if e == 0
            counter += 1
        end
    end

    return counter
end

lst = [0,1,2,3,0,4]

number_of_zeros(lst)

would result in 2.

Additional explanation

First, it might be better to avoid variable names similar to function names. count is a built-in function of Julia. So if you want to use the count function in the number_of_zeros function, you will undoubtedly face a problem.

Check this example:

function number_of_zeros(lst::Array{Int64})

    count = 0
    for e in lst
        if e == 0
            count += 1
        end
    end

    return count, count(==(1), lst)
end

number_of_zeros(lst)

This code will lead to this error:

ERROR: MethodError: objects of type Int64 are not callable   
Maybe you forgot to use an operator such as *, ^, %, / etc. ?
Stacktrace:
 [1] number_of_zeros(lst::Vector{Int64})
   @ Main \t.jl:10
 [2] top-level scope
   @ \t.jl:16

Because I overwrote the count variable on the count function! It's possible to avoid such problems by calling the function from its module:

function number_of_zeros(lst::Array{Int64})

    count = 0
    for e in lst
        if e == 0
            count += 1
        end
    end

    return count, Base.count(==(1), lst)

The point is I used Base.count, then the compiler knows which count I mean by Base.count.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.