为什么我看不到大多数高级语言的管道运算符?

在Unix Shell编程中,管道运算符是一个非常强大的工具。 使用少量的核心实用程序,系统语言(如C)和脚本语言(如Python),您可以构建极其紧凑且功能强大的Shell脚本,这些脚本将由操作系统自动并行化。

显然,这是一个非常强大的编程范例,但是我没有将管道视为除Shell脚本之外的任何语言的第一类抽象。 使用管道复制脚本功能所需的代码似乎总是很复杂。

所以我的问题是,为什么在现代高级语言(如C#,Java等)中看不到类似于Unix管道的东西? 是否有支持一流管道的语言(shell脚本除外)? 这是一种表达并发算法的方便,安全的方法吗?

以防万一有人提出它,我看了看F#管道转发运算符(forward pipe operator),它看起来更像是函数应用程序运算符。 据我所知,它对数据应用了一个函数,而不是将两个流连接在一起,但是我可以接受更正。

后记:在研究实现协程的同时,我意识到存在某些相似之处。 马丁·沃尔夫(Martin Wolf)在一篇博客文章中描述了一个与我类似的问题,只是用协程而不是管道。

14个解决方案
10 votes

哈哈! 多亏了我的Google-fu,我找到了一个您可能会感兴趣的解答。 基本上,答案是通过重载按位OR运算符以提供类似shell的管道操作来反对“除非确实需要,否则不要重载运算符”这一论点,从而导致Python代码如下:

for i in xrange(2,100) | sieve(2) | sieve(3) | sieve(5) | sieve(7):
    print i

从概念上讲,它所做的是通过筛选功能将2到99之间的数字列表(map)用管道传递,该功能会删除给定数字的倍数(先是2,然后是3,然后是5,然后是7)。 这是素数生成器的开始,尽管以这种方式生成素数是一个很糟糕的主意。 但是我们可以做更多的事情:

for i in xrange(2,100) | strify() | startswith(5):
    print i

这将生成范围,然后将所有范围从数字转换为字符串,然后过滤掉所有以5开头的内容。

文章显示了一个基本的父类,该类允许您重载两种方法map和3007782496592462462849,以描述管道的行为。 因此,strify()使用map方法将所有内容转换为字符串,而sieve()使用filter方法来清除不是数字倍数的内容。

它相当聪明,尽管也许意味着它不是Python语言,但是它展示了您所追求的目标以及一种可以轻松应用于其他语言的技术。

Chris Lutz answered 2020-08-12T06:58:51Z
6 votes

您可以在Erlang中非常轻松地对类型并行进行流水线操作。 以下是我在2008年1月发布的博文中的无耻复制/粘贴内容。

另外,格拉斯哥Parallel Haskell允许并行函数组合,这相当于同一件事,为您提供隐式并行化。

您已经想到了 管道-“ gzcat”如何 foo.tar.gz | tar xf-“?您可能不会 已经知道了,但是外壳是 运行解压缩和解压缩 并行-只是在tar中读取标准输入 直到数据被发送到stdout gzcat。

好吧,很多任务可以表达 在管道方面,如果可以的话 这样做然后获得一定程度的 David并行化很简单 King的辅助代码(甚至跨erlang) 节点,即。 机器):

pipeline:run([pipeline:generator(BigList),
          {filter,fun some_filter/1},
          {map,fun_some_map/1},
          {generic,fun some_complex_function/2},
          fun some_more_complicated_function/1,
          fun pipeline:collect/1]).

所以基本上他在这里做的是 列出步骤-每个步骤 有趣地实施 接受任何先前的内容作为输入 步进输出(乐趣甚至可以是 当然定义为内联)。 去检查 大卫的博客条目 代码和更详细的说明。

Mark Aufflick answered 2020-08-12T06:58:11Z
5 votes

例如,您可以在C#和Java中找到类似管道的内容,在其中获取连接流并将其放入另一个连接流的构造函数中。

因此,您使用Java:

new BufferedReader(new InputStreamReader(System.in));

您可能要查找链接输入流或输出流。

James Black answered 2020-08-12T06:59:21Z
4 votes

dplyr软件包在R中提供了类似于F#的管道转发运算符的功能:

