2012-02-12 18 views
6

Dado que todos los ejemplos en la guía son con listas, me resulta difícil ver cómo utilizar la coincidencia de patrones en la raqueta para escribir correspondencia condicional como OCaml hace, por ejemplo:patrón condicional a juego en la raqueta

read ~var_a var_b s = match s.[0] with 
    | _ when var_b >= var_a + 4 -> 
     (* Do something *) 
    | "a" when is_negative var_b -> 
     (* Do something else *) 
    ... 

¿Cómo escribiría algo similar en Racket?

Gracias.

Respuesta

10

La biblioteca racket/match incluye coincidencia de patrones que puede utilizar predicados arbitrarios a través del patrón ?. Junto con and, deberías poder hacer que el emparejador de Racket se comporte. Aunque estoy un poco débil en mi OCaml, creo que la siguiente traducción del código anterior coincide con su significado:

(define (my-read #:var-a var-a var-b s) 
    (match (string-ref s 0) 
    [(and _ 
      (? (lambda (_) 
       (>= var-b (+ var-a 4))))) 
    "do something"] 
    [(and '#\a 
      (? (lambda (_) 
       (< var-b 0)))) 
    "do something else"])) 

;; Exercising the first case:  
(my-read #:var-a 50 
     60 "blah") 

;; Exercising the second case: 
(my-read #:var-a 50 
     -40 "alphabet") 

El matcher ? tiene una implícita and incrustado dentro de ella, así que el código se puede expresar un poco más sucintamente como:

(define (my-read #:var-a var-a var-b s) 
    (match (string-ref s 0) 
    [(? (lambda (_) 
      (>= var-b (+ var-a 4)))) 
    "do something"] 
    [(? (lambda (_) 
      (< var-b 0)) 
     #\a) 
    "do something else"])) 

en tanto, las lambdas en que no están viendo lo que se interpuso coincidentes, por lo que sólo ellos, llamado _ para denotar una de no importa. Pero se pueden imaginar patrones más sofisticados en los que los predicados podrían interesarse por lo que exactamente se combinó.

Eli sugiere usar aquí un cond general, ya que no hay ninguna coincidencia de patrones significativa en el código. Estoy de acuerdo. El código se vería así:

(define (my-read #:var-a var-a var-b s) 
    (cond 
    [(>= var-b (+ var-a 4)) 
    "do something"] 
    [(and (char=? (string-ref s 0) #\a) 
      (< var-b 0)) 
    "do something else"])) 
+3

El uso de tantos '?' Sugiere que se expresaría mejor con un simple 'cond' ... –

3

patrón de coincidencia puede ser fácilmente traducido a una secuencia de pruebas, no hay un lenguaje en el que no se puede hacer eso.

Lo bueno de OCaml (y probablemente Haskell) es que el compilador traduce el código en la secuencia óptima de pruebas cuando es posible (es decir, el programa nunca probará dos veces la misma condición, al menos cuando se evite los guardias when).

+1

Me esperaba que ocurriera lo mismo en Racket, ya que tiene capacidades de coincidencia de patrones explícitas, ¿no? – GiantSquid

+1

Probablemente sea el caso si usa 'match', pero no si usa' cond'. Pero no soy un experto en Racket, solo en OCaml. –

Cuestiones relacionadas