I'm trying to work on this one,
I have a working solution, what I did was to create a module called Guard,
and this module gets automatically required same as Kernel, Kernel.SpecialForms 
and
Kernel.Typespecs.

But I have realized that there is a limitation, and is when the macros are not 
passed a variable,
but a reference to it,

let's say:
kind = {:map, 1}
is_kind(%{foo: :bar}, kind),

is there trick to evaluate kind inside the macro that is valid in  

    cond do
      is_atom(kind) ->
        quote do: ....

      is_tuple(kind) and is_atom(:erlang.element(1, kind)) ->
        quote do: ...

but without putting the logic inside a quote (which will be invalid in a guard),
and unquoting kind to get the value from its calling environment.

thank you.

On Sat, 13 Aug 2016 02:22:09 +0700
eksperimental <eksperimen...@autistici.org> wrote:

> the Comparison group of kinds was the last group and I just included just to 
> see how much i could
> push guard,
> 
> But the rest of the groups are less controversial.
> 
> - Basic and built-in types
> - Additional: Derived from is_* functions
> - Additional: Literal numbers
> 
> and maybe it is arguable if we need them all of them,
> - Additional: Convenience
> 
> Would it be possible to have the best of both worlds here?
> Allow users to define their own guards/kinds, and be able to call them from 
> is/are functions, and
> offering a default set of kinds/guards like the ones listed above (or 
> whatever we agree are the
> minimum needed to be supported by the language).
> 
> defmodule DateTime
> 
>   defkind second(seconds) when seconds >= 0 and seconds <= 60
> 
>   def new(..., seconds) when seconds is :second
> 
> end
> 
> The benefit of are* functions is that it reduces the amount in a significant 
> way when you have
> several items on the left and several kinds on the right hand side.
> 
> also having a defined list of default kinds, helps us to translate directly 
> from the typespecs
> into guard definitions.
> 
> On Fri, 12 Aug 2016 20:24:22 +0200
> José Valim <jose.va...@plataformatec.com.br> wrote:
> 
> > >
> > > thank you for your answer José,
> > >
> > > I can look into how we can add new kinds (I will need help with
> > > defining how to deal with conflicting kinds).
> > > I think the defguard approach is reasonable, but I thought it was
> > > ditched for some reason.
> > >
> > > What we could do is create a defkind macro that uses defguard, but
> > > creates kinds only (since defguard can create any kind of guard).
> > >    
> > 
> > I think the concern runs a little bit deeper: if we have defkind, that is
> > based on defguard, are they then like any other macro? Would we also manage
> > importing and conflicts with import? If so, why don't we use them like any
> > other macro?
> > 
> > When reading your proposal, I effectively broke it two parts:
> > 
> > 1. A huge collection of kinds, which could be implemented as macros.
> > Imagine if we had is_mfa/1, is_list/2 and so on in the stdlib or on a
> > Guards module.
> > 
> > 2. A set of operators that easily apply a set of kinds (or macros) on the
> > rhs to the lhs.
> > 
> > Once we break it apart, I have the following feedback:
> > 
> > 1. Instead of having a large collection of guards in the stdlib maybe we
> > should make it easier to define your own guards since most times you can
> > give it better names that are specific to your domain
> > 
> > 2. What is the benefit of using "is/are" instead of multiple "and/or"
> > calls? I am aware the former is more succinct but remember that if we have
> > multiple and/or calls, then we can always create a new guard with defguard
> > 
> > In other words, instead of having a general solution with a bunch of guards
> > in the stdlib alongside some pre-defined combinations, I would prefer to
> > have a composable solution that is built from small blocks because folks
> > can extend it to their domain without forcing Elixir to add more kinds.
> > 
> > Let me try to be more concrete. With the proposal above, I'd be tempted to
> > write:
> > 
> > defmodule DateTime
> >   def new(..., seconds) when seconds is [{:gte, 0}, {:lte, 60}] do
> > 
> > 
> > But the best solution would most likely be:
> > 
> > defmoduel DateTime
> > 
> >   defguard is_seconds(seconds) when seconds >= 0 and seconds <= 60
> > 
> >   def new(..., seconds) when is_seconds(seconds)
> > 
> > end
> > 
> > 
> > Finally, I just want to say that, although I am not convinced on the "kind"
> > mechanism, I love this proposal because it is asking the right questions
> > and it makes me realize I could be writing better code. So thank you for
> > that!
> >   
> 

-- 
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-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/20170602072926.530696ae.eksperimental%40autistici.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to