不同的编程语言中使用管道pipe(或者说链式调用)
管道pipe(或者说链式调用)既有优点也有缺点。
优点:使用得当可以使可读性强。使用得当可以使代码简洁。可扩展性好。
缺点:过度使用会导致可读性差。调试麻烦。性能问题。
目录
终端语言(如bash,zsh)一般有管道符|
# 将 `echo` 命令的输出传递给 `grep` 命令
echo "Hello, World!" | grep "World"
# 将 `ls` 命令的输出传递给 `wc` 命令,以统计文件和目录的数量
ls | wc -l
ocaml有管道符 |>
let square x = x * x
let double_val x = x * 2
let result = 4 |> square |> double_val
let () = Printf.printf "%d\n" result (* Output: 32 *)
elixir有管道符 |>
defmodule Example do
def square(x), do: x * x
def double_val(x), do: x * 2
end
result = 4 |> Example.square() |> Example.double_val()
IO.puts(result) # Output: 32
python, with toolz
!pip install toolz
from toolz import pipe
def square(x):
return x * x
def double(x):
return x * 2
result = pipe(4, square, double)
print(result) # Output: 32
javascript, with lodash
!npm install lodash
const _ = require('lodash');
function square(x) {
return x * x;
}
function double(x) {
return x * 2;
}
const pipe = _.flow(square, double);
console.log(pipe(4)); // Output: 32
ruby,自定义或者使用then,tap
def square(x)
x * x
end
def double(x)
x * 2
end
module Pipe
refine Object do
def pipe(func)
func.call(self)
end
end
end
using Pipe
result = 4.pipe(method(:square)).pipe(method(:double))
puts result # Output: 32
def square(x)
x * x
end
def double_val(x)
x * 2
end
# result = 4.then { |x| square(x) }.then { |x| double_val(x) } # `then` since Ruby 2.6
result = 4.tap { |x| break square(x) }.tap { |x| break double_val(x) } # `tap` since Ruby 1.9
puts result # Output: 32
mathematica, //
4 // #^2 & // #*2 & // Print
c#,自定义
using System;
public static class FunctionalExtensions
{
public static TResult Pipe<T, TResult>(this T input, Func<T, TResult> func) => func(input);
}
public class Program
{
static int Square(int x) => x * x;
static int Double(int x) => x * 2;
public static void Main(string[] args)
{
int result = 4.Pipe(Square).Pipe(Double);
Console.WriteLine(result); // Output: 32
}
}
c++,自定义
#include <iostream>
#include <functional>
#include <type_traits>
template<typename T>
class Pipeline {
public:
Pipeline(T value) : value_(value) {}
template<typename Func>
auto then(Func&& func) const -> Pipeline<decltype(func(std::declval<T>()))> {
using ReturnType = decltype(func(std::declval<T>()));
return Pipeline<ReturnType>(func(value_));
}
T get() const { return value_; }
private:
T value_;
};
int square(int x) { return x * x; }
int doubleVal(int x) { return x * 2; }
std::string to_string(int x) { return std::to_string(x); }
int main() {
std::string result = Pipeline<int>(4).then(square).then(doubleVal).then(to_string).get();
std::cout << result << std::endl; // Output: "32"
}
scala 3, with scala.util.chaining.pipe
import scala.util.chaining._
object Main extends App {
val result = 4.pipe(x => x * x).pipe(2 * _)
println(result) // Output: 32
}
octave,为了出效果而出效果
function y = square(x)
y = x * x;
end
function y = doubleVal(x)
y = x * 2;
end
function result = chain(x, funcs)
result = x;
for i = 1:length(funcs)
result = funcs{i}(result);
end
end
funcs = {@square, @doubleVal};
result = chain(4, funcs);
disp(result); % Output: 32
kotlin,使用let
fun square(x: Int) = x * x
fun doubleVal(x: Int) = x * 2
fun main() {
val result = 4.let(::square).let(::doubleVal)
println(result) // Output: 32
}
erlang(escript),自定义
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -escript main main
main(_) ->
Square = fun(X) -> X * X end,
DoubleVal = fun(X) -> X * 2 end,
Result = pipeline(4, [Square, DoubleVal]),
io:format("~p~n", [Result]). % Output: 32
pipeline(Value, Functions) ->
lists:foldl(fun(F, Acc) -> F(Acc) end, Value, Functions).
haskell,自定义
square :: Int -> Int
square x = x * x
doubleVal :: Int -> Int
doubleVal x = x * 2
(|>) :: a -> (a -> b) -> b
x |> f = f x
main :: IO ()
main = do
let result = 4 |> square |> doubleVal
putStrLn (show result) -- Output: 32