admin管理员组

文章数量:1593946

react 编程式路由

救援的功能编程? (Functional Programming to the Rescue?)

After establishing my base camp, in the previous part of the series, I need to choose my route to the summit, the one to depart from reactive programming complexity. Functional programming is surely the right path, the one everybody talks about. Why is that? Part 1/7 Why is Reactive Programming so Complicated? Part 2/7 Functional Programming to the Rescue? Part 3/7 Why is Functional Programming so Controversial? Part 4/7 Could Functional Reactive Programming be the Grail? Part 5/7 How did Functional Reactive Programming Originated? Part 6/7 Where is Functional Reactive Programming Now? Part 7/7 Which Functional Reactive Programming is the Grail? Disclaimer: this part in the series is large. I hope it will be large enough to convince the ignorant, the doubter, the unbeliever, the skeptic and the unfaithful! Hard work ahead… Disclaimer: the term “functional” contains the word “function” and I suppose everybody is familiar with functions in the standard programming sense but functional programming goes far beyond programming with functions. This article describes the most commonly mentioned characteristics of functional programming…

在建立我的大本营之后,在本系列的前一部分中,我需要选择到达顶峰的路线,这是摆脱被动编程复杂性的路线。 每个人都在谈论函数式编程肯定是正确的道路。 这是为什么? 第1/7部分为什么React式编程如此复杂? 第2/7部分要进行抢救的功能编程? 第3/7部分为什么函数式编程这么有争议? 第4/7部分功能React式编程会成为圣杯吗? 第5/7部分功能React式编程是如何产生的? 第6/7部分现在功能响应式编程在哪里? 第7/7部分哪些功能React式编程是圣杯? 免责声明:系列中的这一部分很大。 我希望它的规模足以说服无知,怀疑者,不信者,怀疑者和不忠者! 艰苦的工作……免责声明:“功能”一词包含“功能”一词,我想每个人都熟悉标准编程意义上的功能,但功能编程远远超出了使用功能编程的范围。 本文介绍了函数式编程中最常提及的特征。

1.纯功能 (1. Pure functions)

In the functional programming world you hear a lot the expression “pure function” which means “function” in the mathematical sense by opposition to “function” in the standard programming sense. A tacky synonym of “pure function” is “referential transparency”.

在函数式编程世界中,您会听到很多“ 纯函数 ”的表述,在数学意义上意味着“函数”,而在标准编程意义上与“函数”相反。 “纯功能”的俗气同义词是“ 参照透明性 ”。

1.1。 参照透明性意味着没有副作用 (1.1. Referential transparency means no side-effect)

JavaScript impure function example:

JavaScript不纯函数示例:

function increment(){
count++; // side-effect
}
increment();

JavaScript pure function example:

JavaScript纯函数示例:

var count = 0;
function increment(count){
return count + 1;
}
var incrementedCount = increment(counter);

1.2。 参照透明意味着确定性 (1.2. Referential transparency means determinism)

The result of a function only depends on the function argument (the so called “context-independence”).

函数的结果仅取决于函数参数(所谓的“ 上下文无关 ”)。

1.3。 参照透明性意味着纯函数调用可以用其缓存的值替换 (1.3. Referential transparency means that a pure function call may be replaced by its cached value)

The so-called “memoization” optimization.

所谓的“ 记忆 ”优化。

1.4。 可以简单地删除对不返回任何值的纯函数的调用 (1.4. A call to a pure function that does not return any value may simply be removed)

Note that this does not really applies to JavaScript since a function always returns a value which by default is of type “undefined”. Should I care or should I not? Many bugs comes from side-effects getting out of hand. These bugs are generally difficult to pin-point.

请注意,这实际上不适用于JavaScript,因为函数始终返回默认情况下为“未定义”类型的值。 我应该关心还是不应该? 许多错误来自副作用的失控。 这些错误通常很难查明。

You want to avoid wasting your time and tearing your hair out on debugging these (unless your are a true masochist of course who you totally have the right to be, of course). Context-independence simplifies unit-testing. No mock, no context initialization, no nothing. You only need to provide the arguments to the function to test and check its result (unless you are a true masochist of course who does not do unit-test, of course).

您要避免浪费时间并在调试这些代码时费力 (当然,除非您是真正的受虐狂 ,否则您完全有权)。 上下文无关性简化了单元测试。 没有模拟,没有上下文初始化,什么也没有 。 您只需要提供该函数的参数来测试和检查其结果(当然,除非您是真正的受虐狂,但不进行单元测试)。

