alehander92 / gara

MIT License
103 stars 4 forks source link

Suggestion: Leverages Nim's multiple dispatch to make it extensible #17

Open geohuz opened 5 years ago

geohuz commented 5 years ago

Example from Julia's patterndispatch:

@pattern f(x) =  x
@pattern f(2) = 42

println([f(x) for x=1:4])
prints

[1, 42, 3, 4]

actually the @pattern expands to the following code:

const f = (args...)->dispatch(args...)

# ---- Pattern methods: ----
# f(x,)
function match1(x)  #  test_examples.jl, line 6:
    x
end

# f(2,)
function match2()   #  test_examples.jl, line 7:
    42
end

# ---- Dispatch methods: ----
function dispatch(x_1::Any)
    match1(x_1)
end

function dispatch(x_1::Int64)
    if is(x_1, 2)
        match2()
    else
        match1(x_1)
    end
end

You can see it is a really powerful idea which decoupling the dispatch logic from giant if/else block and new logic can be dynamically added. I would say it's a general pattern of multi-method which called predicate dispatch: https://en.wikipedia.org/wiki/Predicate_dispatch

alehander92 commented 5 years ago

Yeah, this is pretty cool: I like it a lot in Elixir.

However, this is an independent feature: we can have both the match branch structure and matchable overloads.

Matchable overloads would look a bit like this: https://github.com/alehander42/poly

alehander92 commented 5 years ago

On the other hand in typed languages it leads to some boilerplate: as you usually have to type the whole header with types etc, so using a single match in a function still would be idiomatic

alehander92 commented 5 years ago

new logic can be dynamically added. this is also not very desirable: having all the branches for the same function in one place is very important.

matchproc f(n: int, m: int):
  f(2, 0):
    0

  f(2, m):
    m

  f(n, m):
    n

maybe this can be possible, but still not sure if worth it?