On Monday, August 29, 2016 at 2:26:41 PM UTC-6, Wiebe-Marten Wijnja wrote:
The idea is to be able to create application-specific comparisons between 
data types, *where these comparisons make sense*.

Hmm, being able to compare disjoint types seems potentially painful and 
most likely incurring a significant overhead compared to just doing it 
manually...  I'm guessing that is where the module explosion talked of 
before came in to play.  It sounds like needing to create a multi-method 
dispatcher in Elixir, and if so the best you could get (without knowing all 
types absolutely at compile-time) would be log(N) runtime, which is not too 
bad...

You could potentially sneak in some tricks though.  If you use something 
like protocols (though something new, not protocol) to generate a call tree 
in a single module, a single entrance function that matches based on both 
of the types (properly ordered so the beam can efficiently match well) 
would get it down to log(n).  Hmm, although if you have a *lot* of 
potential matches (and I mean a **LOT**) then you could dispatch into a map 
and that 'might' be faster (though honestly I would not bet on it).  This 
would require a post-compile step like protocols do though (is there a 
pattern to do those kind of things with elixir or are protocols just 
'special'?).  For normal macro's the best you could really get is to 
manually specify everything in a single file in your base project, just 
import the other modules that define matchers, and have a macro build up 
the same call tree.  Easy enough to do but does require the end-user to 
import all other possible modules compare implementations into it so the 
macro can build the call tree, which can be easy to forget something, but 
good enough for an initial test implementation.

With that you would only have 1 module necessary (with an additional 1 for 
each you import, but those could just be function calls onto some base 
module for each type so that is effectively free).  But the macro would 
just generate something like:
```elixir

# Example structsdefmodule Bike do
  defstruct gears: 5end
defmodule Car do
  defstruct top_speed: 80end
defmodule Truck do
  defstruct wheels: 4
  def compare(%{wheels: wheels0}, %{wheels: wheels1}), do: Comparable.compareend
# An example of what a macro could generate given some information that 
describes things:defmodule Comparable do
  def compare(t, t), do: :eq  # Could generalize this call to something like:  
# def compare(%{__struct__: type}=t0, %{__struct__: type}=t1), do: 
type.compare(t0, t1)  # However that catches structs that do not support a 
compare and has a speed overhead due to dynamic dispatch, so I would not 
recommend it
  def compare(%Bike{gears: gears0}, %Bike{gears: gears1}), do: compare(gears0, 
gears1)
  def compare(%Bike{}, %Car{}), do: :lt
  def compare(%Bike{}, %Truck{}), do: :lt
  def compare(%Car{top_speed: top_speed0}, %Car{top_speed: top_speed1}), do: 
compare(top_speed0, top_speed1)
  def compare(%Car{}, %Bike{}), do: :gt
  def compare(%Car{}, %Truck{}), do: :lt
  def compare(%Truck{wheels: wheels0}, %Truck{wheels: wheels1}), do: 
compare(wheels0, wheels1)
  def compare(%Truck{}, %Bike{}), do: :gt
  def compare(%Truck{}, %Car{}), do: :gt
  def compare(%{__struct__: _t0}, %{__struct__: _t1}, do: raise MatchError(blah)
  def compare(t0, t1), do: if(t0<t1, then: :lt, else: if(t0>t1, do: :gt, else: 
if(t0 == t1, do: :eq, else: raise MatchError(blah))))end

```
That should be quite easily optimizable by the beam and be quite efficient, 
even with large match sets (log(n) specifically).

On Monday, August 29, 2016 at 2:58:15 PM UTC-6, José Valim wrote:
>
> Given the examples below, maybe it would be better to provide protocols 
> for each of those cases. The protocol would convert those data types to an 
> intermediate representation that would be easy to compare on.

 
This could indeed be faster, however you'd have to get everything to agree 
on a single representation (a special tuple format perhaps? but then how 
would that rank with other tuples?).

>

-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/69a8649e-63b5-49dd-91b5-b9b97d6daef1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to