是否存在与 Perl 或 Ruby 中的触发器运算符等效的函数式编程概念?

发布于 2024-11-16 16:55:41 字数 401 浏览 9 评论 0原文

Ruby(和 Perl)有一个触发器的概念:

file = File.open("ordinal")
while file.gets
  print if ($_ =~ /third/) .. ($_ =~ /fifth/)
end

它给出了一个序数列表,例如

first
second
third
fourth
fifth
sixth

在到达“第三”时开始打印,在到达“第五”时停止:

third
fourth
fifth

是否有与此类似的函数式编程概念,或者这通常会用 takewhile 来描述?我不是在问某种特定的语言,只是问你会用什么术语来描述它。

Ruby (and Perl) has a concept of the flip flop:

file = File.open("ordinal")
while file.gets
  print if ($_ =~ /third/) .. ($_ =~ /fifth/)
end

which given a list of ordinals, such as

first
second
third
fourth
fifth
sixth

would start printing when it reached "third" and stop when it reached "fifth":

third
fourth
fifth

Is there a functional programming concept analogous to this, or would this normally be described in terms of takewhiles? I'm not asking about a particular language, just what term you'd use to describe it.

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

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

发布评论

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

评论(3

彩扇题诗 2024-11-23 16:55:42

与 @nanothief 的解决方案相同,但在 Scala 中:

def flipFlop[A](flip: A => Boolean, flop: A => Boolean, seq: Seq[A]): Seq[A] = {
  val (p, q) = seq.dropWhile(!flip(_)).span(!flop(_))
  p ++ q.take(1)
}

示例运行:

> flipFlop[Int](_ == 3, _ == 5, Nil)
List()

> flipFlop[Int](_ == 3, _ == 5, 1 to 19)
Vector(3, 4, 5)

Same as @nanothief's solution, but in Scala:

def flipFlop[A](flip: A => Boolean, flop: A => Boolean, seq: Seq[A]): Seq[A] = {
  val (p, q) = seq.dropWhile(!flip(_)).span(!flop(_))
  p ++ q.take(1)
}

Sample runs:

> flipFlop[Int](_ == 3, _ == 5, Nil)
List()

> flipFlop[Int](_ == 3, _ == 5, 1 to 19)
Vector(3, 4, 5)
狂之美人 2024-11-23 16:55:41

在函数式语言(例如 haskell)中,您可以将触发器条件作为谓词传递,并根据它过滤输入列表。例如,下面是 haskell 中 flipflop 的定义(如果你不了解 haskell,不用担心实现 - 关键部分是它的使用方式)

flipflop flip flop = 
  uncurry (++) . second (take 1) . break flop . dropWhile (not . flip)

:使用:

> flipflop (== 3) (== 5) [1..10]
[3,4,5]

这是一个仅通过使用高阶函数来创建有效的新语言构造的示例。

我不知道函数式语言中该构造是否有一个特殊的名称。

In a functional language such as haskell, you would pass in the flip and flop conditions as predicates, and filter an input list based on it. For example, the following is a definition of flipflop in haskell (don't worry about the implementation if you don't know haskell - the key part is how it is used):

flipflop flip flop = 
  uncurry (++) . second (take 1) . break flop . dropWhile (not . flip)

This is how it can be used:

> flipflop (== 3) (== 5) [1..10]
[3,4,5]

It is an example of making an effectively new language construct just by using higher ordered function.

I don't know if there is a special name for that construct in functional languages.

浅唱々樱花落 2024-11-23 16:55:41

取决于函数式语言。这个怎么样?

ff_gen =
  lambda{ |first, *conditions| 
    flipflop = false
    condition = first
    lambda{ |v| 
      if condition && condition[v]
        condition = conditions.shift
        flipflop = !flipflop
        true
      else
        flipflop
      end
    }
  }

ff = ff_gen[lambda{|v| v == 3}, lambda{|v| v == 5}, lambda{|v| v == 7}, lambda{|v| v == 11}]

puts (0..20).select{ |i| ff[i] }.inspect # => [3, 4, 5, 7, 8, 9, 10, 11]

补充:当然,Ruby 不是纯函数式语言,所以我决定用 Erlang 重写它:

#!/usr/bin/env escript

flipflop(E, {[H|T] = Conditions, FlipFlop}) ->
  case H(E) of
    true ->
      {true, {T, not FlipFlop}};
    false ->
      {FlipFlop, {Conditions, FlipFlop}}
  end;

flipflop(_, {[], FlipFlop}) ->
  {FlipFlop, {[], FlipFlop}}.

flipflop_init(Conditions) ->
  {[], {Conditions, false}}.

main([]) ->
  {L, _} = 
    lists:foldl(
      fun(E, {L2, FFState}) -> 
        case flipflop(E, FFState) of
          {true, FFState2} ->
            {[E|L2], FFState2};
          {false, FFState2} ->
            {L2, FFState2}
        end
      end,
      flipflop_init([
        fun(E) -> E == 3 end, 
        fun(E) -> E == 5 end, 
        fun(E) -> E == 7 end, 
        fun(E) -> E == 11 end
      ]), 
      lists:seq(0,20)
    ),
  io:format("~p~n", [lists:reverse(L)]),
  ok.

注意: 事实上,经典的触发器应该像 dropwhile( !第一)-> takewhile(!second),所以 Ruby 的触发器是临时触发器(与电子器件中的触发器相比)。

Depends on functional language. How about this?

ff_gen =
  lambda{ |first, *conditions| 
    flipflop = false
    condition = first
    lambda{ |v| 
      if condition && condition[v]
        condition = conditions.shift
        flipflop = !flipflop
        true
      else
        flipflop
      end
    }
  }

ff = ff_gen[lambda{|v| v == 3}, lambda{|v| v == 5}, lambda{|v| v == 7}, lambda{|v| v == 11}]

puts (0..20).select{ |i| ff[i] }.inspect # => [3, 4, 5, 7, 8, 9, 10, 11]

Added: Of course, Ruby is not a pure functional language, so I decided to rewrite it in Erlang:

#!/usr/bin/env escript

flipflop(E, {[H|T] = Conditions, FlipFlop}) ->
  case H(E) of
    true ->
      {true, {T, not FlipFlop}};
    false ->
      {FlipFlop, {Conditions, FlipFlop}}
  end;

flipflop(_, {[], FlipFlop}) ->
  {FlipFlop, {[], FlipFlop}}.

flipflop_init(Conditions) ->
  {[], {Conditions, false}}.

main([]) ->
  {L, _} = 
    lists:foldl(
      fun(E, {L2, FFState}) -> 
        case flipflop(E, FFState) of
          {true, FFState2} ->
            {[E|L2], FFState2};
          {false, FFState2} ->
            {L2, FFState2}
        end
      end,
      flipflop_init([
        fun(E) -> E == 3 end, 
        fun(E) -> E == 5 end, 
        fun(E) -> E == 7 end, 
        fun(E) -> E == 11 end
      ]), 
      lists:seq(0,20)
    ),
  io:format("~p~n", [lists:reverse(L)]),
  ok.

Note: In fact, classic flip-flop should work like dropwhile(!first) -> takewhile(!second), so Ruby's flip-flop is ad hoc one (compare with flip-flop in electronics).

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