【问题标题】:Fill a list in a do loop returns the list empty在 do 循环中填充列表返回列表为空
【发布时间】:2018-10-24 20:56:17
【问题描述】:

我正在学习 Racket 不知道为什么 lst 总是为空:

#lang racket

(define sort-asc-by-second
  (lambda (lst)
    (sort lst
          (lambda (x y) (< (cdr x) (cdr y))))))

(define sum
  (lambda (lst)
    (apply + (map cdr lst))
  )
)

(define greater-than
    (lambda (lst y)
      (cond ((null? lst) (void))
            ((>= (cdr (car lst)) y) (car lst))
            (else (greater-than (cdr lst) y)))))

(define my-procedure
  (lambda (lst)
    (define sorted (sort-asc-by-second lst))
    (define suma (sum lst))
    (define probabilidades (map (lambda (p) (cons (car p) (/ (cdr p) suma))) sorted))

    (define prob (random))

    (car (greater-than lst prob))
   )
)
(define lst '())

(do ([x 6000 (- x 1)]
     (set! lst (my-procedure '((a . 1)(b . 2)(c . 3)))))
  ((zero? x) lst))

(display lst)

我想修改 do 中的 lst 列表,但没有。

你知道为什么 lst 是空的吗?

更新
我已经测试了以下指令,结果如下:

> (my-procedure '((a . 1)(b . 2)(c . 3)))
'a

> (set! lst (my-procedure '((a . 1)(b . 2)(c . 3))))
> (display lst)
'a

我仍然不知道为什么我在循环时lst 是空的。

【问题讨论】:

  • 您没有收到一些错误消息吗?
  • 没有。我没有任何错误。
  • 当您尝试在 REPL 提示符处评估它时,(set! (my-procedure '((a . 1)(b . 2)(c . 3))) lst) 是否按预期工作?当您在 REPL 提示符下尝试时,(my-procedure '((a . 1)(b . 2)(c . 3))) 返回了什么?
  • @WillNess REPL 提示?
  • @VansFannel 我已经添加了答案。

标签: scheme lisp racket


【解决方案1】:

do-form 是

(do (initialisers)
    (stop-condition end-expression)
    body)

但你已经写了

(do (initialiser body)
    (stop-condition end-expression))

不幸的是,(my-procedure '((a . 1)(b . 2)(c . 3))) 的值已在循环内绑定到名称 set!,并且永远不会修改 lst

【讨论】:

    【解决方案2】:

    我猜你的意思是这个lst

    (define lst '())
    

    您将其定义为空列表。您永远不会将其设置为其他任何值。

    也许documentation of set! 有点帮助。当您在那里时,查找do 的文档。

    您可能会遇到的下一个问题是,反复将某项设置为相同的值不会产生可观察到的效果(可能除了 CPU 温度)。

    【讨论】:

    • 但是我在do循环里面修改了。
    • 不,你没有。看看set! 语法。
    【解决方案3】:

    你的代码

    (do ([x 6000 (- x 1)]
         (set! lst (my-procedure '((a . 1)(b . 2)(c . 3)))))
      ((zero? x) lst))
    

    相同
    (do (  [x    6000  (- x 1)                                ]
           [set! lst   (my-procedure '((a . 1)(b . 2)(c . 3)))]  )
      ((zero? x) lst))
    

    您将set! 定义为循环变量之一(另一个是x)。 lst 是它的初始值,(my-procedure '((a . 1)(b . 2)(c . 3))) 是它的步骤表达式。

    所以你的set! 的本地绑定重复设置为'a,而x 倒计时到0;然后返回相同的lst——从未更改过——。

    试试看:

    > (do ([x 0 (- x 1)]
           (set! 1 (my-procedure '((a . 1)(b . 2)(c . 3)))))
      ((zero? x) set!))
    1
    

    【讨论】:

      【解决方案4】:

      这就是我的工作方式:

      (do ([x 6000 (- x 1)])
        ((zero? x))
        (set! lst (cons (my-procedure '((a . 1)(b . 2)(c . 3))) lst)))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-23
        • 1970-01-01
        • 2016-11-25
        • 1970-01-01
        • 1970-01-01
        • 2021-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多