# Supporting syntax \`x not in y\` as alias for \`!(x in y)\`

**URL:** <https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146>\
**Category:** Internals & Design\
**Created:** [February 13, 2024, 11:01am UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146 "2024-02-13T11:01:34Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![fingolfin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fingolfin/32/6033_2.png) [@fingolfin](https://discourse.julialang.org/u/fingolfin)\
**Post date:** [February 13, 2024, 11:01am UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/1 "2024-02-13T11:01:34Z")

</div>

One thing I like in Python is that they allow writing `x not in y` instead of `!(x in y)`. To me this results in code that is much easier to read (obviously this is subjective).

I wonder if it would be possible to support this in Julia without introducing serious ambiguities to the language, and how much effort it would take.

---

<div class="post-metadata">

**Author:** ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)\
**Post date:** [February 13, 2024, 11:07am UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/2 "2024-02-13T11:07:08Z")

</div>

A related issue: [Add infix "!in" as synonym for ∉ ? · Issue #15353 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15353)

---

<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:** [February 13, 2024, 12:04pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/3 "2024-02-13T12:04:17Z")

</div>

> <https://github.com/JuliaLang/julia/issues/25512>
>
> It would be nice to be able to negate infix operators by writing
> \`\`\`julia
> a !\<…op\> b
> \`\`\`
> and have that be equivalent to
> \`\`\`julia
> !(a \<op\> b)
> \`\`\`
> This is analogous to how \`!\<function\>\` works, and it also works for operators called in function form, like this:
> \`\`\`julia
> julia\> !\<(3, 5)
> false
> \`\`\`
> Also allowing infix negation seems more consistent.
> 
> Related discussion is \[here\](https://discourse.julialang.org/t/for-infix-operators/8257)
> 
> Many unicode operators have negated versions, but not all. Furthermore, negated unicode operators frequently are rendered as small and hard to read compared to surrounding code. As for ascii operators, I miss in particular:
> \`\`\`julia
> a !in A
> b !isa B
> C !\<: D
> \`\`\`
> The unicode version of \`!in\` is \`∉\`, but mixing \`in\` and \`∉\` in code isn't very pleasing to the eye. And having \`!\` compose with arbitrary infix operators means that they will always work, instead of depending on whether or not a suitable negated unicode symbol happens to be available.

---

<div class="post-metadata">

**Author:** ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)\
**Post date:** [February 13, 2024, 1:49pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/4 "2024-02-13T13:49:27Z")

</div>

This is one of the cases where I prefer the unicode `a ∉ b` over `!(a in b)`.

My personal convention is to use ∈, ∋, and ∉ for inclusion tests, and `in` for iteration (which is a syntactic sugar for = anyhow).

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 13, 2024, 2:36pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/5 "2024-02-13T14:36:04Z")

</div>

> [@HanD](#):
>
> I prefer the unicode `a ∉ b`

(Note for new users: you can type `∉` by tab-completing `\notin`. This works in the Julia REPL and other interactive environments, and all major editors can also be configured to support these tab completions.)

---

<div class="post-metadata">

**Author:** ![fingolfin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fingolfin/32/6033_2.png) [@fingolfin](https://discourse.julialang.org/u/fingolfin)\
**Post date:** [February 13, 2024, 2:41pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/6 "2024-02-13T14:41:54Z")

</div>

Thanks for the pointers to the two existing issues. Though I’d consider `!in` strictly inferior to `not in` in terms of readability.

Also thanks to pointing out ∉ – I’ll make sure to use that for demos but I don’t feel comfortable using unicode like that in my actual code (of course that’s a “me” problem 😉 ).

> [@HanD](#):
>
> My personal convention is to use ∈, ∋, and ∉ for inclusion tests, and `in` for iteration (which is a syntactic sugar for = anyhow).

Totally off-topic, but: for iteration, I don’t view `in` as syntactic sugar for `=`, but rather `=` as a horrible alternative syntax for `in` that is there to appease people coming from certain programming languages – it is IMHO utterly confusing for anyone else :-).

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [February 13, 2024, 2:49pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/7 "2024-02-13T14:49:36Z")

</div>

> [@fingolfin](#):
>
> I don’t view `in` as syntactic sugar for `=`, but rather `=` as a horrible alternative syntax for `in` that is there to appease people coming from certain programming languages – it is IMHO utterly confusing for anyone else

I agree with this.

---

<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:** [February 13, 2024, 3:48pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/8 "2024-02-13T15:48:23Z")

</div>

> [@fingolfin](#):
>
> I’d consider `!in` strictly inferior to `not in` in terms of readability.

That would be highly inconsistent, since `!` is the negation operator. Are you suggesting replacing `!` with `not`, so that, e.g. `!=` becomes `not ==` or `not =` ?

---

<div class="post-metadata">

**Author:** ![fingolfin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fingolfin/32/6033_2.png) [@fingolfin](https://discourse.julialang.org/u/fingolfin)\
**Post date:** [February 13, 2024, 4:16pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/9 "2024-02-13T16:16:34Z")

</div>

> [@DNF](#):
>
> Are you suggesting replacing `!` with `not`, so that, e.g. `!=` becomes `not ==` or `not =` ?

No, I am not, and I think nothing I wrote suggests that? I talked about exactly one thing, “in”.

Though ironically what you wrote highlights one of the issues with the `!in` proposal – `!=` does _not_ mean `not =` after all. (That’s not to say I am opposed to it, but it just isn’t a perfect solution either)

---

<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:** [February 13, 2024, 4:36pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/10 "2024-02-13T16:36:05Z")

</div>

> [@fingolfin](#):
>
> No, I am not, and I think nothing I wrote suggests that? I talked about exactly one thing, “in”.

In terms of consistency, I don’t think there should be both `!` and `not` to mean logical negation. It was a genuine question (which seemed to follow logically), not an accusation.

> [@fingolfin](#):
>
> Though ironically what you wrote highlights one of the issues with the `!in` proposal – `!=` does _not_ mean `not =` after all. (That’s not to say I am opposed to it, but it just isn’t a perfect solution either)

I totally agree. The usage of `!=` is very unfortunate, and is also a blocker for the issue I linked to further up. Having generic `!<op>` behavior would be great, but it’s too late to change `!=`. Still, in terms of consistency, `!in` is far preferable to `not in`, which I think would stick out like a sore syntactical thumb.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [February 13, 2024, 4:47pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/11 "2024-02-13T16:47:14Z")

</div>

I think we could live with `!=` and `!==` being special cases, and all other infix operators being negatable with the `!` prefix.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 13, 2024, 5:59pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/12 "2024-02-13T17:59:41Z")

</div>

We could also be more conservative and just allow `!in` and `!isa`, which seem like the least-objectionable and the most-beneficial infix operators to negate. I don’t see much of a need for `!<` or `!!` or `!:<`.

---

<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:** [February 13, 2024, 6:06pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/13 "2024-02-13T18:06:31Z")

</div>

A blocking issue to general infix negation is that `!(operator)` is not an infix.

```julia-repl
julia> typeof(!<)
ComposedFunction{typeof(!), typeof(<)}

julia> 1 (!<) 2
ERROR: ParseError:
1 (!<) 2
#└─────┘ ── extra tokens after end of expression

```

We could maybe special case (for example) `!in` to evaluate like `∉` (rather than `ComposedFunction(!, in)`) and to have infix parsing, but doing this for all infix operators seems excessive and like it would probably be breaking in some cases. Such handling would mean that disagreement could arise between `(!in)(a,b)` and `!(in(a,b))` if a package overloads one but not the other.

It looks like the above poster beat me to part of this post.

---

<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:** [February 13, 2024, 6:14pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/14 "2024-02-13T18:14:29Z")

</div>

> [@stevengj](#):
>
> allow `!in` and `!isa`

`!in` is definitely the one I miss the most.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 13, 2024, 6:16pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/15 "2024-02-13T18:16:32Z")

</div>

> [@DNF](#):
>
> `!in` is definitely the one I miss the most.

I agree, but it would be weird to allow `!in` but not `!isa` — the principle being to allow `!` before any operator that is spelled like an ordinary function name.

---

<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:** [February 13, 2024, 6:18pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/16 "2024-02-13T18:18:42Z")

</div>

I just meant, then the most important case would be covered, nothing against `!isa`

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [February 13, 2024, 6:33pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/17 "2024-02-13T18:33:27Z")

</div>

> [@fingolfin](#):
>
> No, I am not, and I think nothing I wrote suggests that? I talked about exactly one thing, “in”.

The relevance is that Python uses `and, or, not` where Julia uses `&&, ||, !`. Special-casing `not in` doesn’t make as much sense for that reason, `!in` is consistent with the rest of the language.

One can argue that `and, or, not` is easier to read, but Julia has already decided the question of how to spell logical operators.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [February 13, 2024, 7:06pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/18 "2024-02-13T19:06:46Z")

</div>

> [@mikmoore](#):
>
> We could maybe special case (for example) `!in` to evaluate like `∉` (rather than `ComposedFunction(!, in)`) and to have infix parsing, but doing this for all infix operators seems excessive and like it would probably be breaking in some cases. Such handling would mean that disagreement could arise between `(!in)(a,b)` and `!(in(a,b))` if a package overloads one but not the other.

I don’t think it’s breaking. Currently `a !x b` (with `x` an infix operator) gives a syntax error. We would just make it equivalent to `(!x)(a, b)` which already works for all infix operators AFAIK. Nothing else would change, for example the (silly) `!<` would still be a `ComposedFunction{typeof(!), typeof(<)}`, except that currently you have to write `(!<)(1, 2)` and with this change you could also write `1 !< 2`…

But then I admit I can’t see much use for it outside of `!in`. It makes no sense for most other ASCII operators and would probably need special casing for `&&` and `||`. It would make sense for many Unicode operators but these typically have a Unicode negation already, e.g. `≉`, `⊄`, etc.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [February 13, 2024, 7:07pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/19 "2024-02-13T19:07:35Z")

</div>

> [@mnemnion](#):
>
> Special-casing `not in` doesn’t make as much sense for that reason, `!in` is consistent with the rest of the language.

Yeah I think the sane alternative would be `notin` rather than `not in`.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [February 13, 2024, 7:25pm UTC](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146/20 "2024-02-13T19:25:20Z")

</div>

> [@sijo](#):
>
> Yeah I think the sane alternative would be `notin` rather than `not in`.

I would read `!in` as “not in” in any of these spellings, so I favor `!in` as the most consistent choice. `!isa` is kind of goofy but `isn'ta` isn’t parsable and `isnta` is illegible, `isnota` isnota much better choice, so I’d take `!isa` there as well, although I’d probably stick with `!(T isa U)` for aesthetic reasons.

Actually, `isnta` is growing on me. `T isnta U` isn’t proper English but nothing says it has to be.

[Next page](https://discourse.julialang.org/t/supporting-syntax-x-not-in-y-as-alias-for-x-in-y/110146.md?page=2)
