Qqwy

Qqwy

TypeCheck Core Team

So while writing Confy, I wanted to turn shorthand atoms like:integer, :string, :atom into the ‘normal’ forms &Confy.Parsers.integer/1, &Confy.Parsers.string/1, &Confy.Parsers.atom/1, etc.

However, I struggled to properly perform quoting and unquoting while using the function capture operator&.

In the end, I settled on the following snippet:

  # Replaces simplified atom parsers with
  # an actual reference to the parser function in `Confy.Parsers`.
  # NOTE: I dislke the necessity of `Code.eval_quoted` here, but do not currently know of another way.
  defp normalize_parser(parser) when is_atom(parser) do
    case Confy.Parsers.__info__(:functions)[parser] do
      nil -> raise ArgumentError, "Parser shorthand `#{inspect(parser)}` was not recognized. Only atoms representing names of functions that live in `Confy.Parsers` are."
      1 ->
        {binding, []} = Code.eval_quoted(quote do &Confy.Parsers.unquote(parser)/1 end)
        binding
    end
  end
defp normalize_parser(other), do: other

Note the Code.eval_quoted line: Although it is probably safe since it is only executed when parser indeed is an atom and exists as a function inside the Confy.Parsers module, it does not feel nice to need it.
Is there another way to build a function capture out of a module and function atom?

Note that 'function captures like wrapping everything with fn are not what I am looking for, since the result of normalize_parser is also used to create documentation:
inspect(&Module.foo/1) is "&Module.foo/1" whereas
inspect(fn x -> Module.foo(x) end) is "#Function<6.127694169/1 in :erl_eval.expr/5>".

Thanks! :smile:

Showing Posts 1 to 5

OvermindDL1

OvermindDL1

Would not &apply(Confy.Parsers, parser, [&1]) work? :slight_smile:

apply/3 is so very useful. ^.^

iex(1)> h apply/3

                     def apply(module, function_name, args)                     

  @spec apply(module(), function_name :: atom(), [any()]) :: any()

Invokes the given function from module with the list of arguments args.

apply/3 is used to invoke functions where the module, function name or
arguments are defined dynamically at runtime. For this reason, you can't invoke
macros using apply/3, only functions.

Inlined by the compiler.

## Examples

    iex> apply(Enum, :reverse, [[1, 2, 3]])
    [3, 2, 1]

Consequently it has no speed hit over a normal indirect call either since they lower to the same beam code, just to be sure I’ve also benchmarked it. ^.^

OvermindDL1

OvermindDL1

Also instead of this, this is faster:

if function_exported?(Confy.Parsers, parser, 1) do
iex(2)> h function_exported?

                def function_exported?(module, function, arity)                 

  @spec function_exported?(module(), atom(), arity()) :: boolean()

Returns true if module is loaded and contains a public function with the given
arity, otherwise false.

Note that this function does not load the module in case it is not loaded.
Check Code.ensure_loaded/1 for more information.

Inlined by the compiler.

## Examples

    iex> function_exported?(Enum, :member?, 2)
    true
Qqwy

Qqwy OP

TypeCheck Core Team

Using function_exported? is definitely the way to go. Thank you, I did not know about that function!

As for using apply: It would end up in the documentation as well:
See f.e. here:

Validated/parsed by calling &Confy.Parsers.boolean/1 .

this would then become

Validated/parsed by calling &apply(Confy.Parsers, :boolean, [&1]) .

which is not nearly as nice.

Thus I really am looking for a way to construct &SomeModule.foo/1 where foo is a dynamic value.

If there is no way around sing Code.eval_quoted then that is fine, but I did want to check :slight_smile:.

hauleth

hauleth

Function.capture/3 is what you are looking for.

axelson

axelson

Scenic Core Team

Wow, there’s so many little goodies in the stdlib. Never ceases to amaze me.

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
rlipscombe
I’d like to create a file with 600 permissions (rw-------), but there’s a race condition if I create it and then change the permissions. ...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
saleyn
Is there a way to import record definitions in the iex shell for pretty printing (similar to the rr command in the erl shell)? This woul...
New
rlipscombe
When I use Mix.install with a git dependency, using git@github.com:... how do I change the SSH identity used? I’ve got two Github accoun...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews