jcouyang / functional-javascript

DEPRECATED: moved to https://github.com/jcouyang/clojure-flavored-javascript
39 stars 7 forks source link

chapter 2 revise and :uk: #5

Open scozv opened 10 years ago

scozv commented 10 years ago

chapter 2, Higher-order function

I'll start to translate 2.1 and 2.2, is that OK?

jcouyang commented 10 years ago

:+1: 速度好快啊

scozv commented 10 years ago

抱歉,今天还没有开始翻译第二章

scozv commented 10 years ago

2.1和2.2完成了70%,还有地方需要完善

scozv commented 10 years ago

2.1和2.2的翻译完成了。第二章的README.md完成了50%。

几个问题:

high-order_function.md

  1. “如果我们要逆序的排序”,将“逆序”修改成降序(descending),是不是含义更加明确
  2. 在 “function as return value”那一小节,我使用了member(成员)一词来指你中文的“函数内部的一些方法”
  3. 有个问题(和翻译无关),还是这一节,aliasFor 的代码那里,为什么是E=()=>{},而非E={}
  4. aliasFor('reduce').is('reduceLeft).is(foldl), 这里的reduce, foldl是E中的方法,还是特指Array里面的?这个地方没有指明reduce是Array里面了,这句话能成功吗?是不是应该写成:

    aliasFor('Array.reduce').is('Array.reduceLeft).is(Array.foldl)

scozv commented 10 years ago

另外,我看到你已经开始merge第一章了。我想问问,你对request的merge和我之后的push会有冲突吗?

jcouyang commented 10 years ago
  1. 可以的
  2. 对象内部的方法应该是method,单独的函数是function
  3. 前者是创建了一个对象,后者是声明一个函数
  4. 这个应该是typo,应该都有引号

翻的好快啊,要是阅读上有些地方不好理解,都可以提,我思路可能比较飘😅 On Jul 22, 2014 10:59 PM, "Scott" notifications@github.com wrote:

2.1和2.2的翻译完成了。第二章的README.md完成了50%。

几个问题: high-order_function.md

  1. “如果我们要逆序的排序”,将“逆序”修改成降序(descending),是不是含义更加明确
  2. 在 “function as return value”那一小节,我使用了member(成员)一词来指你中文的“函数内部的一些方法”
  3. 有个问题(和翻译无关),还是这一节,aliasFor 的代码哪里,为什么是E=()=>{},而非E={}? 4.

    aliasFor('reduce').is('reduceLeft).is(foldl), 这里的reduce, foldl是E中的方法,还是特指Array里面的?这个地方没有指明reduce是Array里面了,这句话能成功吗?是不是应该写成:

    aliasFor('Array.reduce').is('Array.reduceLeft).is(Array.foldl)

— Reply to this email directly or view it on GitHub https://github.com/jcouyang/functional-javascript/issues/5#issuecomment-49750665 .

jcouyang commented 10 years ago

不会有冲突,我merge后还修改了一些,可能你pull request前要pull下代码 On Jul 22, 2014 11:04 PM, "Scott" notifications@github.com wrote:

另外,我看到你已经开始merge第一章了。我想问问,你对request的merge和我之后的push会有冲突吗?

— Reply to this email directly or view it on GitHub https://github.com/jcouyang/functional-javascript/issues/5#issuecomment-49751471 .

scozv commented 10 years ago
  1. 跟翻译无关的一个讨论

    aliasFor 的代码那里,为什么是E=()=>{},而非E={}? why using E=()=>{} instead of E={} in source code of aliasFor?

    这个问题,写法我理解,但是我不明白,为什么此处要用函数,而非一个对象。如果用对象,相当于一个hashtable,E[newName] = E[oldName];这句话似乎也能用——用两个不同的key,指向同一个value,也能起到alias的效果吧。 using E={} as a hashtable seems that we can still give alias to a function.

  2. 我已经从你的主库更新代码了
jcouyang commented 10 years ago

在这里对于绑 alias确实没什么区别,因为 Function 也是 Object,但是function 能干更多的事情,但就这个例子确实是效果一样的。

scozv commented 10 years ago

第二章的README,2.1,2.2都已经全部翻译好了。

README.md这一篇有几个问题,我在source code的相应地方加了备注。(删除这些备注,所有的英文都是完整的翻译。)你merge的时候看看。

scozv commented 10 years ago

2.3 currying已经翻译完毕。Haskell我不是很熟悉,可能翻译的不够完善。

对于Haskell中:max :: Ord a => a -> a -> a,这样的结果是不是分成两部分:

相当于: a: Ord -> (a -> a)

也就是说,Haskell的大箭头=>不够成Lambda表达式的一部分

jcouyang commented 10 years ago

=>左边是类型定义,说明 a 表示 Ord 类型, 右边表示接受一个 a 类型 再接受一个 a 类型,返回一个 a 类型。

scozv commented 10 years ago

2.4(compose_function.md)翻译完毕,有几个翻译问题,还有一些讨论。有点儿长,你抽空看看,谢谢。

翻译问题:

  1. 如下这句话,是不是有typo错误,后半段没看懂

    这种方式怎么看都不是函数式, 而是以对象为中心, 或者函数式一些, 组合 This code doesn't look like functional, it likes object-oriented, 或者函数式一些, 组合

  2. 如下翻译,我适当的调整一下句子的结构,你看合不合适:

    区别大了这, 看见tasks 是最后当参数传给E.sort(E.filter(task=>task.completed===true))的吗? 而不是写死在filter 的参数中. 这意味着在接到需要处理的数据前, 我已经组合好一个新的函数在等待数据, 而不是把数据混杂在中间, 或是保持在一个中间对象中.

    However, the big difference here is, in E.compose, tasks is the final parameter passed into E.sort(E.filter(task=>task.completed===true)), whereas, in _.sortBy, tasks is a binded parameter of _.filter. That means, E.compose has already created a new function before accepting the parameter, instead of mixing data (passed as parameter) during composition, or keeping data in a middle object like _.filter.

讨论:

  1. 你说underscore中,这样的代码

    _(tasks).chain().filter( task => ...).sortBy( task => ...).value(); 这种方式怎么看都不是函数式, 而是以对象为中心, 或者函数式一些, 组合

    我觉得这样的写法非常符合声明式的要求啊,声明式就是函数编程的重要特点啊。反而

    E.compose(E.sortBy(task=>task.id), E.filter(task=>task.completed===true))(tasks)

    我还觉得不够“声明”,我们的需求就是找出符合要求的元素,然后排序,那么, lst.where().orderBy() 这种结构的语句,很具有声明式的特点啊?

  2. 关于延后执行,如果说

    E.compose(E.sortBy(task=>task.id), E.filter(task=>task.completed===true))(tasks)

    是先组合出一个函数g(lst) = sortBy(filter(lst)),也就是tasks最后才会被传进组合函数里面。

    那么Scala里面的view,岂不是也能达到这样的效果:

    lst.view.filter(x=>...).sortBy(x=>...)

    另外,在C#中的LINQ,也具有延后执行的效果:

    IEnumerable.Where(x=>...).OrderBy(x=>...)

    也就是说,Scala和LINQ自动组合了这两个函数(filter和sort),也都是在最后才把tasks传进组合函数中。那么相较于E.compose(sortBy, filter)(tasks),它们是不是更体现函数编程的思想呢?

  3. 关于你文中的两个例子:

    E.compose(E.sortBy(task=>task.id), E.filter(task=>task.completed===true))(tasks)

    var completedAndSorted = E.compose(E.sortBy(task=>task.id), E.filter(task=>task.completed===true))
    E.map(completedAndSorted)(groupedTasks)

    我想请问一下第二个例子和completedAndSorted(groupedTasks)有什么区别?

jcouyang commented 10 years ago
  1. underscore 的这种写法之所以不是函数式,是因为每次比如_(list).filter(selectSomething)其实返回的是一个封装好 context 的 underscore 对象,其实就是中间对象或者容器。看到下一章 monad 的话其实就可以把他理解为 monad,但是本章是讲函数组合,所以我不认为一个返回对象的方法是函数,因此这些方法的串联也不是函数组合。真正的函数组合永远是 a(b(c(d)))这种形式的,当然更可读的方式是compose(a,b,c)(d)(所以lisp 这么多括号:scream:).

我不是很懂 声明式 是什么

  1. 推后是顺带获得的好处,但目的不是推后,真正的用意是配置好的这个函数可以组合到其他函数中,具体就是第三问有什么不一样,当然也是响应2.3为什么要柯里化。 这里的 scala 我不是很懂但是类似于 haskell 的 list,我都理解为 monad 活着 functor。monad跟函数组合也没有关系,只是应用一些函数到一个容器里而已,它并不会返回函数的组合。
  2. groupedTasks 是个数组的数组(文中的“包含几组 tasks的列表 groupedTasks”) 也就是[[task1,task2], [task1,task2]] completedAndSorted只能操作completedAndSorted([task1,task2])而不是completedAndSorted([[task1,task2], [task1,task2]])

map 可以将completedAndSorted应用到 groupedTasks 中的 tasks 数组[task1,task2], 这里的意思是, 换 underscore 是根本做不到这样灵活的组合的。如果 underscore 要实现只能这样

_(groupedTasks).map((tasks)=>{
  return _(tasks)
    .chain()
    .filter( task => task.completed===true)
    .sortBy( task => task.id).value();
})

中间任何部分都拆不出来组合。


其实这节就是为什么要柯里化的加强版,因为柯里化就是为了函数组合,underscore 刚好做反了,没有柯里化,而且先吃目标对象,这样使得根本上就没法柯里化了。函数式的思想很简单,就是拿各种函数组装好一个函数,然后拿数据来吃,吐出结果,因为这完全就是数学公式的顺序,你先列出公式,然后喂数据才出结果。underscore 刚好是反得,先吃了数据,再应用各种方法,跟 jquery 一样他们是对容器操作而不是组合。 http://hughfdjackson.com/javascript/why-curry-helps/ http://fr.umio.us/why-ramda/