在 TypeScript
中,类型系统的一部分是关于如何处理函数参数和返回值的类型的。这就涉及到了 逆变(contravariant) 和 协变(covariant) 的概念。在TypeScript中学习协变性和逆变性可能有些棘手,但是了解它们对于理解类型和子类型是一个很好的补充。
9 篇博文 含有标签「JavaScript」
查看所有标签技巧 | 03 JavaScript 中将 ArrayBuffer 转换为字符串
在 JavaScript 中将 ArrayBuffer 转换为 字符串,可以使用 TextDecoder API。TextDecoder 可从字节序列中解码文本内容,支持多种编码格式。
Functional Programming in JavaScript
Agenda
- What is Functional Programming?
- How Functional Programming Differs From Other Paradigms
- Functional Programming in Javascript
- Advantages and Disadvantages of Functional Style
- Interaction of Functional and Object-Oriented Styles
What is Functional Programming?
- Restricted sense, FP means programming without mutable variables, assignments, loops and other imperative control structures
- Wider sense, FP means focusing on the functions
- Particularly, functions can be values that are produced, consumed, and composed.
Functional Programming Languages
Functions in a FP languages are first-class citizens. This means:
- they can be defined anywhere, including inside other function
- like any other values, they can be passed as parameters to functions and returned as results
- as for other values, there exist a set of operators to compose functions
Some languages
Restricted sense:
- Pure Lisp, XSLT, XPath, XQuery, FP
Wider sense:
- JavaScript
- Lisp, Scheme, Racket, Clojure
- SML, F#
- Haskell (full language)
- Scala
OOP vs FP
OO focuses on the differences in the data, while FP concentrates on consistent data structures.
Object-Oriented
- Data and the operations upon it are tightly coupled
- Objects hide their implementation of operations from other objects via their interfaces
- The central model for abstraction is the data itself
- The central activity is composing new objects and extending existing objects by adding new methods to them
Functional
- Data is only loosely coupled to functions
- Functions hide their implementation, and the language’s abstractions speak to functions and the way they are combined or expressed
- The central model for abstraction is the function, not the data structure. The central activity is writing new functions
Declarative vs Imperative
One main distinguishing characteristics of functional programming languages is that they describe what they want done, and not how to do it. OO, inside its methods, still uses mostly imperative techniques.
Imperative programming is about
- modifying mutable variables
- using assignment
- and control structures such as if-then-else, loops, break, continue, return.
The most common informal way to understand imperative programs is as instruction sequences for a Von Neumann computer
Processor <---- bus ----> Memory
Declarative programming is about
- concentrate on functions
- avoid mutations (mutation can bestroy useful laws)
- have powerful ways to abstract and compose functions
Imperative style
var sumOfSquares = function(list) {
var result = 0;
for (var i = 0; i < list.length; i++) {
result += square(list[i]);
}
return result;
};
console.log(sumOfSquares([2, 3, 5]));
Functional style
var sumOfSquares = pipe(map(square), reduce(add, 0));
console.log(sumOfSquares([2, 3, 5]));
Functional Features in JavaScript
Easily available in Javascript
- First-class functions
- Lambdas/Anonymous Functions with closures
- Compact, even terse, functions
Possible to accomplish in JavaScript
- Mostly stateless processing
- Side-effect-free functions calls
Not available in JavaScript
- Performant recursion through tail call optimization
- Pattern matching (Haskell, Erlang)
- Lazy Evaluation (Miranda, Haskell)
- Homoiconicity (mostly LISP-like languages?)
Shared examples
This calculates the odds of choosing the correct n
numbers out of the p
possibilities.
iterative version
function odds(n, p) {
var acc = 1;
for(var i = 0; i < n; i++) {
acc *= (n - i) / (p - i);
}
return acc;
}
console.log(odds(3, 10)); //=> (3/10) * (2/9) * (1/8) => (1/120) => 0.008333...
Recursive version
// Recursive version
function odds(n, p) {
return (n == 0) ? 1 : (n / p) * odds(n - 1, p - 1);
}
console.log(odds(3, 10)); //=> (3/10) * (2/9) * (1/8) => (1/120) => 0.008333...
- recursive functions are often much more elegant than their iterative cousins.
- Unfortunately, they often don't perform as well. All the overhead of creating stack contexts for function calls tends to add up. But certain kinds of recursive calls can be easily optimized.
tail recursive
var odds = (function(){
var odds1 = function(n, p, acc) {
return (n == 0) ? acc : odds1(n - 1, p - 1, (n / p) * acc);
}
return function(n, p) {
return odds1(n, p, 1)
}
})();
Note that the recursive call in odds1 is the last statement in its branch of the function. If this is true for all recursive calls, then the function is tail-recursive, and the compiler can replace the entire set of nested calls with simple JUMP operations.
Functional Programming in Javascript
With first-class function, closures, and anonymous functions, Javascript allows us to do a great deal of functional programming, even if we don't have things like pattern matching and homoiconicity.
There are some tools built in to modern Javascript environments, and it's straightforward to roll your own.
- Ramda
- Underscore, Lo-Dash