# A question about redefining a function in Julia

**URL:** <https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579>\
**Category:** New to Julia\
**Tags:** question, functions\
**Created:** [October 31, 2025, 3:15pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579 "2025-10-31T15:15:16Z")\
**Posts on this page:** 18\
**Page:** 2

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [November 3, 2025, 2:28am UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/21 "2025-11-03T02:28:14Z")

</div>

> [@josePereiro](#):
>
> having several versions of functions creates harder to follow programs.

I think “capturing a name within a function” is somewhat a nontrivial thing.

A safer design would be bypassing “capture and then re-bind” completely, e.g.

```julia-auto
julia> const ref = Ref{Function}(x -> x+1);

julia> function g(; ref = ref)
           f = ref.x
           f(1)
       end;

julia> g()
2

julia> setfield!(ref, :x, x -> x+2);

julia> g()
3

```

* * *

Edit: the `ref = ref` in the definition of `g` is redundant, since the `ref` is already `const`, which is fast.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [November 3, 2025, 4:34am UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/22 "2025-11-03T04:34:42Z")

</div>

> [@StefanKarpinski](#):
>
> Default expressions, like everything else about a function definition, are evaluated in the scope where the function is defined.

Oh my god. I didn’t think of this. Did you mean that

```julia-auto
function f(; x = x/2, y = x)
    @show x y    
end

```

boils down to

```julia-auto
function f()
    x = x/2
    y = x
    @show x y    
end

```

? If this is the case, I think it’s terrible. Because the first version looks clean and I think it will be clean. The second version apparently violates the [avoid untyped global variables](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-untyped-global-variables) performance tip.

* * *

I asked AI to give me a reformulation of

```julia-auto
function f(w; x = x, y = y)
    return w, x, y
end

```

, who gives me

```julia-auto
function f(w; kwargs...)
    local x = haskey(kwargs, :x) ? kwargs[:x] : Main.x
    local y = haskey(kwargs, :y) ? kwargs[:y] : Main.y
    return w, x, y
end

```

So I guess that the definition `f(w; x = x, y = y)` is problematic in terms of performance.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [November 3, 2025, 6:08am UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/23 "2025-11-03T06:08:39Z")

</div>

There are many issues in this context…

But whatever, for writing daily code, there is only one thing important for me to care about:  
This “const and no arg” style is already fast:

```julia-auto
const x = rand(1000)
function loop_over_global()
    s = 0.0
    for i in x
        s += i
    end
    return s
end
loop_over_global()

```

There is no need to write a standard function like the following

```julia-auto
function loop_over_global(x)
    ...
end
loop_over_global(x)

```

because this style in practical code would become very cumbersome that one can ill afford.

I did a test, which proves that “`const`” is the fastest, even faster than the standard definition.

> **test**
>
> ```julia-auto
> import Statistics
> 
> a = rand(100000);
> b = rand(100000);
> c = rand(100000);
> d = rand(100000);
> e = rand(100000);
> f = rand(100000);
> g = rand(100000);
> h = rand(100000);
> i = rand(100000);
> j = rand(100000);
> k = rand(100000);
> l = rand(100000);
> m = rand(100000);
> n = rand(100000);
> o = rand(100000);
> p = rand(100000);
> q = rand(100000);
> r = rand(100000);
> s = rand(100000);
> 
> function loop_over_global(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s)
> s0 = -1.797693134862315e308
> for vec = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s), ind in vec
> s0 += ind
> end
> return s0
> end
> 
> loop_over_global(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s)
> tvec = [];
> for _ = 1:100
> t = time()
> loop_over_global(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s)
> push!(tvec, time()-t)
> end
> Statistics.mean(tvec)
> 
> ```

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [November 3, 2025, 8:29am UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/24 "2025-11-03T08:29:36Z")

</div>

> [@WalterMadelim](#):
>
> I think writing expressions at the default value position of a kwarg is obfuscating

It has its uses. Say you create a module with some computation which may take as input a precision, and uses that to compute the number of basis functions used in the computation. However, not being infallible you allow for the caller to specify the number of basis functions. Moreover, this is not typically done, so you let these arguments be keyword arguments. You’d do something like this:

```julia-auto
function computation(x, y; precision=√eps(x), Nbasis=nfuncs(precision))
    ...
end

```

The caller of the function may not be aware of the function `nfuncs`, it’s an implementation detail. So the caller may happen to define their own `nfuncs` for some entirely unrelated work. You wouldn’t want that to interfere with the default number of basis functions, the default should use _your_ `nfuncs` (and `√` and `eps`).

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [November 3, 2025, 9:29am UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/25 "2025-11-03T09:29:43Z")

</div>

> [@WalterMadelim](#):
>
> If this is the case, I think it’s terrible. Because the first version looks clean and I think it will be clean. The second version apparently violates the [avoid untyped global variables](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-untyped-global-variables) performance tip.

How would you interpret

```julia-auto
function f(; x = x/2, y = x)
    @show x y    
end

```

other than using some outer variable `x` for computing `x/2`?

> [@WalterMadelim](#):
>
> So I guess that the definition `f(w; x = x, y = y)` is problematic in terms of performance.

Potentially because of how the outer `x` and `y` are defined (like you mention), but not due to the `haskey` etc., as you can easily benchmark. The reason is that `kwargs` will be a (`Pairs` wrapper around a) `NamedTuple` for which the `haskey` and `getindex` (`getfield`) can just be compiled away.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [November 3, 2025, 10:08am UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/26 "2025-11-03T10:08:58Z")

</div>

> [@eldee](#):
>
> How would you interpret

Yes, I understand it now.

That grammer is indeed a bit tricky, which can be understood as `x = x/2; y = x` rather than  
`x, y = x/2, x`.

* * *

> [@eldee](#):
>
> as you can easily benchmark

According to my benchmark (with the instance attached in my #23 post), the performance of  
the style “`f(; x = x, y = y)`” is virtually the same as the standard style (where you explicitly pass all args), their results are around `0.00163` sec on my computer.

Whereas the “const + no arg” style is not only a lot more concise to read but also has shorter time, which is `6.81496e-5` sec on my computer.

> [@eldee](#):
>
> for which the `haskey` and `getindex` (`getfield`) can just be compiled away

Maybe you’re right.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [November 3, 2025, 10:54am UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/27 "2025-11-03T10:54:41Z")

</div>

> [@WalterMadelim](#):
>
> According to my benchmark (with the instance attached in my #23 post), the performance of  
> the style “`f(; x = x, y = y)`” is virtually the same as the standard style (where you explicitly pass all args), their results are around `0.00163` sec on my computer.
> 
> Whereas the “const + no arg” style is not only a lot more concise to read but also has shorter time, which is `6.81496e-5` sec on my computer.

As far as I can tell you only provided code for your `loop_over_global(<19 non-const positional arguments>)` timing?

For the 0/1 (kw)arg version, i.e. with `const x = rand(1000)` and

- `function loop_over_global() ... end`
- `function loop_over_global(x) ... end`
- `function loop_over_global(; x = x) ... end`

all of

- `@benchmark loop_over_global()`
- `@benchmark loop_over_global(x)`
- `@benchmark loop_over_global($x)`
- `@benchmark loop_over_global(; x)`
- `@benchmark loop_over_global(; x=$x)`

(tested at the appropriate time) give me the same result (namely 910 ns mean execution time).

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [November 3, 2025, 12:11pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/28 "2025-11-03T12:11:04Z")

</div>

Thank you for really testing that. I didn’t use any benchmark packages but just use practical experience: I execute in my shell (zsh in linux).

 ![image](https://global.discourse-cdn.com/julialang/original/3X/b/a/ba4d676530fc6554a2c48dba168e5d6547c9ae35.png)

The three source code are:

## kwarg.jl

```julia-auto
import Statistics
import Random
Random.seed!(1)

a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s = (
    rand(1000) for _ = 1:19
);

function loop_over_global(; a = a, b = b, c = c, d = d, e = e, f = f, g = g, h = h, i = i, j = j, k = k, l = l, m = m, n = n, o = o, p = p, q = q, r = r, s = s)
    s0 = -1.797693134862315e308
    for vec = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s), ind in vec
        s0 += ind
    end
    return s0
end;

loop_over_global()
tvec = [];
for _ = 1:10000
    t = time()
    loop_over_global()
    push!(tvec, time()-t)
end
println("kwarg_in_def> $(sum(tvec))")

```

## arg.jl

```julia-auto
import Statistics
import Random
Random.seed!(1)

a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s = (
    rand(1000) for _ = 1:19
);

function loop_over_global(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s)
    s0 = -1.797693134862315e308
    for vec = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s), ind in vec
        s0 += ind
    end
    return s0
end;

loop_over_global(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s)
tvec = [];
for _ = 1:10000
    t = time()
    loop_over_global(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s)
    push!(tvec, time()-t)
end
println("standard_arg> $(sum(tvec))")

```

## const.jl

```julia-auto
import Statistics
import Random
Random.seed!(1)

const a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s = (
    rand(1000) for _ = 1:19
);

function loop_over_global()
    s0 = -1.797693134862315e308
    for vec = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s), ind in vec
        s0 += ind
    end
    return s0
end;

loop_over_global()
tvec = [];
for _ = 1:10000
    t = time()
    loop_over_global()
    push!(tvec, time()-t)
end
println("const_no_arg> $(sum(tvec))")

```

As you can see, the standard grammar in `arg.jl` is very cumbersome. The `const.jl` is both clean and fast.  
(One last thing to add, if you drop the `const` annotation in `const.jl`, the result is around `18` sec).

**Edit** : Oh, I see. We can make `arg.jl` faster by adding `const` (I did that in `constarg.jl`) and get

 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/f/cf3145cd2e9299d75c714e15b9a7cfaa17c9eec5.png)

* * *

So to sum up: We need to add the `const` keyword annotation whenever possible for performance. With that, we can write concise and fast no-arg function calls.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [November 3, 2025, 1:12pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/29 "2025-11-03T13:12:17Z")

</div>

I’m sorry the SNR is a bit low. I give a recap here:

When we handle our functions in practice, it would be perfect if we define and call standard functions (at the definition, all names are read from the arg line; at the caller’s place, we specify all arguments). But this style in practice would soon become very cumbersome. Imagine if you have a function with a long arg list, and that function still needs to be wrapped within a “shell” function. So that “shell” function also has to define a long list of args.

Instead of writing

```julia-auto
f = x -> x+1
g() = f(1)
f = x -> x+2
g()

```

as in #1 post (which is a non-standard function since `f` is not an arg of `g`), we can write

```julia-auto
const ref = Ref{Function}(x -> x+1);
function g()
    f = ref.x
    f(1)
end;
g()
setfield!(ref, :x, x -> x+2);
g()

```

. Although it is not a standard function, the `ref` is a `const`, which retains performance (as suggested in my #28 post).

---

<div class="post-metadata">

**Author:** ![quantum2025](https://avatars.discourse-cdn.com/v4/letter/q/90ced4/32.png) [@quantum2025](https://discourse.julialang.org/u/quantum2025)\
**Post date:** [November 3, 2025, 1:57pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/30 "2025-11-03T13:57:49Z")

</div>

Yes, this is exactly what I was confused by, as both c and g() are defined by the equal sign, but they behave differently.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [November 3, 2025, 2:00pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/31 "2025-11-03T14:00:02Z")

</div>

Your `arg.jl` still uses non-const globals, so it’s not surprising that it takes time; there will be dynamic dispatch of the `loop_over_global`. Moreover, when there are more than a few arguments, a function call does not pass the arguments in registers, so it also takes time.

But, of course, constant globals will be fast.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [November 3, 2025, 2:02pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/32 "2025-11-03T14:02:30Z")

</div>

> [@quantum2025](#):
>
> Yes, this is exactly what I was confused by, as both c and g() are defined by the equal sign, but they behave differently.

The equal sign is just a syntactical variant of a function definition. I.e.

```julia-auto
function g(x)
   f(x)
end

```

means exactly the same as

```julia-auto
g(x) = f(x)

```

---

<div class="post-metadata">

**Author:** ![quantum2025](https://avatars.discourse-cdn.com/v4/letter/q/90ced4/32.png) [@quantum2025](https://discourse.julialang.org/u/quantum2025)\
**Post date:** [November 3, 2025, 2:20pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/33 "2025-11-03T14:20:31Z")

</div>

My confusion actually comes from my experience with Mathematica which I used more before. In Mathematica, one can explicitly specify whether expressions determined by other functions are evaluated immediately or not at the time of defining the function.  
For example:

```Mathematica
f[x_]:=x+1
g[x_]=f[2] (*define g[x] with f[2] immediately evaluated*)
h[x_]:=f[2] (*f[2] is not immediately evaluated when h[x] is defined until h[x] is called*)
g[1] (*g[1]=3*)
h[1] (*h[1]=3*)
f[x_]:=x+2
g[1] (*still g[1]=3*)
h[1] (*now h[1]=4*)

```

It seems that in Julia a function is defined without any expression evaluated, just like the way h was defined. That puzzled me because the equal sign = can be used to define both a variable and a function which behave nevertheless differently.  
In addition, I was wondering if there is a similar way in Julia to specify whether expressions are immediately evaluated or not in defining functions.

---

<div class="post-metadata">

**Author:** ![quantum2025](https://avatars.discourse-cdn.com/v4/letter/q/90ced4/32.png) [@quantum2025](https://discourse.julialang.org/u/quantum2025)\
**Post date:** [November 3, 2025, 2:27pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/34 "2025-11-03T14:27:07Z")

</div>

I understand now. I think the same symbol (the equal sign) in both definitions of a variable and a function puzzled me.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [November 3, 2025, 2:45pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/35 "2025-11-03T14:45:25Z")

</div>

> [@quantum2025](#):
>
> And I was wondering if there is a similar way in Julia to specify whether expressions are immediately evaluated or not in defining functions.

There is no such direct way in julia. It is possible, indirectly with `@eval` and “$-interpolation”:

```julia-auto
julia> f(x) = x+1

julia> @eval g(x) = $(f(1)) + x;

julia> g(0)
2

julia> f(x) = x+2;

julia> g(0)
2

```

There are also other ways to incorporate some precomputed constant via a “closure”, i.e. a function with “hidden” parameters. Below, `add` is a function which returns a function which adds `a`:

```julia-auto
julia> function add(a)
           return (x -> x + a)
       end
add (generic function with 1 method)

julia> f = add(1)
#add##0 (generic function with 1 method)

julia> g = add(2)
#add##0 (generic function with 1 method)

julia> f(0)
1

julia> g(0)
2

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [November 3, 2025, 2:55pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/36 "2025-11-03T14:55:29Z")

</div>

Please don’t use `@eval` for this. A better approach — especially for beginners — is to use a temporary `let` name.

```julia-auto
julia> x = 0
0

julia> f() = x+1
f (generic function with 1 method)

julia> f()
1

julia> x = 10
10

julia> f()
11

julia> let x=x
           global g
           g() = x + 1
       end
g (generic function with 1 method)

julia> g()
11

julia> x = 100
100

julia> g()
11

julia> f()
101

```

The same approach now works if you want to “freeze” the evaluation of a function too. You _just evaluate it_ and reference that result.

```julia-auto
julia> let result=f()
           global h
           h() = result+1
       end
h (generic function with 1 method)

julia> h()
102

julia> f() = 42
f (generic function with 1 method)

julia> h()
102

```

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [November 3, 2025, 2:59pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/37 "2025-11-03T14:59:40Z")

</div>

Came to think of it, it would be handy with $-interpolation in function definitions, though I think there might be some gotchas with it.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [November 3, 2025, 5:51pm UTC](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579/38 "2025-11-03T17:51:42Z")

</div>

> [@WalterMadelim](#):
>
> When we handle our functions in practice, it would be perfect if we define and call standard functions (at the definition, all names are read from the arg line; at the caller’s place, we specify all arguments). But this style in practice would soon become very cumbersome. Imagine if you have a function with a long arg list, and that function still needs to be wrapped within a “shell” function. So that “shell” function also has to define a long list of args.

There already have been a number of topics on how to organise many method arguments, such as

> [@Good coding practices: How to cluster many variables in function argument](https://discourse.julialang.org/t/good-coding-practices-how-to-cluster-many-variables-in-function-argument/92855):
>
> Hello there, I’m still fairly new to julia, but I guess it is anyway a general programming question. In my code there are several physical parameters, e.g. mass,speed,height,… as well as numerical parameters for different numerical methods used subsequently, e.g. n1,n2,n3,…, and m1,m2,m3,… (In reality I give them more useful names). Now I wrote a function which does the main calculation function fun\_unclear(mass,speed,height,n1,n2,n3,m1,m2,m3) end However, as there are so many arguments (ar…

and we are starting to get off-topic here, but in general you would just group your arguments into (one or multiple) structs, (named) tuples, …

> [@WalterMadelim](#):
>
> As you can see, the standard grammar in `arg.jl` is very cumbersome.

This example is also just very artificial. You destructure your generator to 19 variables, which you then later combine again. Instead you could have just defined (e.g.) `vec = Tuple(rand(1000) for _ = 1:19)` and `function loop_over_global(vec) ... end`.

[Previous page](https://discourse.julialang.org/t/a-question-about-redefining-a-function-in-julia/133579.md?page=1)
