1

In ruby you can create a simple toggle function like so:

@switch = false

def toggle
  @switch = !@switch
end

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

I am wondering if it is possible to do it in scheme. The closest I can get is:

(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

Thanks.

Tim
  • 365
  • 2
  • 15
  • The idea of "no-mutations" is that functions should never modify something outside of itself. This way, you can run functions without worrying about whether they'll have strange effects on the rest of the program. – erjiang Nov 11 '10 at 16:01
  • I understand the functional paradigm (though I am not sure I am willing to subscribe to it yet).'Never' is so strict. Sometimes, don't you secretly think, "ooh, having a memory of the occurrence of an event would be so nice." Any interactive software must keep track of interactions--must keep memories of some events/settings. – Tim Nov 12 '10 at 00:06

2 Answers2

3

You can do it the same way if you like:

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

Is this homework?

xscott
  • 2,350
  • 16
  • 18
  • Not homework. I like comparing and contrasting languages and the one on my chopping block is scheme. I was not aware of the switch! function--never came up in The Little Schemer. Thanks for your answer. – Tim Nov 11 '10 at 05:20
  • 1
    I think you meant the *set!* function, but yeah there's a sub-cult of Scheme programmers that try to avoid mutation, and that's probably why it doesn't come up in The Little Schemer. Scheme is pretty slick - hopefully you'll keep it on your block for a while. – xscott Nov 11 '10 at 05:35
  • Yes, you're correct. I meant set!. Right now, using scheme is a bit like running intervals. It is an uncomfortable challenge, but I can also tell there are benefits to the discomfort of thinking through things in this new (for me) functional way. – Tim Nov 11 '10 at 23:56
  • If you advance to The Seasoned Schemer, `set!` is covered. – Sean Devlin Nov 12 '10 at 15:25
  • Oh, I am reading SS right now, but just started. I can't wait to meet set! – Tim Nov 12 '10 at 22:14
0

I would write something like this:

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

Which can be invoked like this:

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

A little explanation: the outer lambda is a function that takes an initial state and returns another function that flips that state back and forth upon each invocation. Note that the outer function is being invoked immediately with the #f on the last line; switch is then defined as the result of this invocation, the inner function capturing state in a closure.

You could also write something like this:

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

make-switch takes what we had before and wraps it in yet another function. Now what we have is a factory for making switches, each with their own internal state. So we can write something like this:

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

And see that each switch is independent of the other:

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

Similarly you could parameterize make-switch to set the initial state of the switch, and on and on.

Hope this helps.

Sean Devlin
  • 1,662
  • 12
  • 17
  • I am in awe. You are a lambda slinging guru. This gives me a lot to chew on. Thank you. – Tim Nov 13 '10 at 03:52
  • @Tim Like all things, it just takes a little practice. Keep plugging away and you'll get it. (For the record, I found that working through The Little Schemer a second time was very helpful.) And remember: when in doubt, just wrap another `lambda` around it. :) – Sean Devlin Nov 14 '10 at 19:05