Заполнить список в цикле do возвращает список пустым - PullRequest
0 голосов
/ 24 октября 2018

Я изучаю 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)

Я хочу изменить список lst внутри do, но это не так.

Знаете ли вы, почему lst пуст?

ОБНОВЛЕНИЕ Я проверил следующие инструкции со следующими результатами:

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

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

Я до сих пор не знаю, почему lst пусто, когда я делаю цикл.

Ответы [ 4 ]

0 голосов
/ 24 октября 2018

Ваш код

(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
0 голосов
/ 24 октября 2018

Форма do имеет вид

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

, но вы написали

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

, к сожалению, значение (my-procedure '((a . 1)(b . 2)(c . 3))) было привязано к имени set! внутри цикла, а lst никогда не изменяется.

0 голосов
/ 24 октября 2018

Вот как я это делаю:

(do ([x 6000 (- x 1)])
  ((zero? x))
  (set! lst (cons (my-procedure '((a . 1)(b . 2)(c . 3))) lst)))
0 голосов
/ 24 октября 2018

Полагаю, вы имеете в виду это lst:

(define lst '())

Вы определили его как пустой список.Вы никогда не устанавливаете его на что-либо другое.

Возможно, документация set! немного поможет.Пока вы там, ищите документацию do.

Следующая проблема, с которой вы можете столкнуться, состоит в том, что установка чего-то одного и того же значения повторно не приведет к наблюдаемому эффекту (возможно, кроме температуры процессора).

...