将链接发挥到极致的语言?

发布于 2024-10-04 15:58:44 字数 548 浏览 13 评论 0原文

所以,我只是在想链接是多么酷以及它如何使内容更容易阅读。对于很多语言,当将一堆函数应用于变量时,您会编写如下内容:

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

So, I was just thinking about how cool chaining is and how it makes things easier to read. With a lot of languages, when applying a bunch of functions to a variable, you'd write something like this:

i(h(g(f(x))))

And you have to read it from right-to-left or inner-most to outer-most. You apply f first, then g, and so forth. But if it were chained, it would look more like

x|f|g|h|i

And you could read it like a normal human being. So, my question is, there has to be some languages that do it that way, what are they? Is that what these fancy-pants functional programming languages do?


Because of this, I usually end up creating a whole bunch of temp variables so that I can split it onto separate lines and make it more readable:

a = f(x)
b = g(a)
c = h(b)
what_i_really_wanted_all_along = i(c)

Where's with my magical language, you could still split it onto different lines, if they're getting too long, without needing intervening variables:

x | f
  | g
  | h
  | i

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

似梦非梦 2024-10-11 15:58:46

它并不是函数式编程所独有的,尽管它可能最好用函数式语言实现,因为函数组合的整个概念完全属于函数式编程的领域。

一方面,任何具有面向对象倾向的语言都具有返回类实例的方法的链接:

obj.method1().method2().method3(); // JavaScript
MyClass->new()->f()->g()->i(); # Perl

或者,这种链接模式最著名但最少的“编程语言”示例将是完全非 OO 和非对象的东西。 -function...你猜对了,Unix 中的管道。如,ls |切-c1-4 |排序-n。由于 shell 编程被认为是一种语言,所以我说这是一个完全有效的例子。

It's not exclusive to functional programming, though it probably best implemented in functional languages, since the whole concept of function composition is squarely in the functional programming's domain.

For one thing, any language with object-oriented bent has chaining for methods which return an instance of the class:

obj.method1().method2().method3(); // JavaScript
MyClass->new()->f()->g()->i(); # Perl

Alternately, the most famous yet the least "programming-language" example of this chaining pattern would be something completely non-OO and non-functional ... you guessed it, pipes in Unix. As in, ls | cut -c1-4 | sort -n. Since shell programming is considered a language, I say it's a perfectly valid example.

待天淡蓝洁白时 2024-10-11 15:58:46

好吧,您可以在 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

如您所见,函数从左到右读取,并且对象和函数都不需要任何特殊实现。秘密就在 compose 中。

Well, you can do this in JavaScript and its relatives:

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

As you can see, the functions read left-to-right and neither the object nor the functions need any special implementation. The secret is all in compose.

遗失的美好 2024-10-11 15:58:46

您所描述的本质上是流畅的界面模式。

维基百科有一个来自多种语言的很好的例子:

http://en.wikipedia.org/wiki/Fluent_interface< /a>

Martin Fowler 在这里写了他的文章:

http://www.martinfowler.com/bliki /FluentInterface.html

正如 DVK 指出的那样 - 任何方法可以返回其所属类的实例的 OO 语言都可以提供此功能。

What you're describing is essentially the Fluent Interface pattern.

Wikipedia has a good example from a number of languages:

http://en.wikipedia.org/wiki/Fluent_interface

And Martin Fowler has his write up here:

http://www.martinfowler.com/bliki/FluentInterface.html

As DVK points out - any OO language where a method can return an instance of the class it belongs to can provide this functionality.

吖咩 2024-10-11 15:58:46

C# 扩展方法完成的事情非常接近您神奇的语言,只是稍微不那么简洁:

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; }
    ...
}

Linq 非常广泛地使用它。

C# extension methods accomplish something very close to your magical language, if a little less concisely:

x.f()
 .g()
 .h()
 .i();

Where the methods are declared thus:

static class Extensions 
{
    static T f<T>(this T x) { return x; }
    static T g<T>(this T x) { return x; }
    ...
}

Linq uses this very extensively.

梦里寻她 2024-10-11 15:58:46

哈斯克尔。以下三个示例是等效的:

  • i(h(g(f(x))))(嵌套函数调用)
  • x & f&克&哈& i (根据要求从左到右链接)
  • (i . h . g . f)(x) (函数组合,在 Haskell 中更常见)

http://www.haskell.org/haskellwiki/Function_composition

http://en.wikipedia.org/wiki/Function_composition_(computer_science)

Haskell. The following three examples are equivalent:

  • i(h(g(f(x)))) (Nested function calls)
  • x & f & g & h & i (Left-to-right chaining as requested)
  • (i . h . g . f)(x) (Function composition, which is more common in Haskell)

http://www.haskell.org/haskellwiki/Function_composition

http://en.wikipedia.org/wiki/Function_composition_(computer_science)

春庭雪 2024-10-11 15:58:46

