How to define a function with more than one optional arguments in Julia?

I am trying to understand the mechanism to define functions in Julia.
For example

function xyzpos(x, y, z=0)
    println("$x, $y, $z")
end

Note that

xyzpos(1,2)
> 1, 2, 0

and

xyzpos(1,2,z=3)
> 1, 2, 3

Up to here, it’s ok. Now, note that

xyzpos(x,y=9,z=3)
> MethodError: no method matching xyzpos(::Int64; y=9, z=3)

So, I’m trying to fix this with

function xyzpos2(x, y=0, z=0)
   println("$x, $y, $z")
end

But, note that

xyzpos2(5,y=9,z=3)
> MethodError: no method matching xyzpos2(::Int64, ::Int64; y=9, z=3)

I’m not understanding the logic of the mechanism when defining functions

Help

julia> xyzpos(x, y, z=0) = x,y,z
xyzpos (generic function with 2 methods)

julia> xyzpos(1,2,z=3)
ERROR: MethodError: no method matching xyzpos(::Int64, ::Int64; z=3)
Closest candidates are:

this shouldn’t work, if you don’t have ;, you simply don’t have keyword argument, so what you want is:

function xyzpos(; x, y, z=0)
    println("$x, $y, $z")
end

notice the ;

1 Like

For me, It works:
image

what Julia version are you on? that looks like an old bug or your kernel is in bad state (cell 410 and 411? can you restart kernel)

I think you’re confusing optional arguments with keyword arguments.

(In Python, these are essentially the same thing, but in Julia they are distinct because positional arguments are used for dispatch.)

2 Likes
julia> versioninfo() 
Julia Version 1.6.4 Commit 35f0c911f4 (2021-11-19 03:54 UTC) Platform Info:

You must have defined another method earlier that used a keyword z, e.g.:

julia> xyzpos(x, y; z=0) = "$x, $y and keyword $z"
xyzpos (generic function with 1 method)

julia> xyzpos(x, y, z=0) = "$x, $y, $z"
xyzpos (generic function with 2 methods)

julia> xyzpos(1,2,z=3)
"1, 2 and keyword 3"

This is the peril of experimenting in a long-running session; you may have other method definitions lurking that you’ve forgotten about.

2 Likes
  | | |_| | | | (_| |  |  Version 1.6.4 (2021-11-19)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> xyzpos(x, y, z=0) = x,y,z
xyzpos (generic function with 2 methods)

julia> xyzpos(1,2,z=3)
ERROR: MethodError: no method matching xyzpos(::Int64, ::Int64; z=3)
Closest candidates are:
  xyzpos(::Any, ::Any) at REPL[1]:1 got unsupported keyword argument "z"
  xyzpos(::Any, ::Any, ::Any) at REPL[1]:1 got unsupported keyword argument "z"
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1
1 Like

I restarted and it didn’t work. Thanks!

You may consider consulting the section “function arguments” of the course “Introduction to scientific programming and machine learning with Julia”:

1 Like

Thank you for your answer. I have a doubt.

After “;” Why did you leave the y argument with no value and the z = 0 argument? I thought that after the “;” necessarily we had to put “y= some value”

no, if you put value it’s “optional keyword argument”, if not, it’s “keyword argument”

1 Like

From the manual:

If a keyword argument is not assigned a default value in the method definition, then it is required: an UndefKeywordError exception will be thrown if the caller does not assign it a value

(I actually added this feature in Julia 0.7.)

2 Likes

Basically arguments can be:

  • Positional OR Keyword
  • Optional OR Mandatory

Those are two distinct ways of classifying them, and they’re independent of one another:

Positional arguments - those that come before the ; - can be either optional (given a default value) or mandatory.

Same for keyword arguments - ones after the ; in the function definition - those can be optional or mandatory too.

1 Like