2.担任头等公民 (2. Function as first-class citizens)

2.1。 您可以将函数作为参数传递给另一个函数(称为“高阶”函数) (2.1. You can pass functions as arguments to another function (called a “higher-order” function))

JavaScript callback example:

JavaScript回调示例:

function formatTitle(text){ // callback function
return text.toUpperCase();
}
function generateTitle(words, format){ // higher-order function
return format(words.join(" "));
}
var title = generateTitle(["Simple", "Unanimous", "Functional", "Reactive", "Programming"], formatTitle);

2.2。 您可以将函数作为函数的结果返回(也称为“高阶”函数) (2.2. You can return a function as the result of a function (also called a “higher-order” function))

JavaScript curried function example (a curried function is a function with a single argument which is handy for function composition):

JavaScript curried函数示例( curried函数是具有单个参数的函数,对于函数组合非常有用):

function sum(a, b){ // function taking two arguments
return a + b;
}
// curry (defined elsewhere) is a higher-order function
// returning a function
// increment is a function taking a
// single argument (curried function)
var increment = curry(sum, 1);
var count = 0;
var incrementedCount = increment(count); // 1

2.3。 您可以动态定义函数 (2.3. You can define functions dynamically)

You can use “higher-order” functions or other means provided by your favorite programming language. Example of implementation of the curry function seen earlier, using closure (an important aspect of functional programming that I will not explain here) and ES6 arrow and spread syntaxes (alternatives to older JavaScript syntax that I will not explain here either):

您可以使用“高阶”功能或您喜欢的编程语言提供的其他方式。 使用闭包 (此处将不解释的功能编程的重要方面)和ES6 箭头和散点语法(此处也将不解释的较旧JavaScript语法的替代方式)实现curry函数的示例:

// returns a single-argument function from a multi-argument function
// the missing argument values are taken from the closure
function curry(multiArgumentFunction, …args){
return arg => multiArgumentFunction(arg, …args);
}

Should I care or should I not? Actually, you do not need to care too much about this peculiar aspect of functional programming: All modern languages (now) have support for most aspects of functions-as-fist-class-citizens. Moreover, JavaScript masters this beautifully well indeed (Yes, I love JavaScript. So what?).

我应该关心还是不应该? 实际上,您不需要太在意函数编程的这个特殊方面:所有现代语言(现在)都支持类公民函数的大多数方面。 而且,JavaScript确实很好地掌握了这一技巧(是的,我爱JavaScript。那又怎样?)。

3.声明式编程与过程式编程 (3. Declarative programming vs. procedural programming)

In declarative programming you specify what you want whereas in procedural programming you specify how you get what you want. The typical example is mapping an array:

在声明式编程中,您指定所需内容,而在过程式编程中,您指定获取所需内容的方式。 典型的示例是映射数组:

// procedural programming
for(var i = 0; i < array.length; i++){
array[i] = array[i] * array[i];
} // declarative programming
array.map(function(item){
return item * item;
});

Should I care or should I not? Array filter, map and reduce are quite fashionable these days. Are you sure you want to be left behind? The declarative style is more concise, more expressive (focused on what is important), less error prone. The procedural style uses a lot of side-effects (which you have already accepted to avoid after reading paragraph 2.1.).

我应该关心还是不应该? 如今,数组过滤,映射和归约非常流行 。 您确定要落后吗? 声明式样式更简洁,更富有表现力(着重于重要内容),更少出错。 程序风格具有很多副作用(阅读第2.1。节后,您已经接受了避免这些副作用)。

4.不变性 (4. Immutability)

Functional programming is often associated with the concept of “immutability”. Immutability results from the concept of referential transparency seen at paragraph 2.1. In functional programming, data structures are immutable. A pure function is not allowed to change the values contained in a data structure nor its internal references. Instead, the data structure is passed as argument to the pure function which returns an updated version of the data structure. Should I care or should I not? If you do functional programming, you will be confronted to immutability as it is the most noticeable practical difference between the functional paradigm and the procedural one. JavaScript is a multi-paradigm language which supports declarative programming as well as procedural programming. Most built-in functions dealing with objects and arrays do not modify their arguments (map, filter, reduce, concat, slice, …) but some other do (sort, splice, push, pop, …). You better know which one to use. RTFM! In some cases you might need to copy the data structure first:

