# \`if foo isa Foo{K} where K; @show K; end\`: \`K\` not defined

**URL:** https://discourse.julialang.org/t/if-foo-isa-foo-k-where-k-show-k-end-k-not-defined/115572
**Category:** General Usage
**Created:** [June 12, 2024, 6:57pm UTC](https://discourse.julialang.org/t/if-foo-isa-foo-k-where-k-show-k-end-k-not-defined/115572 "2024-06-12T18:57:22Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [June 12, 2024, 6:57pm UTC](https://discourse.julialang.org/t/if-foo-isa-foo-k-where-k-show-k-end-k-not-defined/115572/1 "2024-06-12T18:57:22Z")

</div>

Is there a good way to make type parameters from the `where` keyword accessible in an `if` statement, the way we can with function signatures?

```julia-repl
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.10.4 (2024-06-04)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> struct Foo{K} end

julia> foo = Foo{3}()
Foo{3}()

julia> if foo isa Foo{K} where K
           @show K
       end
ERROR: UndefVarError: `K` not defined
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

```

It seems weird that `if foo isa Foo{K} where K` is valid syntax but leaves `K` undefined.

(I am aware that there are other ways of accomplishing this, such as defining `get_k(::Foo{K}) where K = K`. My question is about the syntactic inconsistency.)

---

<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: [June 12, 2024, 7:38pm UTC](https://discourse.julialang.org/t/if-foo-isa-foo-k-where-k-show-k-end-k-not-defined/115572/2 "2024-06-12T19:38:02Z")

</div>

This has nothing to do with `if` and everything to do with `where`.

```julia-repl
julia> foo isa Foo{K} where K
true

julia> K
ERROR: UndefVarError: `K` not defined

```

The reason that `Foo{K} where K` does not work is that it does not actually assign `K` as a variable. It’s only usable as a typevar within the expression it belongs to. As far as I know (which may be wrong) the parameter is only made available when `where` is used in a method definition (e.g., with `function`). I don’t have an explanation as to why.

I’m not aware of any responsible way to recover `K` from the type except for the `get_k` pattern you already mentioned.

_ONE SHOULD NOT_ but one can get this particular parameter with `typeof(foo).parameters[1]`. This is absolutely discouraged and may break in any Julia version. It’s also very brittle to changes in `Foo`.

---

<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: [June 12, 2024, 8:33pm UTC](https://discourse.julialang.org/t/if-foo-isa-foo-k-where-k-show-k-end-k-not-defined/115572/3 "2024-06-12T20:33:25Z")

</div>

> [@maxkapur](#):
>
> It seems weird that `if foo isa Foo{K} where K` is valid syntax but leaves `K` undefined.

`(Foo{K} where K)` is one type, all `isa` does is check if `foo` is an instance of said type. It reasonably does not assign variables in its scope. You just happened to make an `if` condition where a `K` value could exist in the branch, but what if the condition were `if foo isa (Foo{K} where K) || foo isa Complex`? Do you assign `K` when `foo = 1im`? `if` statements don’t make new local scopes anyway so it’s not possible to isolate any `K` assignment to a branch.

`where` in methods is different, the clause doesn’t belong to a type and it’s intended to get static parameters (not variables, you can’t reassign them) from the argument types after dispatch. Method syntax resembles other block structures but syntax often does different things in different places; `let` is probably the closest thing by taking inputs in the header, making a local scope, and returning an output, but you’re not dispatching to it and annotating the header variables restricts their further assignment unlike a method’s argument annotations used for dispatch.

---

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [June 13, 2024, 10:23pm UTC](https://discourse.julialang.org/t/if-foo-isa-foo-k-where-k-show-k-end-k-not-defined/115572/5 "2024-06-13T22:23:24Z")

</div>

That clears it up–thank you!

So, I take it by your “ONE SHOULD NOT” that there’s no stable API way to get `K` in line (i.e. without defining a `get_k()` method), correct?
