Functional programming
-
Avoid mutation
-
Functions as values
-
Laziness
-
First-class functions: can using functions wherever we use values.
Higher-order functions: accepts functions as arguments and return functions as results. -
Function closure: Functions can use bindings from outsides the function definition (in scope where function is defined)
--code
--environment -
lexical scope: using environment where function is defined.
Dynamic scope: using environment where function is called.
Why lexical scope ?
- Function meaning does not depend on variable names used.
- Function can be type-checked and reasoned where defined.
- Closures can easily store the data they need.
Currying
- Every function just takes one argument.
- Caller and callee must use the same technique (currying).
- A famous example:
fun foldl (f, acc, xs) =
case xs of
null => acc
| x::xs=> foldl (f, f(acc, x), xs
)
fun foldr (f, acc, xs) =
case xs of
null => acc
| x::xs=> f (foldr (f, acc, xs
), x)
Value restriction
When you get a warning/error, you should just turn var-binding back into fun-binding.
Continuation
Reference
ref e
to create a reference with initial contents e
e1 := e2
to update contents
!e
to retrieve contents
val x = ref []
value restriction
call-back
网友评论