首页 > 代码库 > 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 一切皆为函数 第二周视频笔记