Scheme - 在闭包中访问变量

时间:2015-10-20 08:58:48

标签: lambda scheme closures counter let

假设我在Scheme中有以下闭包,每次调用时都会增加一个计数器:

'attribute' => 'status',
'format' => 'raw',
'value' => function ($model) use ($bgStatus) {
    $status = Constant::$status['background'][$model->status];
    return Html::tag('span', $status, ['class'=>'label '.$bgStatus[$status], 'data-id'=>'1', 'data-ds'=>'123']);
},
'label' => 'Status'

我的问题很简单,如何重新编写此函数,以便在不增加计数器的情况下访问 (define count (let ((next 0)) (lambda () (set! next (+ next 1)) next))) 的值?我试过玩lambdas,但我似乎无法弄明白。

编辑:某些背景信息:

next

1 个答案:

答案 0 :(得分:3)

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闭包)。
  5. 然后,您可以(define acc-dispatch (make-account)),然后使用(acc-dispatch 'count)检索当前计数,但如果您愿意,仍然可以使用((acc-dispatch 'next))增加当前计数。

    请注意,后者通过调用(acc-dispatch 'next)来应用返回的lambda。