Open scozv opened 10 years ago
:+1: 速度好快啊
抱歉,今天还没有开始翻译第二章
2.1和2.2完成了70%,还有地方需要完善
2.1和2.2的翻译完成了。第二章的README.md
完成了50%。
几个问题:
aliasFor
的代码那里,为什么是E=()=>{}
,而非E={}
?aliasFor('reduce').is('reduceLeft).is(foldl)
, 这里的reduce, foldl是E中的方法,还是特指Array里面的?这个地方没有指明reduce是Array里面了,这句话能成功吗?是不是应该写成:
aliasFor('Array.reduce').is('Array.reduceLeft).is(Array.foldl)
另外,我看到你已经开始merge第一章了。我想问问,你对request的merge和我之后的push会有冲突吗?
翻的好快啊,要是阅读上有些地方不好理解,都可以提,我思路可能比较飘😅 On Jul 22, 2014 10:59 PM, "Scott" notifications@github.com wrote:
2.1和2.2的翻译完成了。第二章的README.md完成了50%。
几个问题: high-order_function.md
- “如果我们要逆序的排序”,将“逆序”修改成降序(descending),是不是含义更加明确
- 在 “function as return value”那一小节,我使用了member(成员)一词来指你中文的“函数内部的一些方法”
有个问题(和翻译无关),还是这一节,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 .
不会有冲突,我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 .
跟翻译无关的一个讨论
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.
在这里对于绑 alias确实没什么区别,因为 Function 也是 Object,但是function 能干更多的事情,但就这个例子确实是效果一样的。
第二章的README,2.1,2.2都已经全部翻译好了。
README.md这一篇有几个问题,我在source code的相应地方加了备注。(删除这些备注,所有的英文都是完整的翻译。)你merge的时候看看。
2.3 currying已经翻译完毕。Haskell我不是很熟悉,可能翻译的不够完善。
对于Haskell中:max :: Ord a => a -> a -> a
,这样的结果是不是分成两部分:
* =>
大箭头左边的,是参数类型x -> x ...
大箭头右边的这些小箭头才是函数签名相当于:
a: Ord -> (a -> a)
也就是说,Haskell的大箭头=>
不够成Lambda表达式的一部分
=>左边是类型定义,说明 a 表示 Ord 类型, 右边表示接受一个 a 类型 再接受一个 a 类型,返回一个 a 类型。
2.4(compose_function.md)翻译完毕,有几个翻译问题,还有一些讨论。有点儿长,你抽空看看,谢谢。
如下这句话,是不是有typo错误,后半段没看懂
这种方式怎么看都不是函数式, 而是以对象为中心, 或者函数式一些, 组合 This code doesn't look like functional, it likes object-oriented, 或者函数式一些, 组合
如下翻译,我适当的调整一下句子的结构,你看合不合适:
区别大了这, 看见
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 intoE.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
.
你说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()
这种结构的语句,很具有声明式的特点啊?
关于延后执行,如果说
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)
,它们是不是更体现函数编程的思想呢?
关于你文中的两个例子:
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)
有什么区别?
_(list).filter(selectSomething)
其实返回的是一个封装好 context 的 underscore 对象,其实就是中间对象或者容器。看到下一章 monad 的话其实就可以把他理解为 monad,但是本章是讲函数组合,所以我不认为一个返回对象的方法是函数,因此这些方法的串联也不是函数组合。真正的函数组合永远是 a(b(c(d)))这种形式的,当然更可读的方式是compose(a,b,c)(d)
(所以lisp 这么多括号:scream:). 我不是很懂 声明式 是什么
- 推后是顺带获得的好处,但目的不是推后,真正的用意是配置好的这个函数可以组合到其他函数中,具体就是第三问有什么不一样,当然也是响应2.3为什么要柯里化。 这里的 scala 我不是很懂但是类似于 haskell 的 list,我都理解为 monad 活着 functor。monad跟函数组合也没有关系,只是应用一些函数到一个容器里而已,它并不会返回函数的组合。
- 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/
chapter 2, Higher-order function
I'll start to translate 2.1 and 2.2, is that OK?