Till now in functions you have seen functions where arguments are positional, say you define a function like this:

function sub(a, b)
  return a - b

here it’s always b, the second argument that will get subtracted from a, the first argument. Like when you call sub(5, 3) that you will get 2 as output, but what if I want to do something like this sub(b = 20, a = 70), where I expect output to be 70 minus 20 that is 50, no that isn’t possible till now. Now let’s see how to do these kind of stuff.

Code the function below in your Jupyter lab and let’s see how it works.

function increment(number = 0; inc = 0, dec = 0)
    number + inc - dec


increment (generic function with 4 methods)

First, we call just increment() as shown below:




in this case the number, inc and dec defaults to 0. And hence we get the output as 0. Now let’s call it with just one argument as shown:




here increment(1), the 1 is passed as positional argument and hence number in function increment(number = 0; inc = 0, dec = 0) becomes 1 and hence 1 is returned.

Now let’s see the code below:

increment(2, inc = 5)



and this code:

increment(12, dec = 8)



Looks like, inc and dec are not passed as positional argument, but they were named as inc in increment(2, inc = 5) and dec in increment(12, dec = 8), yet Julia seems to have compute the results correctly. If these were positional then 8 should have been pass to inc within the function when we call increment(12, dec = 8).

In the example below we give both inc and dec as named arguments to the function:

increment(10, inc = 5, dec = 7)



So how Julia knows inc and dec are named arguments but not positional. If you see the function definition function increment(number = 0; inc = 0, dec = 0), you can see we have place inc = 0 and dec = 0 after a semicolon ;, that’s a hint to Julia that these arguments could be named arguments.

Just because we have said that they are named arguments, it does not mean that they have lost their positional status. We can very well call the increment() function as shown below, where every argument preserves its positional properties.

increment(10, 5, 7)



Now see how I have coded the function printline5() below, where all arguments are placed after the semicolon ; and are hence named arguments, and they have default values too:

function printline5(;length = 50, character = '*')
    println(character ^ length)


printline5 (generic function with 1 method)

So if I want a line of variable length I can call as shown:

printline5(length = 7)

If I want a line of different character, I can call like this:

printline5(character = '@')



Let’s say I want a line of my preferred length and the character of my choice, I can call like this:

printline5(length = 7, character = '!')



And I can call it with out any argument at all, in the case below it takes default length and character:




But since all are placed behind a semicolon, I notice that they have lost their positional status in this case:

printline5(7, '!')


MethodError: no method matching printline5(::Int64, ::Char)


 [1] top-level scope at In[53]:1

 [2] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091

 [3] execute_code(::String, ::String) at /home/karthikeyan/.julia/packages/IJulia/a1SNk/src/execute_request.jl:27

 [4] execute_request(::ZMQ.Socket, ::IJulia.Msg) at /home/karthikeyan/.julia/packages/IJulia/a1SNk/src/execute_request.jl:86

 [5] #invokelatest#1 at ./essentials.jl:710 [inlined]

 [6] invokelatest at ./essentials.jl:709 [inlined]

 [7] eventloop(::ZMQ.Socket) at /home/karthikeyan/.julia/packages/IJulia/a1SNk/src/eventloop.jl:8

 [8] (::IJulia.var"#15#18")() at ./task.jl:356

Looks like you need one positional argument before the semicolon ; for named argument to preserve their positional properties.

You can get the Jupyter notebook file for this blog here https://gitlab.com/data-science-with-julia/code/-/blob/master/functions.ipynb.