Sanity check function input variables

I’ve been reading “Julia as a Second Language: General purpose programming with a taste of data science” by Erik Engheim and he suggests putting this

cone_volume(r, h) = pir^2h/3

in a file and including it. I would like to sanity check so I created this

function cone_volume(r, h)
if ((@isdefined r) && (@isdefined h))
pir^2h/3
else
println(“The function cone_volume requires two arguments, radius and height”)
end
end

It sort of works the way I want. I can use floating point, integer, or mixed and get an output. If I enter just one argument instead of it falling through to println it generates no method matching. I’m trying to write this as I would a bash script checking variables are there enough and of the right type. I assume I’m missing something or Julia has a better way.

TIA,
Joe

You can only dispatch to that particular method with 2 positional arguments, so that check does nothing; the compiler even removes the println branch. The same MethodError occurs with the first unchecked method too. If you want a more descriptive error, you could make a fallback method for any other number of arguments: cone_volume(args...) = error("Only cone_volume(::Any, ::Any) is supported.") I don’t think that’s necessary though, the MethodError lists the only candidate method already.

Welcome to the Julia forum :wave:

I personally feel the Method not Matching error is very informative, since it even tells you which (hopefully closest) alternatives exist, so that you can fix the error (and indeed provide two arguments).
For me that usually helps more than a println, (or “manual own error”), since it has these hints included.

However, you could get to your version for example like

function cone_volume(r=nothing, h=nothing)
    (isnothing(r) || isnothing(h)) && error("The function cone_volume requires two arguments, radius and height")
    return π * r^2 * h/3
end

Here, I went for error in stead of your print, since that print would cause the function to return nothing, which would anyways make the next computations you would do with the result of the function to very probably error.
Benny’s solution also covers the case for more than 2 arguments, which this approach does not.
So you could do this, but I do not feel that is the Julia way, the Julia way – in my oppinion – is to see the Method Error.

For the type check, I am not so sure what you would like to check, but if you want both to be of same type you could do

cone_volume(r::T, h::T) where T = π*r^2*h/3

then you get

one_volume(1, 1.0)
ERROR: MethodError: no method matching cone_volume(::Int64, ::Float64)

Closest candidates are:
  cone_volume(::T, ::T) where T
   @ Main REPL[1]:1

which might be something nice, but note that the original function does conversions if they exist, i.e. here it would convert the integer to a float and then return a float result (with the pi it would anyways do that also for 2 ints for sure).
So, again, I think for this function the T is not so useful, but in general it might be nice to now this exists, and you can even restrict the T by writing e.g. where {T <: Real} or so.

This is not how julia works. The method cone_volume(r, h) has two arguments of arbitrary type. It makes no sense to test the arguments with @isdefined, the arguments will always be defined if the method has been called. If you only provide a single argument, e.g. cone_volume(2.3), the julia compiler will look for a method with that signature, i.e. a function cone_volume(x). If it can’t find it, it will inform you that no such method exists.

You can however test the type of the arguments, e.g. with
r isa Real || error("radius must be a real number")
If you want a sanity check, as indicated by the title of this thread, it is more common to create the function with two methods as:

function cone_volume(r::Real, h::Real)
    (r < 0 || h < 0) && error("radius and height can't be negative")
    pi * r^2 * h/3
end

function cone_volume(args...)
    error("cone_volume must have two real arguments")
end

Hi @Benny, @kellertuer, and @sgaure,

Thanks for the replies. From your answers I need to adjust my thinking from a bash/python mindset when I’m working in Julia. I would have loved having Julia available when I was getting my BS in 1987.

Regards,
Joe

1 Like

No worries, I had the same troubles in the beginning, since Matlab, where I come from, also has this “you can pass as many arguments as you want” thing. That takes a while, but getting used to that is really worth it, I think; with proper typing, I feel I program faster.