函数式编程通常与“ 不变性 ”的概念相关联。 不变性源于第2.1段中提到的参照透明性的概念。 在函数式编程中,数据结构是不可变的。 纯函数不允许更改数据结构或其内部引用中包含的值。 而是将数据结构作为参数传递给纯函数,该函数返回数据结构的更新版本。 我应该关心还是不应该? 如果您进行函数式编程,您将面临不变性,因为它是函数式范例与过程式范例之间最明显的实际区别。 JavaScript是一种多范式语言,它支持声明式编程以及过程式编程。 大多数处理对象和数组的内置函数不会修改其自变量( mapfilterreduceconcatslice等 ),而其他一些函数会进行排序splicepushpop等 。 您最好知道使用哪个。 RTFM! 在某些情况下,您可能需要先复制数据结构:

// slice() without argument copies the array so 
// in-place sort() does not alter the original array
return array.slice().sort();

Immutability impacts performance. That much is true. Sometimes it goes unnoticed, sometimes it does not, for heavy processing on heavy data structure. Don’t get bitten. Be aware that in case you need it, medications exist, loads of them, either generic (techniques) or brand-named (libraries). Type “immutability libraries” in your favorite search engine and you will see what I mean by “loads of them“!

不变性会影响性能。 那是真的 。 有时,对于繁重的数据结构进行繁重的处理会引起注意,有时却不会引起注意。 别被咬 请注意,如果您需要它,则存在药品,大量药品(无论是通用药品(技术)还是品牌药品(图书馆))。 在您最喜欢的搜索引擎中输入“ 不变性库 ”,您将明白我所说的“负载量”!

5.功能组合器 (5. Function combinators)

A function combinator is a higher-order function in which each argument is a function and the result is a function. Combinators are a convenient way to combine functions into new functions. Here is an example of using the function composition combinator where increment and double are functions and compose is a combinator:

函数组合器是一个高阶函数,其中每个参数是一个函数,结果是一个函数。 组合器是将功能组合为新功能的便捷方法。 这是使用函数组合组合器的示例,其中增量 精度为函数, 组合为组合器:

var doubleAndIncrement = compose(increment, double);
var x = doubleAndIncrement(10); // 21

A combinator may even generate combinators. Just for fun, check the famous (at least in the lambda calculus realm) recursive strict fixed-point Z combinator in JavaScript! Should I care or should I not? Working with higher-order functions is fun and fulfilling (I have no proof other than my own experience so try it for yourself). Humanity level of consciousness is (slowly) rising and so is the level of abstraction in programming. That’s life!

组合器甚至可以生成组合器。 只是为了好玩,请检查JavaScript中著名的(至少在lambda演算领域中)递归严格定点Z组合器 ! 我应该关心还是不应该? 使用高阶函数很有趣而且很充实(除了我自己的经验,我没有其他证据,因此请自己尝试)。 人类的意识水平正在(缓慢)上升,编程中的抽象水平也在上升。 那就是生命 !

6.无点式 (6. Point-free style)

Programming with the point-free style, you do not mention the elements of the function domain. As this is not obvious to explain and to grasp, I will give an example about function composition.

使用无点样式编程,您不会提及函数域的元素。 由于这很难解释和掌握,因此我将举一个有关函数组成的示例。

// point-full style: x is an element of the g function domain
function FoG(x){ return f(g(x)); } // point-free style: using the compose function is a combinator,
// the x element is not needed
let FoG = compose(f, g);

Point-free style is related to function-level programming as opposed to value-level programming (the two programming paradigms identified by John Backus in 1977). Point-free is also related to concatenative programming paradigm (typically stack-oriented programming languages using the reversed polish notation such as Forth, PostScript and Joy). Should I care or should I not? Point-free is not point-less. Stated like that, the content may not be very convincing but I hope the form will impress you! Point-free style goes hand in hand with combinators and notably function composition.

无点风格与功能级编程有关,而与价值级编程有关( John Backus在1977年确定了两种编程范例 )。 无点还与级联编程范例(通常使用反向抛光符号(如Forth , PostScript和Joy ) 的面向堆栈的编程语言)有关。 我应该关心还是不应该? 无分并非毫无意义。 如此陈述,内容可能不会令人信服,但我希望表格能给您留下深刻的印象! 无点样式与组合器和功能组合密切相关。

7. Lambda演算 (7. Lambda calculus)

The lambda calculus is a formalism invented by Alonzo Church in the 1930’s which may be considered as the gist of today’s functional programming. It as been proved that the lambda calculus is Turing-complete which means that you can rewrite any procedural style program into a functional style program. The term “combinator” used in this presentation is borrowed from the lambda calculus. Here is the definition of the strict fixed-point Z combinator, mentioned earlier:

