2010-11-11 13 views
1

En ruby ​​vous pouvez créer une simple fonction à bascule comme ceci:est-il possible de faire une fonction bascule dans le schéma?

@switch = false 

def toggle 
    @switch = [email protected] 
end 

toggle # => true 
toggle # => false 
toggle # => true 

Je me demande s'il est possible de le faire dans le schéma. Le plus proche que je peux obtenir est:

(define a #f) 
(define (toggle a) 
    (cond ((eq? a #t) #f) 
     (else #t))) 

(define a (toggle a)) 
a # => #t 
(define a (toggle a)) 
a # => #f 
(define a (toggle a)) 
a # => #t 

Merci.

+0

L'idée de «non-mutations» est que les fonctions ne devraient jamais modifier quelque chose en dehors de lui-même. De cette façon, vous pouvez exécuter des fonctions sans vous soucier de savoir si elles auront des effets étranges sur le reste du programme. – erjiang

+0

Je comprends le paradigme fonctionnel (même si je ne suis pas sûr d'être prêt à y adhérer), «Jamais» n'est aussi strict. Parfois, ne pensez-vous pas secrètement, "ooh, avoir un souvenir de l'occurrence d'un événement serait tellement agréable." Tout logiciel interactif doit garder une trace des interactions - doit garder des souvenirs de certains événements/paramètres. – Tim

Répondre

0

Je voudrais écrire quelque chose comme ceci:

(define switch 
    ((lambda (state) 
    (lambda() 
     (begin 
     (set! state (not state)) 
     state))) 
    #f)) 

qui peut être invoqué comme ceci:

> (switch) 
#t 
> (switch) 
#f 
> (switch) 
#t 

Une petite explication: le lambda externe est une fonction qui prend un état initial et retourne un autre fonction qui retourne cet état d'avant en arrière à chaque invocation. Notez que la fonction externe est invoquée immédiatement avec le #f sur la dernière ligne; Le commutateur est alors défini comme le résultat de cette invocation, la fonction interne capturant state dans une fermeture.

Vous pouvez aussi écrire quelque chose comme ceci:

(define make-switch 
    (lambda() 
    ((lambda (state) 
     (lambda() 
     (begin 
      (set! state (not state)) 
      state))) 
    #f))) 

make-switch prend ce que nous avions avant et l'enveloppe dans une autre fonction. Maintenant, ce que nous avons est une usine pour faire des commutateurs, chacun avec leur propre état interne. Nous pouvons donc écrire quelque chose comme ceci:

(define switch-a (make-switch)) 
(define switch-b (make-switch)) 

Et voir que chaque commutateur est indépendant de l'autre:

> (switch-a) 
#t 
> (switch-b) 
#t 
> (switch-b) 
#f 
> (switch-a) 
#f 

De même vous pourriez paramétrez make-switch pour définir l'état initial du commutateur, et ainsi sur.

Espérons que cela aide.

+0

Je suis dans la crainte. Vous êtes un gourou lambda. Cela me donne beaucoup à mâcher. Je vous remercie. – Tim

+0

@Tim Comme tout, il faut juste un peu de pratique. Continuez à brancher et vous l'aurez. (Pour l'anecdote, j'ai trouvé que travailler une seconde fois avec The Little Schemer était très utile.) Et rappelez-vous: en cas de doute, enveloppez juste un autre «lambda» autour d'elle. :) –

3

Vous pouvez le faire de la même façon si vous le souhaitez:

(define switch #f) 
(define (toggle) 
    (set! switch (not switch)) 
    switch) 

Est-ce devoir?

+0

Pas les devoirs. J'aime comparer et contraster des langues et celui sur mon billot est schéma. Je n'étais pas au courant de l'interrupteur! fonction - n'est jamais venu dans The Little Schemer. Merci pour votre réponse. – Tim

+1

Je pense que vous vouliez dire la fonction * set! *, Mais oui, il y a un sous-culte des programmeurs Scheme qui essaient d'éviter la mutation, et c'est probablement pourquoi ça ne se présente pas dans The Little Schemer. L'arrangement est assez lisse - j'espère que vous le garderez sur votre bloc pendant un moment. – xscott

+0

Oui, vous avez raison. Je voulais dire ensemble! À l'heure actuelle, l'utilisation de schéma est un peu comme des intervalles de fonctionnement. C'est un défi inconfortable, mais je peux aussi dire qu'il y a des avantages à l'inconfort de penser à travers les choses dans cette nouvelle façon fonctionnelle (pour moi). – Tim