2012-04-28 5 views
4

Как отправить список отдельной функции/процедуре, удалить элемент из списка, обновить новый список (элемент удален) и отобразить его из первой функции/процедура.Как обновить список в схеме (Racket)

Кроме того, я знаю, что вы можете использовать набор! для обновления списка, но я продолжаю видеть руководства, которые говорят, что с помощью set! не является «способом схемы».

Но я не понимаю, как еще создать эту программу, кроме этого пути (который не работает):

#lang racket 

(define list1 '("read" "id" "$$")) 

(define (displayer list1) 
    (remover list1) 
    (newline) 
    (display list1)) ;also doesn't display updated list here 

(define (remover list1) 
    (remove "$$" list1) 
    (display list1)) ;doesn't display updated list here 

Спасибо!

ответ

3

С вашего кода, если я пишу:

(displayer list1) 

он покажет:

(read id $$) 

Но если я изменить его на:

#lang racket 

(define list1 '("read" "id" "$$")) 

(define (displayer list1) 
    (display (remover list1))) 

(define (remover list1) 
    (remove "$$" list1)) 

Таким образом, когда вы запускаете

(displayer list1) 

Он вернется

(read id) 

помнить, что в функциональных языках, все это выражение и дело с «переменными» не изменяемые является предпочтительным способом (работает без государства делает его легче проверить, оптимизировать и распараллеливание программы и проще писать автоматизированные инструменты для выполнения этих задач, читайте здесь: http://en.wikipedia.org/wiki/Functional_programming#Comparison_to_imperative_programming) , поэтому, если вы хотите удалить элемент из списка, а затем отобразить, вам нужно написать функцию, которая возвращает новый список с меньшим количеством элементов

С другой стороны, Racket не является чистым функциональным языком, например Haskell, так как вы упоминалось выше, если вы действительно хотите, чтобы переопределить значение, на который ссылается переменная «песни1» вы можете использовать ракетку императивном образом, как это:

#lang racket 
(define list1 '("read" "id" "$$")) 

(define (displayer list1) 
    (set! list1 (remover list1)) 
    (newline) 
    (display list1)) 

(define (remover list1) 
    (remove "$$" list1)) 

комплект! перенаправляет list1, чтобы указать новое значение теперь

Вы можете прочитать об этом здесь: http://htdp.org/2003-09-26/Book/curriculum-Z-H-44.html

1
(remove "$$" list1) 

возвращается list1 с «$$» удалена, но не меняетlist1 ,Таким образом, решение является вызов дисплей с remover вызова:

(display (remover list1)) 

и переопределять remover, чтобы удалить «$$», но не имеют никаких других побочных эффектов (выход побочный эффект):

(define (remover list1) (remove "$$" list1)) 
3

Как указано в вопросе, это действительно, действительно не способ сделать что-то в схеме; тем не менее вы можете добиться того, что задаете в Racket, set!, используя глобальное определение и выбирая язык, который позволяет переопределять начальные привязки - тот факт, что вам нужно возиться с языковыми настройками, должен быть довольно четким признаком того, что вы делаете Это неправильно.

Во всяком случае, вот как:

(define list1 '("read" "id" "$$")) 

(define (displayer) 
    (remover) 
    (newline) 
    (display list1)) 

(define (remover) 
    (set! list1 (remove "$$" list1)) 
    (display list1)) 

(displayer) 
> (read id) 
> (read id) 

Более идиоматическое подходом было бы избежать определения глобальных переменных для изменения их внутри процедур; вместо того, чтобы каждый раз, когда вам нужно изменить список создать новый (remove создает новый список) и передать его вокруг, как это:

(define (displayer lst) 
    (let ((removed (remover lst))) 
    (newline) 
    (display removed))) 

(define (remover lst) 
    (let ((removed (remove "$$" lst))) 
    (display removed) 
    removed)) 

(define list1 '("read" "id" "$$")) 
(displayer list1) 
> (read id) 
> (read id) 

Обратите внимание, что второе решение делает не модифицировать list1, это функциональная способ решения проблемы.

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