rnorm(100) %>% abs %>% mean

结合dplyr软件包,它带来了一个简洁的数据处理工具:

iris %>%
  filter(Species == "virginica") %>%
  select(-Species) %>%
  colMeans
gkcn answered 2020-08-12T06:59:46Z
2 votes

感谢所有出色的答案和评论,以下是我所学的摘要:

事实证明,有一个完整的范式与我感兴趣的基于流的编程有关。 Hartmann流水线是专门为基于流的程序设计的语言的一个很好的例子。 Hartamnn管道概括了Unix和其他OS中使用的流和管道的概念,以允许多个输入和输出流(而不仅仅是一个输入流和两个输出流)。 Erlang包含强大的抽象,使您可以轻松地以类似于管道的方式来表达并发进程。 Java提供了PipedInputStream和PipedOutputStream,它们可以与线程一起使用,以更详细的方式实现相同的抽象。

cdiggins answered 2020-08-12T07:00:12Z
2 votes

您在查看F#|>运算符吗? 我认为您实际上需要>>运算符。

Nathan Phillips answered 2020-08-12T07:00:33Z
1 votes

我认为最根本的原因是因为C#和Java倾向于用于构建更多的单片系统。 从文化上讲,甚至不想做类似管道的事情并不常见-您只需使应用程序实现必要的功能即可。 在这些情况下,构建大量简单工具然后以任意方式将它们粘合在一起的想法并不常见。

如果您查看某些脚本语言,例如Python和Ruby,则有一些相当不错的工具可以在这些脚本中执行类似管道的操作。 例如,查看Python子流程模块,该模块可让您执行以下操作:

proc = subprocess.Popen('cat -',
                       shell=True,
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,)
stdout_value = proc.communicate('through stdin to stdout')[0]
print '\tpass through:', stdout_value
divegeek answered 2020-08-12T07:00:58Z
1 votes

Objective-C具有NSPipe类。 我经常使用它。

Dave DeLong answered 2020-08-12T07:01:20Z
1 votes

在Python中构建管道函数给我带来了很多乐趣。 我有一个编写的库,将内容和示例运行在此处。 我最适合的是XML处理,如Wikipedia文章所述。

Joel answered 2020-08-12T07:01:40Z
1 votes

基于协程的流媒体库在Haskell中已经存在了相当一段时间。 两个流行的例子是导管和管道。

这两个库都写得很好并且有据可查,并且相对成熟。 Yesod Web框架基于管道,而且非常快。 Yesod在性能上可以与Node竞争,甚至在一些地方都可以胜过它。

有趣的是,所有这些库在默认情况下都是单线程的。 这是因为管道的唯一激励用例是服务器,这些服务器受I / O约束。

Lambda Fairy answered 2020-08-12T07:02:20Z
1 votes

通常,您只是不需要它,没有它,程序运行会更快。

基本上,管道是消费者/生产者模式。 编写这些消费者和生产者并不难,因为他们没有太多数据。

  • 为Python配管:pypes
  • Mozart-OZ可以使用端口和线程来制作管道。
Egon answered 2020-08-12T07:02:53Z
0 votes

您可以通过链接/过滤/转换迭代器在Java中进行类似管道的操作。您可以使用Google的Guava迭代器。

我要说的是,即使使用了非常有用的guava库和静态导入,它最终仍然是很多Java代码。

在Scala中,使自己的管道操作员非常容易。

Adam Gent answered 2020-08-12T07:03:40Z
0 votes

如果您仍然对答案感兴趣...

您可以看一下因素,或者看一下串联模式带来的喜悦。输入参数和输出参数是隐式的,转储到堆栈中。 然后下一个单词(函数)将获取该数据并对其进行处理。

语法是后缀。

“ 123”打印

在哪里print需要一个参数,无论堆栈中有什么。

kobi7 answered 2020-08-12T07:04:18Z
0 votes

您可以在python中使用我的库:github.com/sspipe/sspipe

mhsekhavat answered 2020-08-12T07:04:53Z
translate from https://stackoverflow.com:/questions/1586850/why-dont-i-see-pipe-operators-in-most-high-level-languages