ikigai-go / compiler

Ikigai compiler
MIT License
0 stars 0 forks source link

Tuple syntax vs multi arguments #5

Open alfonsogarciacaro opened 5 years ago

alfonsogarciacaro commented 5 years ago

This was briefly discussed in #2, but it deserves a bit more attention. As we've decided we won't have implicit currying, if we use () for tuples, they could be confused with multi-arguments. Is this clear enough?

// If we have one single argument, parens can be optional
let square x = x * 2

// These are two arguments, but look like a tuple
let add (x, y) = x + y

// Two tuple arguments destructured
let addPoints ((x1,y1), (x2,y2)) = (x1 + x2, y1 + y2)

let test() =
   let p = (2, 3)
   addPoints(p, (add(3,4), 5))

Same example if we use [] for tuples as Typescript does:

let addPoints ([x1,y1], [x2,y2]) = [x1 + x2, y1 + y2]

let test() =
   let p = [2, 3]
   addPoints(p, [add(3,4), 5])

Any preference?

MangelMaxime commented 5 years ago

Could you please explain to me what implicit currying is? So I can better understand the situation :)

alfonsogarciacaro commented 5 years ago

In ML languages like F# functions are supposed to accept only one argument so let add x y = .. is just sugar syntax for let add = fun x -> fun y -> ... and add 4 5 is actually ((add 4) 5). F# and Fable some magic to convert most of these functions to multi-argument in compiled code, but this forces the semantics and creates some edge cases when interacting with native code.

In JS you can have function with multiple arguments and also curried functions if you make it explicit (const f = x => y => x + y). I would like Ikigai to do the same to make interop with JS easier.

MangelMaxime commented 5 years ago

Ok and then is there something preventing us to convert:

let add x y = ...

to

function add(x, y) {  ...  }

And if the function got a tuple it would be:

let funWithTuple (x : number) (vx: number, vy : number) = ...

to

function funWithTuple (x, arg1) {
    const vx = arg1.Value1; // Code for the demo only
    const vy = arg1.Value2; // Code for the demo only
}

And this case let add (x, y) = x + y would not be 2 arguments but a single tuple.

I never liked the let add (x, y) syntax :)

alfonsogarciacaro commented 5 years ago

Yes, there's a problem :) How do you apply multiple arguments then?

let add x y = x + y

let curriedAdd x = fun y -> x + y

let test() =
   let res1 = add 4 5 // This translates to add(4,5)?
   let res2 = curriedAdd 4 5 // How do we apply functions explicitly curried?
   let res3 = add 4 // Do we allow partial application for non-curried functions? Is this a compiler error?
   ()

Fable already does something like you propose. It automatically uncurries fun x y -> x + y, but this creates conflicts when we need to interact with JS methods that accept curried functions. For example, I had to change the signature unit -> unit -> unit to unit -> (unit -> unit) option in React useEffect hook to prevent auto-uncurrying.

MangelMaxime commented 5 years ago

How do you apply multiple arguments then?

Joker? :)

Ok, perhaps we can't. Then I vote to use () both for tuple and arguments depending on the context. Because [] is already used for list and array. So adding tuple support to the same syntax start to make it really hard to grasp on the first look IHMO.