2010-11-11 5 views
1

В рубине можно создать простую функцию переключения следующим образом:Можно ли включить функцию переключения в схему?

@switch = false 

def toggle 
    @switch = [email protected] 
end 

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

мне интересно, если это возможно сделать это в схеме. Самое близкое, что я могу получить:

(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 

Спасибо.

+0

Идея «no-mutations» заключается в том, что функции никогда не должны изменять что-либо вне себя. Таким образом, вы можете запускать функции, не беспокоясь о том, будут ли они иметь странные эффекты для остальной части программы. – erjiang

+0

Я понимаю функциональную парадигму (хотя я не уверен, что готов подписаться на нее еще). «Никогда» не настолько строг. Иногда, вы не тайно думаете: «Ох, если вспомнить о событии, было бы так приятно». Любое интерактивное программное обеспечение должно отслеживать взаимодействия - должно сохранять воспоминания о некоторых событиях/настройках. – Tim

ответ

0

Я хотел бы написать что-то вроде этого:

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

который может быть вызван следующим образом:

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

Небольшое пояснение: внешний лямбда-функция, которая принимает начальное состояние и возвращает другое функция, которая переворачивает это состояние вперед и назад при каждом вызове. Обратите внимание, что внешняя функция вызывается немедленно с #f на последней строке; тогда переключатель определяется как результат этого вызова, внутренняя функция захватывает state в закрытии.

Вы также могли бы написать что-то вроде этого:

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

make-switch берет то, что было раньше, и заворачивает его в другом функции. Теперь у нас есть фабрика для создания коммутаторов, каждая из которых имеет собственное внутреннее состояние. Таким образом, мы можем написать что-то вроде этого:

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

И видим, что каждый коммутатор не зависит от другого:

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

Аналогично можно параметризировать make-switch установить начальное состояние переключателя, и на и на.

Надеюсь, это поможет.

+0

Я в страхе. Вы ловкий гулящий гуру. Это дает мне много жевать. Спасибо. – Tim

+0

@Tim Как все, это просто требует немного практики. Продолжайте подключаться, и вы это получите. (Для записи я обнаружил, что работа через Little Schemer во второй раз была очень полезной.) И помните: когда вы сомневаетесь, просто оберните вокруг себя еще одну «лямбду». :) –

3

Вы можете сделать это так же, если вы хотите:

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

Является ли это домашнее задание?

+0

Не домашнее задание. Мне нравится сравнивать и контрастировать языки, а один на моем измельчительном блоке - это схема. Я не знал об этом переключателе! функция - никогда не появлялась в The Little Schemer. Спасибо за Ваш ответ. – Tim

+1

Я думаю, что вы имели в виду функцию * set! *, Но да, есть суб-культ программистов Scheme, которые пытаются избежать мутации, и, вероятно, поэтому это не происходит в The Little Schemer. Схема довольно гладкая - надеюсь, вы будете держать ее на своем блоке некоторое время. – xscott

+0

Да, ты прав. Я имел в виду набор !. Прямо сейчас, использование схемы немного похоже на промежутки времени. Это неудобная задача, но я также могу сказать, что есть преимущества для дискомфорта в мышлении через вещи в этом новом (для меня) функциональном способе. – Tim

Смежные вопросы