如果您通常不做数学运算,我并不是建议您可以使用 Mathematica ,但它确实足够灵活,可以支持 Postfix 表示法。事实上,您可以定义自己的表示法,但为了简单起见,我们仍使用 Postfix。

您可以输入:

Postfix[Sin[x]]

以获取

x // Sin  

Which 转换为 Postfix 表示法。或者,如果您有更深层次的表达式:

MapAll[Postfix, Cos[Sin[x]]]

获取:

(Postfix[x]//Sin)//Cos  

您可能首先看到 Postfix[x],因为对于 Mathematica x 是稍后要计算的表达式。

反之,你可以输入:

x // Sin // Cos  

To get course

Cos[Sin[x]]  

或者你可以用一个非常常用的习语,以 Postfix 形式使用 Postfix:

Cos[x] // Postfix

To get

x // Cos

HTH!

顺便提一句:
作为对 我的神奇语言在哪里? 的回答,请参阅以下内容:

(x//Sin 
  // Cos
  // Exp 
  // Myfunct)  

给出

Myfunct[E^Cos[Sin[x]]]  

PS:作为读者的练习:) ...如何对采用 n 变量的函数执行此操作?

I am not suggesting you could use Mathematica if you don't do some math usually, but it certainly is flexible enough for supporting Postfix notation. In fact, you may define your own notation, but let's keep with Postfix for simplicity.

You may enter:

Postfix[Sin[x]]

To get

x // Sin  

Which translates to Postfix notation. Or if you have a deeper expression:

MapAll[Postfix, Cos[Sin[x]]]

To get:

(Postfix[x]//Sin)//Cos  

Where you may see Postfix[x] first, as for Mathematica x is an expression to be evaluated later.

Conversely, you may input:

x // Sin // Cos  

To get of course

Cos[Sin[x]]  

Or you can use an idiom very frequently used, use Postfix in Postfix form:

Cos[x] // Postfix

To get

x // Cos

HTH!

BTW:
As an answer to Where's with my magical language,? , see this:

(x//Sin 
  // Cos
  // Exp 
  // Myfunct)  

gives

Myfunct[E^Cos[Sin[x]]]  

PS: As an excercise to the readers :) ... How to do this for functions that take n vars?

讽刺将军 2024-10-11 15:58:46

正如前面提到的,Haskell 支持函数组合,如下:

(i . h . g . f) x,相当于:i(h(g(f(x)) )))

这是数学中函数组合的标准运算顺序。然而,有些人仍然认为这是落后的。无需过多争论哪种方法更好,我想指出您可以轻松定义翻转组合运算符:

infixr 1 >>>, <<<
(<<<) = (.) -- regular function composition
(>>>) = flip (.) -- flipped function composition

(f >>> g >>> h >>> i) x
    -- or --
(i <<< h <<< g <<< f) x

这是标准库使用的表示法 Control.Category。 (尽管实际的类型签名是通用的,并且适用于除函数之外的其他事物)。如果您仍然对末尾的参数感到困扰,您还可以使用函数应用运算符的变体:

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

这与您想要的语法很接近。据我所知, % 不是 Haskell 中的内置运算符,但 $ 是。我忽略了中缀位。如果您好奇,这就是使上述代码解析为:

(((x % f) % g) % h) % i -- intended

而不是:的技术细节

x % (f % (g % (h % i))) -- parse error (which then leads to type error)

As has been previously mentioned, Haskell supports function composition, as follows:

(i . h . g . f) x, which is equivalent to: i(h(g(f(x))))

This is the standard order of operations for function composition in mathematics. Some people still consider this to be backward, however. Without getting too much into a debate over which approach is better, I would like to point out that you can easily define the flipped composition operator:

infixr 1 >>>, <<<
(<<<) = (.) -- regular function composition
(>>>) = flip (.) -- flipped function composition

(f >>> g >>> h >>> i) x
    -- or --
(i <<< h <<< g <<< f) x

This is the notation used by the standard library Control.Category. (Although the actual type signature is generalized and works on other things besides functions). If you're still bothered by the parameter being at the end, you can also use a variant of the function application operator:

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

Which is close to the syntax you want. To my knowledge, % is NOT a built-in operator in Haskell, but $ is. I've glossed over the infix bits. If you're curious, thats a technicality that makes the above code parse as:

(((x % f) % g) % h) % i -- intended

and not:

x % (f % (g % (h % i))) -- parse error (which then leads to type error)
单调的奢华 2024-10-11 15:58:45

是的,对于 F#,您有一个管道运算符 |>(也称为前向管道运算符,并且您有一个后向管道 <|)。

你可以这样写: x |> f|>克|> h|>我

查看这篇博客文章,它提供了现实生活中使用情况的好主意。

Yes, with F# you have a pipeline operator |> (also called forward pipe operator, and you have a backward pipe <|).

You write it like: x |> f |> g |> h |> i

Check this blog post that gives a good idea of real life usage.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文