(cljs/run-at (JSVM. :all) "一起实现柯里化")
2017-07-02 09:11
459 查看
前言
习惯了Ramda.js就会潜意识地认为函数均已柯里化,然后就可以随心所欲的用函数生成函数,或者使用compose组合多个函数来生成一个新函数。如下const f = a => b => a + b const g = c => d => c - d const compose = f => g => x => f(g(x)) const add1 = f(1) add1(2) // 返回3 const addThenMinus = compose(g(2), f(1)) addThenMinus(3) // 返回-2
ES6的arrow function让我们轻易写出柯里化的函数(当然使用Ramda.js会更轻松),若换成ES5就蛋痛很多了。而不幸的是cljs采纳和js一样能够接受可变参数的函数特性,这使得其必须抛弃如haskell函数自动柯里化的特性。若用cljs实现上述代码将会如此地丑陋
(defn f [a] (fn [b] (+ a b))) (defn g [c] (fn [d] (- c d))) (def add1 (f 1))
那么要如何才能在cljs中优美地实现柯里化呢?答案是两步走:
实现Ramda.js中
R.curry函数的cljs版
借助curry函数实现macro
实现curry函数
;; 定义 (defn curry [f n & args] (fn [& more] (let [a (vec (concat args more))] (if (> n (count a)) (apply curry (reduce conj [f n] a)) (apply f (take n a)))))) ;; 使用 (defn f [a b] (+ a b)) (def fc (curry f 2)) (def add1 (fc 1))
实现defnc宏
;; 定义 (defmacro defnc [name args & body] {:pre [(not-any? #{\&} args)]} (let [n (count args)] `(def ~name (curry (fn ~args ~@body) ~n)))) ;; 使用 (defnc f [a b] (+ a b)) (def add1 (f 1))
总结
cljs中的macro让我们可以灵活扩展语言特性,真是越用越酸爽啊!尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/7103601.html ^_^肥仔John
相关文章推荐
- (cljs/run-at (JSVM. :all) "Metadata就这样哦")
- (cljs/run-at (JSVM. :all) "细说函数")
- (cljs/run-at (JSVM. :all) "一次说白DataType、Record和Protocol")
- (cljs/run-at (JSVM. :browser) "搭建刚好可用的开发环境!")
- (cljs/run-at (JSVM. :browser) "命名空间就这么简单")
- (cljs/run-at (JSVM. :browser) "简单类型可不简单啊~")
- (cljs/run-at (->JSVM :browser) "语言基础")
- js实现"replaceAll"
- js实现"replaceAll"效果
- JS:"全选"功能实现(checkbox)
- JSCode all of Brower 全局屏蔽网页右键功能 具体实现
- js中的replaceAll的实现
- JS中实现replaceAll的方法
- JSCode all of Brower 全局屏蔽网页右键功能 具体实现
- C# runat="server"
- js 实现 <input type="file" /> 文件上传
- JS正则表达式怎样实现Java中String.replaceAll的效果
- 如何用原生态的JS实现类似JQuery的$("#id"),$(".selector")等功能
- js实现给<a href=""> href赋值
- 用js实现多个效果一起变化