Domanda

In Python, posso fare qualcosa di simile:

t = (1, 2)
a, b = t

... e una sarà 1 e B sarà 2. Supponiamo che io ho una lista '(1 2) nello Schema. Esiste un modo per fare qualcosa di simile con let? Se si fa la differenza, sto usando Racket.

È stato utile?

Soluzione

In racchetta è possibile utilizzare match ,

(define t (list 1 2))
(match [(list a b) (+ a b)])

e cose correlate come match-define :

(match-define (list a b) (list 1 2))

e match-let

(match-let ([(list a b) t]) (+ a b))

che funziona per le liste, vettori, le strutture, ecc ecc Per più valori, utilizza define-values :

(define (t) (values 1 2))
(define-values (a b) (t))

o let-values. Ma nota che non riesco a definire t come una "tupla", in quanto più valori non sono valori di prima classe in (la maggior parte) delle implementazioni schema.

Altri suggerimenti

Uno scarno linguaggio è quello di utilizzare applicare con lambda dove occorre utilizzare let , come:

(define t '(1 2))
(apply (lambda (a b)
          ;; code that would go inside let
        )
        t)

Il vantaggio è che funziona su qualsiasi implementazione. Naturalmente questo può essere utilizzato solo su casi semplici, ma a volte questo è tutto ciò che serve.

Il termine generale per quello che stai cercando per (almeno in Lisp-mondo) è destrutturazione e una macro che l'implementa è conosciuto come destrutturazione-bind . In Common Lisp, funziona in questo modo:

(destructuring-bind (a b c) '(1 2 3)
  (list a b c)) ;; (1 2 3)

funziona anche per più "livelli" di nidificazione:

(destructuring-bind (a (b c) d) '(1 (2 3) 4)
  (list a b c d)) ;; (1 2 3 4)

Sembra che ci sia un bella realizzazione di destrutturazione-bind come macro schema.

Credo che questo è quello che stai cercando:

Guarda let-values o let+.

Questo funziona in Racket, se non si vuole portare in dipendenza match:

Da un elenco:

(let-values ([(a b c) (apply values '(1 2 3))])
  (+ a b c))

o direttamente da un espressione valori:

(let-values ([(a b c) (values 1 2 3)])
  (+ a b c))

Ecco un semplice macro destructuring-bind per gli schemi con case-lambda (come Racket o Schema Chez):

(define-syntax bind
   (syntax-rules ()
      ((_ arg pat def body)
         (apply
            (case-lambda
               [pat body]
               [x def] )
            arg ))))

Ecco l'esempio che mi ha motivato a scrivere questo macro. Mettere il default prima che le marche del corpo per codice leggibile:

(define (permutations l)
   ;
   (define (psub j k y)
      ;
      (define (join a b)
         (bind a (ah . at) b
            (join at (cons ah b)) ))
      ;
      (define (prec a b z)
         (bind b (bh . bt) z
            (prec (cons bh a) bt
               (psub (cons bh j) (join a bt) z) )))
      ;
      (if (null? k)
         (cons (reverse j) y)
         (prec (list) k y) ))
   ;
   (psub (list) (reverse l) (list)) )

Qui ci sono punti di riferimento per le permutazioni di lunghezza 9 di calcolo, su vari schemi:

0m0.211s Chez Scheme
0m0.273s Bigloo
0m0.403s Chicken
0m0.598s Racket

La traduzione di GHC Haskell è 5 volte più veloce di Chez Scheme. Guile è molto più lento rispetto a qualsiasi di questi schemi.

A parte la facilità di sfruttare il codice esistente case-lambda, mi piace come questa macro accetta esattamente la stessa sintassi di liste di argomenti definizione di funzione. Amo la semplicità di schema. Sono abbastanza vecchio da ricordare la programmazione Fortran su schede perforate, in cui la sintassi consentita variato selvaggiamente con il contesto. Schema si suppone che sia migliore di quello. L'impulso è schiacciante all'Arte dei giglio sulla macro come questa. Se non è possibile giustificare la modifica della sintassi per le definizioni di funzioni troppo, quindi non cambiare la sintassi neanche qui. Avere una grammatica ortogonale è importante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top