I can “overwrite” native stdlib functions, just by not importing them from the kernel, right?
Like:
defmodule Filter do
Import Kernel, except: [not: 1]
def not args do
# ...
end
end
Okay, that’s valid! But what if I wanted to put this function as a callback in a behavior, what would the syntax look like? Is that possible?
defmodule FilterBehaviour do
Import Kernel, except: [not: 1]
@callback not(args) :: any()
end
It doesn’t seem to work yet as a syntax error
1 Like
(Have to preface it with: I would not recommend doing this)
Are you sure the syntax error you’re getting is not related to the args
type being undefined? The following works for me:
defmodule FilterBehaviour do
@callback not(any()) :: any()
end
defmodule Impl do
@behaviour FilterBehaviour
import Kernel, except: [not: 1]
@impl FilterBehaviour
def not(_args), do: :ok
end
In fact, yes, i do have sure its not related. I tried to built a simpler example but this is my current module:
defmodule Supabase.PostgREST.Query.FilterBehaviour do
@moduledoc false
import Kernel, except: [not: 1, or: 2, in: 2]
@type column :: String.t()
@type value :: term
@callback eq(column, term) :: String.t()
@callback neq(column, term) :: String.t()
@callback gt(column, term) :: String.t()
@callback lt(column, term) :: String.t()
@callback gte(column, term) :: String.t()
@callback lte(column, term) :: String.t()
@callback is(column, term) :: String.t()
@callback in(column, term) :: String.t()
end
looks at the in
callback, it gives me the following syntax error:
== Compilation error in file lib/supabase/postgrest/query/filter_behaviour.ex ==
** (SyntaxError) lib/supabase/postgrest/query/filter_behaviour.ex:22:28: syntax error before: ')'
|
22 | @callback in(column, term) :: String.t()
| ^
(elixir 1.14.4) lib/kernel/parallel_compiler.ex:340: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/7
TL;DR this works:
@callback unquote(:in)(column, term) :: String.t()
I can’t give you an intelligent answer as to why but I’m assuming it has to do with how def
vs @callback
get parsed. @callback
clearly tries to parse in
as an operator, even if it’s excluded.
That’s interesting! I was mislead a bit by or/2
being excluded, but no or
callback being defined in the module - trying to define it also fails, so seems there’s something generally different about infix macros?
Defining it should work. You define infixes like so:
def a or b, do: a + b
I just don’t know how you would write that as a callback spec
…and now that I said that:
@callback column() or term() :: String.t()
…also compiles so… there we go, ha.
3 Likes
Huh, works for both @callback
and def
. And since the implementing module is its own namespace of course, the import Kernel, except: [...]
is not needed there.
defmodule Filter do
@callback not(term) :: String.t()
@callback term or term :: String.t()
@callback unquote(:in)(term, term) :: String.t()
end
defmodule Impl do
@behaviour Filter
@impl Filter
def not(a), do: "!#{a}"
@impl Filter
def a or b, do: "#{a} or #{b}"
@impl Filter
def unquote(:in)(a, b), do: "#{a} in #{inspect(b)}"
end
Impl.not(1) <> ", " <> Impl.or(1, 2) <> ", " <> Impl.in(3, [3, 4])
#=> "!1, 1 or 2, 3 in [3, 4]"
Soo, yeah… thanks for the TIL!
1 Like
You can also do left in right
, no need for unquote.
3 Likes