2011-06-23 7 views
6

Ruby (y Perl) tiene un concepto del flip flop:¿Existe un concepto de programación funcional equivalente al operador de flip-flop en Perl o Ruby?

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

cual da una lista de números ordinales, como

first 
second 
third 
fourth 
fifth 
sixth 

sería empezar a imprimir cuando se alcanza la "tercera" y se detendrá cuando que alcanzó "quinta":

third 
fourth 
fifth 

¿existe un concepto de programación funcional análogo a esto, o sería esto normalmente se describe en términos de takewhile s ? No estoy preguntando sobre un idioma en particular, solo qué término utilizarías para describirlo.

+0

Qué idiomas están considerando que para el FP? Hay muchos enfoques diferentes, y algunos pueden satisfacer sus necesidades. Además, ¿está usted, en este ejemplo, simplemente escribiendo la tercera - quinta línea? Es posible que desee explicar con más detalle lo que espera que suceda. –

+0

@James Black: ¿Cómo es la nueva versión de la pregunta? –

Respuesta

7

En un lenguaje funcional como haskell, pasaría en las condiciones flip-flop como predicados y filtraría una lista de entrada basada en él. Por ejemplo, la siguiente es una definición de flipflop en Haskell (no se preocupe por la puesta en práctica, si usted no sabe Haskell - la parte clave es cómo se utiliza):

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

Ésta es la forma en que puede ser utilizado:

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

Es un ejemplo de hacer una construcción de lenguaje efectivamente nuevo simplemente mediante el uso de una función más ordenada.

No sé si hay un nombre especial para esa construcción en los lenguajes funcionales.

4

Depende del lenguaje funcional. ¿Qué tal esto?

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] 

Agregado: Por supuesto, Ruby no es un lenguaje funcional puro, por lo que decidió volver a escribir en 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. 

Nota: De hecho, clásico flip-flop debe trabaje como dropwhile (! first) -> takewhile (! second), por lo que el flip-flop de Ruby es ad hoc (compare con el flip-flop en electrónica).

+0

¿Sabes si hay un término que describa el concepto? –

0

Igual que la solución de @ nanothief, pero en 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) 
} 

carreras de la muestra:

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

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