Language agnostic 将链式链接发挥到极致的语言?
所以,我只是在想链接有多酷,它如何让事情更容易阅读。对于许多语言,当将一组函数应用于变量时,您会编写如下内容:Language agnostic 将链式链接发挥到极致的语言?,language-agnostic,fluent-interface,method-chaining,Language Agnostic,Fluent Interface,Method Chaining,所以,我只是在想链接有多酷,它如何让事情更容易阅读。对于许多语言,当将一组函数应用于变量时,您会编写如下内容: i(h(g(f(x)))) 你必须从右到左或者从最里面到最外面去读。首先应用f,然后应用g,依此类推。但如果用链子锁住,它看起来更像 x|f|g|h|i 你可以像正常人一样阅读它。所以,我的问题是,一定有一些语言是这样做的,它们是什么?这些函数式编程语言就是这么做的吗 因此,我通常会创建一大堆临时变量,以便将其拆分为单独的行,使其更具可读性: a = f(x) b = g(a)
i(h(g(f(x))))
你必须从右到左或者从最里面到最外面去读。首先应用f
,然后应用g
,依此类推。但如果用链子锁住,它看起来更像
x|f|g|h|i
你可以像正常人一样阅读它。所以,我的问题是,一定有一些语言是这样做的,它们是什么?这些函数式编程语言就是这么做的吗
因此,我通常会创建一大堆临时变量,以便将其拆分为单独的行,使其更具可读性:
a = f(x)
b = g(a)
c = h(b)
what_i_really_wanted_all_along = i(c)
我的魔法语言在哪里,你仍然可以把它分成不同的行,如果它们变得太长,而不需要插入变量:
x | f
| g
| h
| i
它不是函数式编程所独有的,尽管它可能最好用函数式语言实现,因为函数组合的整个概念完全属于函数式编程的领域 一方面,任何具有面向对象bent的语言都有返回类实例的方法的链接:
obj.method1().method2().method3(); // JavaScript
MyClass->new()->f()->g()->i(); # Perl
或者,这种链接模式最著名但最少的“编程语言”示例将是完全非OO和非函数的东西。。。你猜对了,Unix中的管道。与中一样,
ls | cut-c1-4 | sort-n
。既然shell编程被认为是一种语言,我说它是一个非常有效的例子。它不是函数式编程的专利,尽管它可能最好用函数式语言实现,因为函数组合的整个概念完全属于函数式编程的领域
一方面,任何具有面向对象bent的语言都有返回类实例的方法的链接:
obj.method1().method2().method3(); // JavaScript
MyClass->new()->f()->g()->i(); # Perl
或者,这种链接模式最著名但最少的“编程语言”示例将是完全非OO和非函数的东西。。。你猜对了,Unix中的管道。与中一样,ls | cut-c1-4 | sort-n
。既然shell编程被认为是一种语言,我说它是一个非常有效的例子。是的,使用F#你有一个管道操作符
(也称为前向管道操作符,你有一个后向管道F |>g |>h |>I
检查此选项,可以很好地了解实际使用情况。是的,使用F#可以使用管道操作符
(也称为前向管道操作符,使用后向管道操作符F |>g |>h |>i
勾选此项,可以很好地了解实际使用情况。Haskell。以下三个示例是等效的:
(嵌套函数调用)i(h(g(f(x)))
(根据要求从左到右链接)x&f&g&h&i
(函数组合,在Haskell中更常见)(i.h.g.f)(x)
Haskell。以下三个示例是等效的:
(嵌套函数调用)i(h(g(f(x)))
(根据要求从左到右链接)x&f&g&h&i
(函数组合,在Haskell中更常见)(i.h.g.f)(x)
您所描述的基本上是流畅的界面模式 Wikipedia有一个来自多种语言的好例子: 马丁·福勒在这里写道:
正如DVK所指出的——任何OO语言,只要方法可以返回它所属类的实例,就可以提供这种功能。您所描述的基本上是流畅的接口模式 Wikipedia有一个来自多种语言的好例子: 马丁·福勒在这里写道:
正如DVK所指出的——任何OO语言,只要方法可以返回它所属类的实例,就可以提供此功能。好的,您可以在JavaScript及其相关语言中实现这一点:
function compose()
{
var funcs = Array.prototype.slice.call(arguments);
return function(x)
{
var i = 0, len = funcs.length;
while(i < len)
{
x = funcs[i].call(null, x);
++i;
}
return x;
}
}
function doubleIt(x) { print('Doubling...'); return x * 2; }
function addTwo(x) { print('Adding 2...'); return x + 2; }
function tripleIt(x) { print('Tripling...'); return x * 3; }
var theAnswer = compose(doubleIt, addTwo, tripleIt)( 6 );
print( 'The answer is: ' + theAnswer );
// Prints:
// Doubling...
// Adding 2...
// Tripling...
// The answer is: 42
函数组合()
{
var funcs=Array.prototype.slice.call(参数);
返回函数(x)
{
变量i=0,len=funcs.length;
而(我
如您所见,函数从左到右读取,对象和函数都不需要任何特殊实现。秘诀在于
compose
好的,您可以在JavaScript及其相关程序中实现这一点:
function compose()
{
var funcs = Array.prototype.slice.call(arguments);
return function(x)
{
var i = 0, len = funcs.length;
while(i < len)
{
x = funcs[i].call(null, x);
++i;
}
return x;
}
}
function doubleIt(x) { print('Doubling...'); return x * 2; }
function addTwo(x) { print('Adding 2...'); return x + 2; }
function tripleIt(x) { print('Tripling...'); return x * 3; }
var theAnswer = compose(doubleIt, addTwo, tripleIt)( 6 );
print( 'The answer is: ' + theAnswer );
// Prints:
// Doubling...
// Adding 2...
// Tripling...
// The answer is: 42
函数组合()
{
var funcs=Array.prototype.slice.call(参数);
返回函数(x)
{
变量i=0,len=funcs.length;
而(我
如您所见,函数从左到右读取,对象和函数都不需要任何特殊实现。秘密在于
compose
如果您通常不做一些数学运算,我不建议您使用它,但它肯定足够灵活,可以支持后缀符号。事实上,您
MapAll[Postfix, Cos[Sin[x]]]
(Postfix[x]//Sin)//Cos
x // Sin // Cos
Cos[Sin[x]]
Cos[x] // Postfix
x // Cos
(x//Sin
// Cos
// Exp
// Myfunct)
Myfunct[E^Cos[Sin[x]]]
x.f()
.g()
.h()
.i();
static class Extensions
{
static T f<T>(this T x) { return x; }
static T g<T>(this T x) { return x; }
...
}
infixr 1 >>>, <<<
(<<<) = (.) -- regular function composition
(>>>) = flip (.) -- flipped function composition
(f >>> g >>> h >>> i) x
-- or --
(i <<< h <<< g <<< f) x
infixr 0 $
infixl 0 #
f $ x = f x -- regular function application
(%) = flip ($) -- flipped function application
i $ h $ g $ f $ x
-- or --
x % f % g % h % i
(((x % f) % g) % h) % i -- intended
x % (f % (g % (h % i))) -- parse error (which then leads to type error)