2017-05-28 21:10:53 +00:00
|
|
|
|
// define function
|
2020-10-15 17:29:27 +00:00
|
|
|
|
// GOOD
|
2017-05-28 21:10:53 +00:00
|
|
|
|
def f(x: Int) = { x*x }
|
2020-10-15 17:29:27 +00:00
|
|
|
|
// BAD
|
2017-05-28 21:10:53 +00:00
|
|
|
|
// hidden error: without = it’s a Unit-returning procedure; causes havoc
|
|
|
|
|
def f(x: Int) { x*x }
|
|
|
|
|
|
|
|
|
|
// define function
|
|
|
|
|
// GOOD
|
|
|
|
|
def f(x: Any) = println(x)
|
|
|
|
|
// BAD
|
|
|
|
|
// syntax error: need types for every arg.
|
|
|
|
|
def f(x) = println(x)
|
|
|
|
|
|
|
|
|
|
// type alias
|
|
|
|
|
type R = Double
|
|
|
|
|
|
|
|
|
|
// call-by-value
|
|
|
|
|
def f(x: R)
|
|
|
|
|
// call-by-name (lazy parameters)
|
|
|
|
|
def f(x: => R)
|
|
|
|
|
|
|
|
|
|
// anonymous function
|
2020-10-15 17:29:27 +00:00
|
|
|
|
(x:R) => x*x
|
2017-05-28 21:10:53 +00:00
|
|
|
|
|
|
|
|
|
// anonymous function: underscore is positionally matched arg.
|
|
|
|
|
(1 to 5).map(_*2) // vs.
|
|
|
|
|
(1 to 5).reduceLeft( _+_ )
|
|
|
|
|
|
|
|
|
|
// anonymous function: to use an arg twice, have to name it.
|
|
|
|
|
(1 to 5).map( x => x*x )
|
|
|
|
|
|
|
|
|
|
// anonymous function: bound infix method. Use 2*_ for sanity’s sake instead.
|
2020-10-15 17:29:27 +00:00
|
|
|
|
// GOOD
|
2017-05-28 21:10:53 +00:00
|
|
|
|
(1 to 5).map(2*)
|
|
|
|
|
// BAD
|
|
|
|
|
(1 to 5).map(*2)
|
|
|
|
|
|
|
|
|
|
// anonymous function: block style returns last expression.
|
|
|
|
|
(1 to 5).map { x => val y=x*2; println(y); y }
|
|
|
|
|
|
|
|
|
|
// anonymous functions: pipeline style. (or parens too).
|
|
|
|
|
(1 to 5) filter {_%2 == 0} map {_*2}
|
|
|
|
|
|
|
|
|
|
// anonymous functions: to pass in multiple blocks, need outer parens.
|
|
|
|
|
def compose(g:R=>R, h:R=>R) = (x:R) => g(h(x))
|
|
|
|
|
val f = compose({_*2}, {_-1})
|
|
|
|
|
|
|
|
|
|
// currying, obvious syntax.
|
|
|
|
|
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd
|
|
|
|
|
|
|
|
|
|
// currying, obvious syntax
|
|
|
|
|
def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd
|
|
|
|
|
|
|
|
|
|
// currying, sugar syntax. but then:
|
|
|
|
|
def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd
|
|
|
|
|
|
|
|
|
|
// need trailing underscore to get the partial, only for the sugar version.
|
|
|
|
|
val normer = zscore(7, 0.4) _
|
|
|
|
|
|
2018-07-13 15:07:30 +00:00
|
|
|
|
// using curried parameters with a partially applied function
|
|
|
|
|
// can be called as "add(1)(2)" to return "3"
|
|
|
|
|
def add(x: Int) = x + (_: Int)
|
|
|
|
|
|
2017-05-28 21:10:53 +00:00
|
|
|
|
// generic type.
|
|
|
|
|
def mapmake[T](g:T=>T)(seq: List[T]) = seq.map(g)
|
|
|
|
|
|
|
|
|
|
// infix sugar.
|
|
|
|
|
5.+(3); 5 + 3
|
|
|
|
|
(1 to 5) map (_*2)
|
|
|
|
|
|
|
|
|
|
// varargs
|
|
|
|
|
def sum(args: Int*) = args.reduceLeft(_+_)
|
|
|
|
|
|
2018-07-13 15:07:30 +00:00
|
|
|
|
// default parameters
|
|
|
|
|
def countTo(i: Int = 5) = 1 to i
|
|
|
|
|
countTo(3) = Range(1,2,3)
|
|
|
|
|
countTo() = Range(1,2,3,4,5)
|
2017-05-28 21:10:53 +00:00
|
|
|
|
|
2018-07-13 15:07:30 +00:00
|
|
|
|
// higher order functions
|
|
|
|
|
// as long as a function returns the correct type, it can be used as a parameter in another function
|
|
|
|
|
def sum(a: Int, b: Int): Int = a + b
|
|
|
|
|
def double(x: Int): Int = x * 2
|
|
|
|
|
double(sum(1, 1)) // returns 4
|