lambda演算是Alonzo Church在1930年代发明的一种形式主义,可以被认为是当今函数式编程的要旨。 事实证明,lambda演算是图灵完备的 ,这意味着您可以将任何程序样式程序重写为功能样式程序。 本演示文稿中使用的“组合器”一词是从lambda演算中借用的。 这是前面提到的严格定点Z组合器的定义:

λf.(λx.f(λy.x x y))(λx.f(λy. x x y))

Another important concept for functional programming, recursion, has also emerged from the lambda calculus. There are many interesting formalisms derived from the original lambda calculus, my two favorite ones being the minimalist jot language and the pi calculus which formalizes asynchronicity. Should I care or should I not? If you are only interested in practical matters, I advise you to bypass the lambda calculus (a real world program written in this formalism would be too scary for humans). You can see the term “lambda” everywhere nowadays in all major development environment. You know better. When some expert tells you that a “lambda” means an “anonymous function” because of the French expression “individu lambda”, you know better (hijack of the caret ^ notation from Principia Mathematica). It is important to know bird names!

函数编程的另一个重要概念,即递归,也来自lambda演算。 从原始的lambda演算派生出许多有趣的形式主义,我最喜欢的两个是极简主义的jot语言和将异步形式化的pi演算 。 我应该关心还是不应该? 如果您仅对实际问题感兴趣,建议您绕过lambda演算(用这种形式主义编写的现实世界程序对人类来说太可怕了)。 在当今的所有主要开发环境中,您都可以看到“ lambda”一词。 你比较清楚。 当某个专家告诉您“ lambda”由于法语表达“ individu lambda”而意味着“匿名函数”时,您会更好地知道( Principia Mathematica劫持了插入符号)。 重要的是要知道鸟的名字 !

8.函数类型签名 (8. Function type signature)

The idea is to declare the type of each argument of a function as well as the type of its result. Often, functional programming makes heavy use of function type signature. Because of higher-order functions, function type signature may quickly become complex as the type of an argument or result may itself be a complex function type, including recursive types. The most widespread formalism is the Hindley–Milner type system. As an example, here is the function type signature of the JavaScript reduce Array function (an arrow represents a function, letters represents generic types, the square brackets represents an array of a generic type and parentheses disambiguate precedence):

想法是声明一个函数的每个参数的类型以及其结果的类型。 通常,函数式编程大量使用函数类型签名。 由于存在高阶函数,函数类型签名可能会很快变得复杂,因为参数或结果的类型本身可能是复杂的函数类型,包括递归类型。 最普遍的形式主义是Hindley-Milner类型系统 。 例如,这是JavaScript reduce的函数类型签名 数组函数(箭头代表函数,字母代表泛型类型,方括号表示泛型类型数组,并且括号消除了优先级):

// reduce :: (b -> a -> b) -> b -> [a] → b

It reads: reduce is a function returning a value of type b and taking three arguments, the first argument is a function returning a value of type b and taking an argument of type b and an argument of type a, the second argument is a value of type b, the third argument is an array of type a. Other formalisms exists such as Algebraic Data Types which allows recursive composition of types (a product of type is a tuple and a sum of types is a union in more classical typing system) and Generalized Algebraic Data Types (a function type signature is considered as a type function which may be applied to types to generate types). Should I care or should I not? Although producing, understanding and maintaining function type signatures takes time, patience and self-sacrifice, you will find (at least I did) the benefit far overtakes the pain as it helps reasoning at a higher level of abstraction. Note that some functional language are loosely typed (JavaScript) or not typed at all (the original lambda calculus). You may however use type signatures (in code comments or on paper) to help your reasoning. If you believe typed languages are superior to untyped languages (because it helps preventing bugs, I guess), think a minute about the following: the untyped lambda calculus is Turing-complete, the typed lambda calculus is not. You wake up one morning and your lovely .js JavaScript files are all gone, replaced by those ugly .ts TypeScript files: do not panic, you are a type signature master!

