GithubHelp home page GithubHelp logo

vic / expat Goto Github PK

View Code? Open in Web Editor NEW
177.0 6.0 5.0 72 KB

Reusable, composable patterns across Elixir libraries

Home Page: https://hex.pm/packages/expat

License: Apache License 2.0

Elixir 100.00%
elixir pattern-matching composable-patterns guards named-patterns algebraic-data-types union-types patterns macros

expat's People

Contributors

vic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

expat's Issues

Generated macro functions.

Following @OvermindDL1's idea:

Currently when you define a named pattern

   def var(name, meta, context) when is_atom(name) and is_list(meta) and is_atom(context)

The following macros are generated:

defmacro var()
defmacro var(bindings)
defmacro var(name, bindings)
defmacro var(name, meta, bindings)
defmacro var(name, meta, context, bindings)

var() will underscore all pattern variables not used in guard.
bindings is a Keyword of names to expressions, used to bind variables inside the pattern.
All other functions are just there for providing positional arguments (vs named ones via the last keyword)

Now, I'm thiking about adding a couple more:

defmacro var?(expr)
defmacro var!(bindings)

The first one will just check that expr conforms - that is it matches the pattern and all its guards are satisfied
and the second will raise an error unless all variables inside the patter are bound by name from bindings, it will be used for as data constructor, even for those patterns with guards.

Raise on keys for non existing variables in matches

Hi! First of all: fantastic project!

Thanks you and sharing how the lib helps my usecase

I was writing a credo check. I needed to match on "pipe operator where the second param is function application". Those kinds of patterns are pretty big:

{:|>, a,
          [b, {{:., c, [{:__aliases__, meta, [module_name]}, function_name]}, d, params}]},

but using the lib makes them more manageable:

  defpat(pipe({:>, meta, [before_pipe, after_pipe]} = ast))

  defpat(
    function_call(
      {{:., dot_meta, [{:__aliases__, module_meta, [module_name]}, function_name]}, params_meta,
       params} = ast
    )
  )
  defp traverse(
         pipe(
           meta: a,
           before_pipe: b,
           after_pipe:
             function_call(
               dot_meta: c,
               module_meta: meta,
               module_name: module_name,
               function_name: function_name,
               params_meta: d,
               params: params
             )
         ),
         ...) do

Thank you very much for making composing pattern matches easier! I wanted to share with you how much easier it makes writing those checks :)

Actual issue

If I make a pattern like this:

  defpat ok({:ok, val})

but then misuse it like this:

  def my_fun(ok(value: value)) do
    value
  end

Notice that the binding is called val but used :value as the key in the keyword list. The error I get is:

warning: variable "value" does not exist and is being expanded to "value()", please use parentheses to remove the ambiguity or change the variable name

If I understand correctly, it means that the key value is ignored when there is no binding called this way. It might be a little bit confusing in case of typos to understand what is happening.

Would you consider it a good idea to raise in case usage of a given pattern tries to access non-existent binding?

If yes, I could try digging into it over the weekend and checking if I understand the lib enough to make that change.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.