首页 > 代码库 > Scala 一切皆为函数 第二周视频笔记

Scala 一切皆为函数 第二周视频笔记

Lecture 2.2 Curring

Motivation    


回顾 sum(f, a,b) 中如何使用不同的f来实现sum,铺垫匿名函数概念

 


Fuctions returning Functions   


函数1可以是另外一个函数2的返回,


这里面蕴含一个重要思想:


在函数1的体内使用函数2时,函数2本身作为函数1的参数的这个效果在函数2的代码不再体现,


即函数2比函数1少去了一个自身的参数,而省去的根本原因在于函数2还可以调用函数2本身


也就是之前为什么需要学习递归思想的原因




Stepwise Applications


正式引出匿名函数概念,通过sum的例子说明匿名函数的用处和原因, 同时开始逐步分析如何简化代码


sumCube, sumFactorials,sumInts用sum(f, a, b)来代替,其中f的实现可以直接在调用时隐式传入


比如sum(x=>x, a, b)






Consecutive stepwise Applications


逐步递进分析,sum(f, a, b) 其实就是 sum(f)(a,b) 这里说明了将sum(f) 看成一个函数 (a,b)看成参数和将sum看成函数 (f,a,b) 看成参数是一样的,说明结合律在函数编程中的该如何理解, 如果sum和f是可以结合的话那么 sum(f, a, b) = (sum(f)) ( a, b) 说明 sum和f结合后再调用(a, b) 参数 和 sum 调用 f 和 (a, b) 结合后的结果作为参数的效果是一样的。 (a+b) + c = a + (b + c)。 有了结合律,为引出下面的多参数函数变换做铺垫




Multiple Parameter List


sum(f,a,b) = sum(f)(a,b) 这里发现函数参数从3个到两个演进的规律,参数在不同上下文(代码块)中引用考虑不同的结合




Expansion of Multiple Parameter List


衍生出公式 def f(args1)(args2)…(argsn)=E


def f(args1)(args2)…(argsn-1) = {def g(argsn) = E; g}


这里需要理解一点,当最后的参数只在g函数调用时,增加一个参数所作用的代码块只在g上,参数argsn对f函数块无作用,只对g代码块作用。函数通过这样的方式扩展新参数


curing可以理解成叠纸,函数是可折叠的




如何将增加的参数柯里化到抽象的函数中,通过一个mapreduce编程例子说明






Lecture  2.3


Finding the fix point of a function


找到函数的固定点  x = f(x) = f(f(x)) = f(f(f(x)))…




Programmic Solution


由以上函数推断出程序解决算法,大概算法意图:当f(x)算到的值非常接近,平方误差小于 0.0001 时结束猜测, 存在一个初始猜测值






Return to Square Roots


举例到平方根的计算方法(牛顿计算法)


def fixedPoint(f: Double => Double)(firstGuess: Double) = {


def iterate(guess: Double): Double = {


val next = f(guess)


println(next)


if (isCloseEnough(guess, next)) next


else iterate(next)


}


iterate(firstGuess)


}




这里关注这个f的实现 y => x/y 的方法进行猜测的数一直在1和2之间转换,无法结束循环,改变函数为 y =>  (y + x/y)/2






Functions as return values


结合上集functions as return functions思考,如何将公式作为参数传入到平方根计算函数中,


def sqrt(x: Double) = fixedPoint(y => (y + x / y) / 2)(1.0)




y => (y+x/y)/2 是否可以抽象为一个有名字的函数呢?可以这样表达,这里的函数作为一个值来看待f(x) 等同于y 等同于(x/y)


def averageDamp(f: Double => Double)(x: Double) = (x + f(x)) / 2




最后平方根计算的表达可以用以下函数,注意这里在averageDamp函数的函数参数中用到了sqrt中的参数x


def sqrt(x: Double) = fixedPoint(averageDamp(y => x/y))(1.0)




可以通过反推法推出牛顿平方根的计算过程


总结


如何通过函数式设计分解,抽象问题,抽象是程序员一直要思考的问题,任何时候都要寻找可以抽象的部分,但是把握抽象的度也非常重要,要不断学习才能真正掌握如何合适的利用抽象 






Lecture 2.4 Scala Syntax Summary


Scala 基本句法总述,记忆性资料,略过




Lecture 2.5  Rational Numbers


通过有理数对象引出有理数加减乘除进行计算时对数据行为(函数)进行抽象的过程,学过Java或面向对象思想和数据结构的理解这个相对容易,不做详细解释






Lecture 2.5 More Fun with Rational Numbers


有基本的有理数例子,引出抽象数据类型概念(Data Type Abstraction)


提出有理数运算时最大公约数问题,引出抽象数据类型进行封装的思想,如何封装最大公约数这个运算? private method gcd ,还是递归


有理数运算外部看不见公约数运算过程




通过有理数运算的例子举例说明以下概念:  自我引用,先决条件,断言,构造器,和从构造器的概念




Lecture 2.6 Evaluation and Operators (运算和运算符)


类如何替换? - 类就是函数,计算实例的值就是应用构造函数来计算,记住scala里面函数就是值。


通过这种方法就可以计算一个表达式的值, 重要一点,视频和课件中的 "/" 符号理解成替换的意思   a/ b 的意思是 用a替换 b


接下来介绍运算符的几个新概念


运算符: 运算符可以看做中缀 a  operator b  等同于 a.b  或者 a.b()


运算符可以是一种标识符,更为宽松的标识符:标识符可以是变量名称,函数名称,还有运算符。


 Scala里面的标识符比Java更为宽松,这就是说Scala这门语言是可扩展的。 记住这一点,将来会认识到这个特性强大之处,这将Scala语言提升到一个新的档次的关键点。


后面举例说明有理数如何将函数转变为更加容易理解的运算符 less(<) add(+)   sub(-)  mul(*) , 其中特意说了下 neg(-) 运算符相同,意义不同怎么办? 视频里面有解释,使用unary_前缀


Scala中的特殊符号冒号和运算符定义之间必须增加空格




运算符优先级顺序,基本等同Java的约定  需要注意的是(all letters) 也可能是运算符,并且它的优先级是最低的


接下来通过好多实例说明运算符优先级顺序问题,大多等同于Java 


本文出自 “刀客” 博客,请务必保留此出处http://kris21.blog.51cto.com/9243389/1596088

Scala 一切皆为函数 第二周视频笔记