# Warning: Method definition f(Any) overwritten

**URL:** https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060
**Category:** New to Julia
**Created:** [August 22, 2023, 12:12pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060 "2023-08-22T12:12:11Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![afyon](https://avatars.discourse-cdn.com/v4/letter/a/f4b2a3/32.png) [@afyon](https://discourse.julialang.org/u/afyon)
#### Post date: [August 22, 2023, 12:12pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/1 "2023-08-22T12:12:12Z")

</div>

Hi everyone,

I am trying to make a function that would look like this:

```julia
function create_f(flag::Bool)
   if flag
      f(x) = x^2
   else
      f(x) = x^3
   end
   return f
end

```

And, when I create this function, I got the warning that f is overwritten. I do understand the warning but I do not know why I got it, since both definitions of f happen in mutually exclusive blocks of code.

Then, when I execute `f = create_f(true)`, f is the cubic function while `f = create_f(false)` gives me the error that f is undefined. Could someone help me make this code work or at least explain to me why it cannot work ?

I know that something like:

```julia
function create_f(flag::Bool)
   if flag
      f1(x) = x^2
      return f1
   else
      f2(x) = x^3
      return f2
   end
end

```

does work fine but it is not very elegant.

Thanks a lot!

---

<div class="post-metadata">

### Author: ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)
#### Post date: [August 22, 2023, 12:55pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/2 "2023-08-22T12:55:34Z")

</div>

You might want to try this:

```julia
function create_f(flag::Bool)
    flag && return x -> x^2
    return x -> x^3
end

```

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [August 22, 2023, 1:54pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/3 "2023-08-22T13:54:13Z")

</div>

It works fine if you do

```julia
function create_f(flag::Bool)
   if flag
      f = x->x^2
   else
      f = x->x^3
   end
   return f
end

```

@algunion 's solution is the same but shortened by use of short circuiting.

Somehow in your original version, Julia seems to think that both `f(x)` denote the same function and then tries to add methods to it. That explains the warning because then the second `f(x) = ...` overwrites the first definition. I am not sure whether this should be treated as a bug or whether the `f(x)` syntax should only be used at toplevel or something.

---

<div class="post-metadata">

### Author: ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)
#### Post date: [August 22, 2023, 2:20pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/4 "2023-08-22T14:20:17Z")

</div>

`if` block does not introduce a new scope.

Here is a version where `f` is defined in a hard scope for both if/else branches:

```julia
function create_f(flag::Bool)
    function locf end
    if (flag)
        let f(x) = x^2
            locf = f
        end
    else
        let f(x) = x^3
            locf = f
        end
    end
    return locf
end

```

Now, both `create_f(true)(x)` and `create_f(false)(x)` are going to behave as expected.

Also, consider the following:

```julia
function nested(flag::Bool)
    f(x) = x
    if flag
        f(x) = x + 1
    end
    return f
end

f = nested(false)
f(2) # will produce 3

```

The thing is that the method/function definition takes place before the runtime call. Also, the method overriding takes place because `if` doesn’t introduce a new scope.

However, I am not (yet) able to explain why the `else` (`flag = false`) branch in the original function throws `UndefVarError: `f` not defined`.

## Later addition:

So there might be a bug after all:

```julia
function create_f(flag::Bool)
    if flag
        f(x) = x^2
    else
        f(x) = x^3
    end
    return f
end

@code_lowered create_f(true)
@code_lowered create_f(false)

```

`@code_lowered` produces:

```julia-auto
CodeInfo(
1 ─ Core.NewvarNode(:(f))
└── goto #3 if not flag
2 ─ f = %new(Main.:(var"#f#7"))
└── goto #3
3 ┄ return f
)

```

So, when `flag = false`, it just skips the `f` definition and attempts to return it. This behavior has nothing to do with overriding the method in the `else` branch (the same issue occurs if a different method signature is used).

We can compare with the following naive example:

```julia
function notbug(flag::Bool)
    if flag
        x = 3
    else
        x = 4
    end
    return x
end
@code_lowered notbug(true)
@code_lowered notbug(false)

```

… which produces (as expected):

```julia-auto
CodeInfo(
1 ─ Core.NewvarNode(:(x))
└── goto #3 if not flag
2 ─ x = 3
└── goto #4
3 ─ x = 4
4 ┄ return x
)

```

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [August 22, 2023, 3:40pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/5 "2023-08-22T15:40:44Z")

</div>

For dynamic creation of functions, use anonymous functions. In your case, the name `f` is also hidden inside the outer function, so this is clearly a job for a lambda.

---

<div class="post-metadata">

### Author: ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)
#### Post date: [August 22, 2023, 3:48pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/6 "2023-08-22T15:48:46Z")

</div>

> [@DNF](#):
>
> For dynamic creation of functions, use anonymous functions. In your case, the name `f` is also hidden inside the outer function, so this is clearly a job for a lambda.

Agree, but despite of best practice recommendation, I think there is a bug. The definition of `f` is simply skipped in the `else` branch - even if I try to force it like this:

```julia
function create_f(flag::Bool)
    if flag
        f(x) = x^2
        z = f(3)
    else
        f(x) = x^3
        z = f(3)
    end
    return f, z
end

@code_lowered create_f(true)
@code_lowered create_f(false)

create_f(true) # (var"#f#8"(), 27)
create_f(false) # UndefVarError: `f` not defined

```

`@code_lowered` output:

```julia
CodeInfo(
1 ─ Core.NewvarNode(:(z))
│ Core.NewvarNode(:(f))
└── goto #3 if not flag
2 ─ f = %new(Main.:(var"#f#8"))
│ z = (f)(3)
└── goto #4
3 ─ z = (f)(3)
4 ┄ %8 = Core.tuple(f, z)
└── return %8
)

```

P. S. And I think I know what is going on: in the `else` branch, only a method push takes place (and before runtime), with no definition for `f` (because the _actual_ name was already generated by `gensym`). So the runtime bug consists in failing to link `f` to the symbol generated by `gensym` when `flag=false`.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [August 22, 2023, 8:01pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/7 "2023-08-22T20:01:57Z")

</div>

You want an anonymous function:

Simple solution:

```julia
function create_f(flag::Bool)
  if flag
    x -> x^2
  else
    x -> x^3
  end
end

```

The above solution is, however, not type stable:

```julia-repl
julia> using Test

julia> @inferred create_f(true)
ERROR: return type var"#1#3" does not match inferred return type Union{var"#1#3", var"#2#4"}

```

A type stable solution:

```julia
function create_f(flag::Bool)
  m = flag ? 2 : 3
  let n = m
    x -> x^n
  end
end

```

Now the type is uniquely inferred:

```julia-repl
julia> using Test

julia> @inferred create_f(true)
#1 (generic function with 1 method)

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [August 22, 2023, 10:04pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/8 "2023-08-22T22:04:01Z")

</div>

It’s been discussed at previous times, but I’ll bring it back up. We probably want to disallow function definitions within control flow (e.g., conditional or loop blocks). This would not apply to anonymous functions, of course, which are the correct solution for such cases.

This could be considered breaking within version 1.x, although we might lawyer it through as a “bug fix” since such function definitions do not behave how one would expect or desire. The only breakage of “correct” code would be in cases where a function was incidentally defined within control flow but there was no competing definition to cause ambiguity.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [August 22, 2023, 10:09pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/9 "2023-08-22T22:09:30Z")

</div>

> [@algunion](#):
>
> Agree, but despite of best practice recommendation, I think there is a bug. The definition of `f` is simply skipped in the `else` branch - even if I try to force it like this:

This is [issue #15602](https://github.com/JuliaLang/julia/issues/15602). Closures’ underlying top-level method tables are made when the surrounding function is defined because a function call that rebuilds a method table (which we can do to global scope functions with `@eval`) is a lot slower than one that conditionally assigns one of several existing functions to a variable. At least now we get a warning, and it should be heeded because we could either get the “all definitions run” effect or the “redefinitions become failed assignments” effect.

> [@mikmoore](#):
>
> We probably want to disallow function definitions within control flow (e.g., conditional or loop blocks).

It’s fine in the global scope, it’s just a footgun during a repeatable function call.

> [@nsajko](#):
>
> A type stable solution:
> 
> ```julia-auto
> function create_f(flag::Bool)
> m = flag ? 2 : 3
> let n = m
> x -> x^n
> end
> end
> 
> ```

Incidentally, the let block isn’t necessary here, `x -> x^m` stably captures the value because there’s only 1 assignment with a type-stable value. `if flag m=2 else m=3 end` would be problematic though, in which case the let block helps.

---

<div class="post-metadata">

### Author: ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)
#### Post date: [August 22, 2023, 10:35pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/10 "2023-08-22T22:35:17Z")

</div>

Thanks, @Benny. I was unsuccessfully searching for the issue - but I restrained from creating another one (this seemed too _significant_ not to be already reported).

---

<div class="post-metadata">

### Author: ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)
#### Post date: [August 22, 2023, 10:45pm UTC](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/11 "2023-08-22T22:45:17Z")

</div>

@afyon, thanks for selecting a solution and helping others that will stumble upon this topic.

You selected my [post](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/2) as the solution - and I think it answers the OP well. However, I think @nsajko’s [solution](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/7) is more complete - since it also addresses the type-stability issue (e.g., it will be more instructive for others in the future).

So, I switched the solution to @nsajko’s [post](https://discourse.julialang.org/t/warning-method-definition-f-any-overwritten/103060/7). I hope that my decision resonates with you.
