zer0-star / nim-curry

MIT License
12 stars 0 forks source link

Add support to `_` notation #1

Open hugosenari opened 4 years ago

hugosenari commented 4 years ago

Similar packages for other languages allow pass some constant, usually _, to ignore parameter in this call and expect it in next call.

ie:

proc my(a, b, c: int): int {.curry.} = a + b + c

let aC = my(1, _, 3)  # proc (b: int): int = 1 + b + 3
let bC = my(_, 2, 3)  # proc (a: int): int = a + 2 + 3
let C = my(_, _, 3)   # proc (a, b: int): int = a + b + 3
schneiderfelipe commented 3 years ago

That would require making my(1, _, 3) a macro, is that correct? Do you have an idea how could this be implemented, @hugosenari?

hugosenari commented 3 years ago

I'm newbie Not sure how, sorry.

But if I get your {.curry.} right :

proc my(a, b, c: int): int {.curry.} = a + b + c
# creates
proc my(a: int) = proc (b: int) = proc (c: int): int
# it requires some standard PlaceHolder
type PlaceHolder = distinct bool
const _ = true.PlaceHolder
# and more proc defs
proc my(discarded: PlaceHolder) = proc(b: int) = proc(c: int) = proc(a: int): int
proc my(a: int) = proc(discarded: PlaceHolder) = proc(c: int) = proc(b: int): int
proc my(a: int) = proc(b: int) = proc(discarded: PlaceHolder) = proc(c: int): int
# ...

In JS

// Curried with placeholders.
curried(1)(_, 3)(2);
// => [1, 2, 3]

pytoolz/toolz propose use flip or partial for this, isn't fancy should work.

fn.py uses a more radical approach _ is for proc creation ie:

let my = _ + _ + _  # template(a, b, c: untyped): untyped =

In this case _ needs to be some kind of template :thinking:

thenjip commented 2 years ago

Hello,

It turns out I did try to implement what is said above. Here is the macro. It is called partial application.

At the time I wrote the macro, I was not aware of currying. So putting N placeholders generates a N-ary proc.

I hope it helps.