Domanda

Sto cercando di scoprire come posso fare un "rientro anticipato" in una procedura di schema di senza con un if di primo livello o cond come costrutto.

(define (win b)
 (let* ((test (first (first b)))
        (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                       (enumerate (length b)))))
  (when (and (not (= test 0)) result) test))
 0)

Ad esempio, nel codice di cui sopra, voglio win per tornare test se la condizione è soddisfatta when, altrimenti restituisce 0. Tuttavia, ciò che accade è che la procedura sarà sempre di ritorno 0, a prescindere dalla il risultato della condizione when.

La ragione per cui sto strutturo il mio codice in questo modo è perché in questo procedimento ho bisogno di fare numerosi controlli complessi (blocchi più simili al let* nell'esempio) e mettere tutto in una grande cond sarebbe molto ingombrante.

È stato utile?

Soluzione

Ecco come utilizzare call / cc per costruire return te stesso.

(define (example x)
  (call/cc (lambda (return)
    (when (< x 0) (return #f))
    ; more code, including possible more calls to return
    0)))

Alcuni sistemi definiscono una macro chiamata let / cc che consente di rilasciare alcuni dei rumori della lambda:

(define (example x)
  (let/cc return
    (when (< x 0) (return #f))
    0))

Naturalmente se il Piano non, lascia / cc è banale scrivere.


Questo funziona perché call / cc salva il punto in cui è stato chiamato come una continuazione. Passa che il mantenimento al suo argomento funzione. Quando la funzione di chiamate che la continuazione, Scheme abbandona qualunque stack di chiamate che aveva costruito finora e prosegue dalla fine della chiamata call / cc. Naturalmente, se la funzione non chiama mai la continuazione, poi appena ritorna normalmente.

Continuazioni non ottengono veramente spremere le meningi fino a quando si inizia a loro ritorno da quella funzione, o forse la loro memorizzazione in una struttura dati globale e li chiama in seguito. In caso contrario, sono proprio come le dichiarazioni strutturati-goto di qualsiasi altra lingua (mentre / per / pausa / ritorno / Continua / eccezioni / condizioni).


Non so che cosa il vostro codice completo assomiglia, ma potrebbe essere meglio andare con il cond e per scomporre le complesse verifiche in funzioni separate. Avendo bisogno di return e let* è di solito un sintomo di codice eccessivamente imperativo. Tuttavia, il metodo di chiamata / cc dovrebbe ottenere il codice a lavorare per la società.

Altri suggerimenti

Un modo potrebbe essere quello di utilizzare la ricorsione invece di looping, quindi una rapida uscita si ottiene non recursing ulteriormente.

È possibile utilizzare il supporto "chiamata con la continuazione corrente" per simulare un ritorno. C'è un esempio su wikipedia . La funzione viene chiamata call-con-corrente di continuazione , anche se c'è spesso un alias chiamato chiamata / cc che è esattamente la stessa cosa. C'è anche un esempio un po 'più pulito qui

Nota: Questo è piuttosto una tecnica di programmazione Scheme avanzata e può essere un po 'la mente di flessione in un primo momento ... !!!!

In questo caso non si vuole un momento, se si desidera un, anche se non di alto livello.

(define (win b)
  (let* ((test (first (first b)))
         (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                        (enumerate (length b)))))
    (if (and (not (= test 0)) result) 
        test
        0)))

Il motivo era sempre tornando a zero è che se il corpo del momento ma ho eseguito, il risultato sarebbe stato lasciato cadere sul pavimento. Vedete, il Lambda implicita nella funzione di definire modulo crea un blocco di inizio implicito anche, in modo

(define foo 
  (lambda (b)
     (begin
       (let ...)
       0)))

e il modo in cui iniziare le opere è che restituisce il risultato dell'ultima modulo all'interno, mentre lasciando cadere tutti i risultati intermedi sul pavimento. Tali risultati intermedi sono destinati ad avere effetti collaterali. Non si sta usando nulla di tutto ciò, che è grande (!), Ma bisogna stare attenti ad avere solo una forma (il cui risultato si vuole veramente) all'interno della definizione di funzione.

Grem

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