课程地址: https://www.coursera.org/learn/progfun1/lecture/xuM1M/lecture-2-1-higher-order-functions
2.1 Higher-Order Functions
Functional languages treat functions as first-class values.
A function can be passed as a parameter and returned as a result.
Functions that take other functions as parameters ot that return functions as results are called higher order functions.
Anonymous Functions:
(x1: T1, ..., xn: Tn) => E
{ def f(x1: T1, ..., xn: Tn) = E; f }
2.2 Currying
def sum(f: Int => Int)(a: Int, b: Int): Int ...
type of sum: (Int => Int) => ((Int, Int) => Int)
def mapReduce(f: Int => Int, combine: (Int, Int) => Int, zero: Int)(a: Int, b: Int): Int = { if (a > b) zero else combine(f(a), mapReduce(f, combine, zero)(a + 1, b)) } def product(f: Int => Int)(a: Int, b: Int): Int = mapReduce(f, (x,y) => x*y, 1)(a, b)
2.4 Scala Syntax Summary
Extended Backus-Naur form (EBNF):
| denotes an alternative, [...] an option (0 or 1), {...} a repetition (0 or more).
A type can be:
- A numeric type: Int, Double (and Byte, Short, Char, Long, Float),
- The Boolean type with the values true and false,
- The String type,
- A function type, like Int => Int, (Int, Int) => Int.
An expression can be:
- An identifier such as x, isGoodEnough,
- A literal, like 0, 1.0, "abc",
- A function application, like sqrt(x),
- An operator aplication, like -x, y+x,
- A selection, like math.abs,
- A conditional expression, like if (x < 0) -x else x,
- A block, like { val x = math.abs(y); x * 2 },
- An anonymous function, like x => x + 1.
A definition can be:
- A function definition, like def square(x: Int) = x * x,
- A value definition, like val y = square(2)
A parameter can be:
- A call-by-value parameter, like (x: Int),
- A call-by-name parameter, like (y: => Double).
2.6 More Fun with Rationals
Preconditions:
require( y > 0, "denominator must be positive")
Assertions:
asser( x >= 0)
difference:
- require is used to enforce a precondition on the caller of a function.
- assert is used as to check the code of the function itself.
2.7 Evaluation and Operators
class C(x1, ..., xm){ ... def f(y1, ..., ym) = b ... }
new C(v1, ..., vm).f(w1, ..., wn) is rewritten to:
[w1/y1, ..., wn/yn][v1/x1, ..., vm/xm][new C(v1, ..., vm)/this]b
Example:
new Rational(1, 2).numer
-> [1/x, 2/y][][new Rational(1, 2)/this]x
=1
new Rational(1, 2).less(new Rational(2, 3))
-> [1/x, 2/y][new Rational(2, 3)/that][new Rational(1, 2)/this]
this.numer * that.denom < that.numer * this.denom
= new Rational(1, 2).numer * new Rational(2, 3).denom < new Rational(2, 3).numer * new Rational(1, 2).denom
= 1 * 3 < 2 * 2
= true
class Rational(x: Int, y: Int) { require(y != 0, "denominator must be nonzero") def this(x: Int) = this(x, 1) private def gcd(a: Int, b: Int): Int = if(b == 0) a else gcd(b, a % b) private val g = gcd(x, y) def numer = x / g def denom = y / g def < (that: Rational) = numer * that.denom < denom * that.numer def max(that: Rational) = if(this < that) that else this def + (that: Rational) = new Rational(numer*that.denom+denom*that.numer, denom*that.denom) def unary_- : Rational = new Rational(-numer, denom) def -(that: Rational) = this + (-that) }
The precedence of an operator is determined by its first character.
The following table lists the characters in increasing order of priority precedence:
(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)