--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/01071A82-653F-488B-B17A-8C0858418C0C%40achempion.com.
On 2 Jun 2022, at 23:59, 'Andrey Yugai' via elixir-lang-core <elixir-l...@googlegroups.com> wrote:
I don't think there's much gain in fiddling with Elixir internals trying to modify special form, or writing new macro specifically to omit the left argument in `::/2` for function specs. Perhaps more profoundly, this would implicitly tie one spec to one function clause, which is kinda odd if you want to specify typespecs for all clauses before a function head.
I do not think we should change the language to make specs
shorter.
One could even argue that having to repeat a 'too' long function
name might nudge the programmer in the direction of re-thinking
the naming of the function:
Maybe there is a more descriptive name or location for the
function? Maybe the function is trying to do too much and could be
split up?
As a side note, if people would like to try this out in their own
code,
it is possible to do so without altering the language itself:
```
defmodule AlteredSpecSyntax do
defmacro __using__(_opts) do
original_module = module_defining_macro(__CALLER__, :@, 1)
quote do
Module.put_attribute(__MODULE__,
AlteredSpecSyntax.OriginalModule, unquote(original_module))
import unquote(original_module), except: [@: 1]
import AlteredSpecSyntax
end
end
import Kernel, except: [@: 1]
defmacro @ast do
case ast do
# Add special cases to all kinds of expressions you want
to intercept...
{:spec, _, expr} ->
desugar(expr)
# ... and pass others on unchanged
_ ->
original_module = Module.get_attribute(__MODULE__,
AlteredSpecSyntax.OriginalModule)
quote do
original_module.@(unquote(ast))
end
end
end
defp desugar(expr) do
# Do whatever you want here :-)
expr |> Macro.to_string |> Code.format_string! |>
IO.puts
# ... and return the AST you _actually_ want the module to
include from here
end
defp module_defining_macro(env, macro_name, arity) do
env.macros
|> Enum.filter(fn {_module, macros} ->
macros[macro_name] == arity end)
|> List.first({Kernel, nil})
|> elem(0)
end
end
# Example usage:
defmodule Foo do
use AlteredSpecSyntax
@spec a() :: 42
def a(), do: 42
end
```
~Marten / Qqwy