Схема - переменная доступа в закрытии

Допустим, у меня есть следующее замыкание в Scheme, которое увеличивает счетчик каждый раз, когда он вызывается:

 (define count
   (let ((next 0))
     (lambda ()
         (set! next (+ next 1))
         next)))

Мой вопрос просто, как я могу переписать эту функцию, чтобы я мог получить доступ к значению next без увеличения счетчика? Я пытался играть с лямбдами, но я просто не могу понять это.

Изменить: некоторый контекст:

(define (dispatch m)
    (let ((count 0))
        (cond ((eq? m 'withdraw) withdraw) ; Increments count
              ((eq? m 'deposit) deposit) ; Increments count
              ((eq? m 'balance) balance-return)
              ((eq? m 'transaction) count) ; "count" on this line should return the value
              (else (error "Unknown request -- MAKE-ACCOUNT"
                           m)))))

1 ответ

Решение

Не совсем понятно, как count связан с примером банковского счета, однако что-то так просто, как

(define (make-account)
    (let ((count 0)) ; Define `count` here...
        (define (dispatch m) ; ...and define `dispatch` such that `count` is in scope
            (cond ((eq? m 'next) ; On message 'next...
                   (lambda () (set! count (+ count 1)))) ; ...return the lambda, which has `count` in its scope
                  ((eq? m 'count) ; On message 'count...
                   count) ; ...return the current count
                  (else ; Otherwise...
                   (error "Unknown request -- MAKE-ACCOUNT" m)))) ...raise error
        dispatch)) ; Return `dispatch` from `make-account`

может быть то, что вы ищете.

Основными идеями являются:

  1. Создайте область, в которой ваша переменная может жить (здесь: область действия make-account процедура)
  2. Создайте свою переменную в этой области (здесь: (let ((count 0)))
  3. Просто получите доступ к нему в рамках (здесь: настройка или получение count)
  4. Вернуть то, что имеет переменную в области видимости (здесь: dispatch закрытие).

Вы можете тогда (define acc-dispatch (make-account))и впоследствии получить текущий счет, используя (acc-dispatch 'count), но вы все равно можете увеличить его, если хотите, используя ((acc-dispatch 'next)),

Обратите внимание, что последний применяет лямбду, возвращаемую при вызове (acc-dispatch 'next),

Другие вопросы по тегам