lantiga / ki

lisp + mori, sweet.js
ki-lang.org
MIT License
478 stars 28 forks source link

dot notation does not work in partial application, function composition #27

Open sirpengi opened 9 years ago

sirpengi commented 9 years ago

From the docs, you can chain dot notation in the following way:

ki require core
var r1 = ki (threadf "lol r1" (.toUpperCase) (.trim));
console.log(r1); // "LOL R1"

However, sometimes you want to move this behavior into a function for reuse. Honestly I feel this should work, but it doesn't compile:

var r2 = ki (comp (.toUpperCase) (.trim));
// Unexpected token .

(Neither does (comp .toUpperCase .trim), but that fails with a runtime error)

If you want the same behavior composed, or partially applied, you have to do the following:

var toUpper = function(x){ return x.toUpperCase(); };
var toTrim = function(x){ return x.trim(); };
var r3 = ki (curry pipeline toUpper toTrim);
console.log(r3("lol r3")); // "LOL R3"
var r4 = ki (comp toUpper toTrim);
console.log(r4("lol r4")); // "LOL R4"

On a related note, threadf also doesn't work with curry. The following compiles but results in a runtime error:

var r5 = ki (curry threadf toUpper toTrim);
console.log(r5("lol r5"));
// ReferenceError: threadf is not defined

It kind of makes sense if you think of threadf as a special form, but it doesn't appear dot notation should be. Dot notation works as an argument to threadf, but not in any other situations?

lantiga commented 9 years ago

Hi. Currently dot notation is turned immediately into property/method access on the js object (Clojure behaves the same way). After all, .toUpperCase is not a function, obj.toUpperCase is. Your idea on lifting this limitation is interesting though.

Currently, to do what you need in a concise way you could use chain:

var r5 = ki (fn [x] (chain x (toUpperCase) (trim)))

which saves you the extra functions.

As to the curry not working with threadf, you're right, threadf is not a function and it only works when invoked as a special form.