If in === ∈, why does .∈ work but .in fails with a ParseError?

Hello everyone,

I’m trying to understand the following behavior regarding in and (I guess they’re called operators?). While they are functionally identical (in === ∈ returns true), they behave differently when used with broadcasting (.) inside macros like @subset in DataFramesMeta.jl. Here’s the code:

using DataFrames, DataFramesMeta

df = DataFrame(x = [1, 1, 2, 2], y = [1, 2, 101, 102])

# This works as expected:
@subset df :y .∈ Ref([101, 102])

# This fails with a ParseError:
@subset df :y .in Ref([101, 102])

ParseError: whitespace is not allowed here.

Why is that?

because parser treats them differently. It may sound like a non-answer but that’s basically the whole reason. The parser COULD special-case .in, but that would be more confusing / inconsistent than helpful

This is it. The object bound to the names in and are the same function object (and this === but that doesn’t have any bearing on how they’re parsed. One is a name, the other is an operator. You can also easily change what they are bound to do that they don’t refer to the same object.

Of course it’s implicit in the previous answers - and even in the question, but I think it is worth telling, for other readers at least, that broadcasting does work with in, but it should be coded as for regular functions, i.e. in.(y, Ref([101, 102])) - or in the OP’s example with DataFramesMeta:

@subset df in.(:y, Ref([101, 102]))

Another thing implicit in previous answers, but perhaps should be made explicit, is that whether in === ∈ is true depends on the namespace, that is, they’re identical in Main, but not in all other modules:

julia> in === ∈
true

julia> baremodule MyModule
           const in = 3
           const ∈ = 7
           const v = in === ∈
       end
Main.MyModule

julia> MyModule.in === MyModule.:(∈)
false

julia> MyModule.v
false

To elaborate on this:

  • in is just a name
  • is an operator, meaning it’s possible to call it, for example, like so: x ∈ y, and the broadcasting syntax is different