2016-08-31 1 views
-3

J'essaie une modification du code de tri sur http://home.adelphi.edu/~siegfried/cs270/270rl10.html où je me sers encore pour la fonction d'insertion:ne peut pas utiliser laisser Racket

(define (mysort alon) 
    (let insert ((n n) (alon alon)) 
    (cond 
     [(empty? alon) (cons n empty)] 
     [else (cond 
       [(< n (first alon)) (cons n alon)] 
       [else (cons (first alon) 
          (insert n (rest alon))])]) 
    (cond 
    [(empty? alon) empty] 
    [(cons? alon) (insert (first alon) 
          (mysort (rest alon)))]))) 

(mysort (list 1 2 3 4 5 6 2 3 1 4 5 2 10)) 

Cependant, il ne fonctionne pas au niveau de la variable « let » déclaration:

n: unbound identifier in module in: n 

Je vois ici (https://docs.racket-lang.org/reference/let.html) que 'laisser' doit avoir des valeurs initiales des variables. Peut-on utiliser 'let' sans initialiser les variables? Comment le code ci-dessus peut-il être corrigé?


Edit: J'ai essayé d'utiliser lambda, mais il ne fonctionne pas:

(define (mysort4 alon) 
    (let ([insert4 
     (lambda (n alon) 
      (cond 
      [(empty? alon) (cons n empty)] 
      [(< n (first alon)) (cons n alon)] 
      [else (cons (first alon) 
         (insert4 n (rest alon)))]))]) 
    (cond 
     [(empty? alon) empty] 
     [(cons? alon) (insert4 (first alon) 
          (mysort4 (rest alon)))]))) 

(mysort4 (list 1 2 3 4 5 6 2 3 1 4 5 2 10)) 

L'erreur est:

insert4: unbound identifier in module in: insert4 
+0

Nommé 'let' sans les valeurs initiales des variables serait juste un lambda. –

+0

Je ne suis pas en mesure d'insérer le mot-clé lambda dans le code ci-dessus. Les deux "(laisser insert (lambda (n alon" et "(laisser insérer lambda (n alon" ne fonctionne pas – rnso

+0

"(let ([insert4 (lambda (n alon) ...]))" ne fonctionne pas non plus – rnso

Répondre

0

Lorsque vous créez quelque chose avec let

(define test 10) 

(let ((test (lambda (x) 
       (list x test)))) 
    (test 'result)) 
; ==> (result 10) 

De toute évidence test à l'intérieur du lambda est celle qui est globale et non pas « lui-même », mais Pourquoi. let est juste sucre syntaxe pour une fonction anonyme qui est immédiatement appelé afin que nous puissions réécrire à ceci:

(define test 10) 
((lambda (test) 
    (test 'result)) 
(lambda (x) 
    (list x test))) 

Ici, vous voyez que la première lambda a test comme variable liée et donc sera toujours le premier opérande, mais le deuxième lambda n'a pas test à l'exception de la liaison globale.

Dans les procédures récursives on ne peut pas utiliser let car les liaisons ne sont pas dans l'environnement lors de la création de la fermeture (lambda est évalué). Pour résoudre ce problème, nous utilisons letrec qui résout ce problème:

(define test 10)  
(letrec ((test (lambda (x) 
       (list x test)))) 
    (test 'result)) 
; ==> (result #<procedure:test>) 

Pour voir pourquoi vous pouvez regarder l'expansion de cette forme:

(let ((test 'undefined)) 
    (let ((newtemp (lambda (x) (list x test)))) 
    (set! test newtemp)) 
    (test 'result)))) 
; ==> (result #<procedure:test>) 

Je ne développerai pas les formes let ici, mais regardez au fait que test existe au moment où le lambda est créé. Le lambda devient la valeur mais la liaison est la même.

define qui ne sont pas de niveau supérieur est réécrite * à un letrec si le code ci-dessous est exactement le même:

(let() ; this is to make `define` local and not global 
    (define test (lambda (x) 
       (list x test)) 
    (test 10)) 
; ==> (result #<procedure:test>) 

Dans un nom let le nom est lié dans une letrec, mais les autres valeurs ne sont pas .Pour fixer la première:

(define (mysort alon) 
    (cond 
    [(empty? alon) empty] 
    [(cons? alon) 
    (let insert ((n (first alon)) 
        (alon (rest alon))) 
     (cond 
     [(empty? alon) (cons n empty)] 
     [(< n (first alon)) (cons n alon)] 
     [else (cons (first alon) (insert n (rest alon)))]))])) 

Notez que je pressai le cond imbriquée depuis le point entier de cond est de ne pas avoir à imbriquer. C'est l'équivalent de if-elseif*-else dans d'autres langues. Le code ne fonctionne pas car il ne place que le premier élément. Pehaps insérant tous les éléments dans une liste commençant par une liste vide fonctionnerait.

La seconde fonctionnerait avec simplement changer de let à letrec. Le code est identique avec la même caractéristique qu'il insère seulement le premier élément selon le reste, mais la récursivité fonctionnera pour cet élément.

Si vous regardez la page que vous avez liée à vous verrez que la liste insert dans est déjà triée. c'est à dire. il vous manque quelque chose ..

insertion-sort n'est pas un algorithme efficace. #lang racket utilise le tri par fusion avec des réglages pour les listes plus petites. Essayer de le battre à la vitesse serait une course de fous.

* ou vice versa. raquette utilise letrec (letrec-values pour être précis)

0

usage interne définissent au lieu de let lorsque vous avez besoin des fonctions d'aide internes . Avec des changements minimes (à l'aide define au lieu de let) vous obtenez:

#lang racket 
(define (mysort alon) 
    (define (insert n alon) 
    (cond 
     [(empty? alon) (cons n empty)] 
     [else   (cond 
         [(< n (first alon)) (cons n alon)] 
         [else    (cons (first alon) 
               (insert n (rest alon)))])])) 
    (cond 
    [(empty? alon) empty] 
    [(cons? alon) (insert (first alon) 
          (mysort (rest alon)))])) 

(mysort (list 1 2 3 4 5 6 2 3 1 4 5 2 10)) 
+0

Je savais que ça fonctionnait, mais je voulais savoir si je pouvais utiliser 'let' dans cette situation, apparemment je ne peux pas ... – rnso

+3

Donc, ce que vous vouliez vraiment demander était "comment fonctionne named?" – soegaard

+1

regardez: http://stackoverflow.com/questions/31909121/how-does-the-named-let-in-the-form-of-a-loop-work – soegaard