记载: 减少是返回类型B的值,并采取三个参数的函数,第一个参数是在返回类型B的值,并采取b型的参数和类型的参数的函数,第二个参数是一个值类型b的第三个参数是类型a的数组。 其他形式化存在诸如代数数据类型 ,其允许的类型的递归组合(类型的产品是一个元组和类型的总和是在更经典的类型系统的联合)和广义代数数据类型 (函数类型签名被认为是一个类型函数,可应用于类型以生成类型)。 我应该关心还是不应该? 尽管产生,理解和维护功能类型签名需要花费时间,耐心和自我牺牲,但您会发现(至少我是这样做的)好处远远超过了痛苦,因为它有助于在更高的抽象水平上进行推理。 请注意,某些功能语言是松散类型(JavaScript)或根本没有键入(原始lambda演算)。 但是,您可以使用类型签名(在代码注释中或在纸张上)来帮助您进行推理。 如果您认为类型化的语言优于非类型化的语言(我想是因为它有助于防止错误),请仔细考虑以下内容:未类型化的lambda演算是图灵完备的,而类型化的lambda演算则不是。 早上醒来,您可爱的.js JavaScript文件全部消失了,取而代之的是那些难看的.ts TypeScript文件:不要惊慌,您是类型签名大师!

9.范畴论 (9. Category theory)

A major benefit with the formalism of pure functions is ability to apply mathematical proof on programs. When it comes to functional programming, the commonly used theory is the category theory. The category theory is altogether stated with very simple, very powerful and general concepts. Should I care or should I not? As already mentioned, array filter, map and reduce are quite fashionable these days. All of these and more are part of the category theory. You may have heard about Monads which is THE buzz-word associated to category theory in relation to functional programming (in the next post I will talk more about Monads in a paragraph about the functional programming curse). Be careful when deep-diving into category theory esoteric concepts:

纯函数形式化的主要好处是能够在程序上应用数学证明。 关于函数式编程,常用的理论是范畴论 。 范畴理论是用非常简单,非常有力和笼统的概念概括起来的。 我应该关心还是不应该? 如前所述,数组过滤,映射和归约这些天很时髦。 所有这些以及更多这些都是类别理论的一部分。 您可能已经听说过Monads ,这是与函数式编程相关的类别理论的流行语 (在下一篇文章中,我将在有关函数式编程诅咒的段落中进一步讨论Monads )。 深入分类理论深奥的概念时要小心:

A monad in a category X is a monoid object in the monoidal category of endofunctors of X with the monoidal structure given by composition.

X类的单子是X泛函的单子类中的单子对象,其单子结构由组成给出。

My quest continues with the next post in the series: Part 3/7 Why is Functional Programming so Controversial? Thanks I would like to thank my wife Sophie for her support during my quest and for sharing me with JavaScript. About the author Nicolas Roumiantzeff is a developer team member in one of 10 R&D scrum teams at Esker, a French SaaS company, where he designed and implemented several client-side JavaScript frameworks for highly customizable Web applications. He likes music, JavaScript (he might already have told you that) and planet Earth. His tech superheroes are: Albert Einstein who showed that you could achieve astonishing findings with an extremely cheap experiment, long before the browser console is at your (F12) fingertips, Andrew Wiles who showed that you could reach your most inconceivable dream even if your first attempt fails, Alan Turing who showed that you could prove the unprovable, Grigori Perelman who showed that being skilled in rocket science does not prevent you from being skilled in rocket lifestyle, Brendan Eich who showed that such a big huge impact could come out of such a tiny little thing.

我的追求继续于该系列的下一篇文章:第3/7部分为什么函数式编程如此有争议? 谢谢,我要感谢我的妻子索菲(Sophie)在我的搜寻过程中给予的支持以及与我分享JavaScript。 关于作者 Nicolas Roumiantzeff是法国SaaS公司Esker的10个研发Scrum团队之一的开发团队成员,他在其中设计和实现了多个客户端JavaScript框架,用于高度可定制的Web应用程序。 他喜欢音乐,JavaScript(他可能已经告诉过您)和地球。 他的技术超级英雄是: 艾伯特·爱因斯坦 ( Albert Einstein) ,他证明了您可以通过极其便宜的实验获得惊人的发现, 远远不及浏览器控制台触手可及(F12); 安德鲁·威尔斯 ( Andrew Wiles )证明,即使您第一次尝试,也可以实现最难以想象的梦想尝试失败, 艾伦·图灵 ( Alan Turing )证明了您可以证明无法证明的事实, 格里戈里·佩雷尔曼 ( Grigori Perelman )证明了掌握火箭科学并不能阻止您掌握火箭的生活方式, 布伦丹·艾希 ( Brendan Eich )证明了如此巨大的影响可能来自于一个小小的事情。

翻译自: https://medium/esker-labs/ascending-functional-reactive-programming-2-7-92a307b5f0c9

react 编程式路由

本文标签: 路由程式功能React