2013-11-19 2 views
1

я определил специальный переменный * несортированный-LST * и функцию для переустановки этого переменного в моем сценарии:SETF в функции не работает

(defparameter *unsorted-lst* nil) 

(defun reset-to-unsorted-list() 
    (setf *unsorted-lst* '(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)) 
    (format t "after reset: ~a~%" *unsorted-lst*) 
) 

После этого я скопировать их SBCL консоли для тестирования, я :

* (setf *unsorted-lst* '(1 2 3)) 
(1 2 3) 
* (reset-to-unsorted-list) 
after reset: (1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44) 
NIL 

Все работает нормально. Тогда я сделал

* (setf (second *unsorted-lst*) 100) 
100 
* (reset-to-unsorted-list) 
after reset: (1 100 0 22 3 1 3 299 31 5 0 3 7 96 24 44) 
NIL 

SETF в функции, кажется, не работает, а второе значение элемента все еще было 100. Это действительно запутать меня. Мне нужно было ввести команду setf прямо в консоли, чтобы внести смену:

* (setf *unsorted-lst* '(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)) 

(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44) 
* *unsorted-lst* 
(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44) 

Теперь это работает. Я не могу сказать, что это не так? Есть некоторые недоразумения setf? или переменной?

+1

возможно дубликат [Неожиданное сохранение данных] (http://stackoverflow.com/questions/18790192/unexpected-persistence-of-data) –

+1

Буквенный данные _literal data_. Если вы знакомы с C или Java, вы можете подумать о цитируемом списке в 'reset-to-unsorted' как статическую переменную. Когда вы назначаете его значение переменной и изменяете базовый объект через эту переменную, вы меняете существующее значение _one_. –

+0

@Joshua Taylor: это просто, что точные эффекты изменения литеральных данных не определены в Common Lisp. Таким образом, избегайте этого. Также я думаю, что общее направление вопроса немного другое: что мы можем сделать, чтобы убедиться, что функция безопасно сбрасывает переменную? –

ответ

9

Вам необходимо установить переменные данные в новый свежий список, который является копией данных литерального типа. Не допускайте, чтобы глобальная переменная указывала на локальные литералы данных функции.

То, что вы смотрите, также является неопределенным поведением в программе Common Lisp.

В функции используются литеральные данные. Позже вы измените данные букв, изменив второй элемент списка. Что именно происходит, не объявлено. Некоторые возможные результаты:

  • данные разделяются с некоторыми другими переменными, все видят изменение.
  • ошибка происходит из-за байтом данных может находиться в памяти только для чтения
  • данные изменяются

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

Если вы хотите, чтобы функция сбросила значение переменной и создала нелитературные данные, вам сначала нужно скопировать список литералов.

CL-USER 30 > (defparameter *unsorted-lst* nil) 
*UNSORTED-LST* 

CL-USER 31 > (defun reset-to-unsorted-list() 
       (setf *unsorted-lst* 
        (copy-list '(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44))) 
       (format t "after reset: ~a~%" *unsorted-lst*)) 
RESET-TO-UNSORTED-LIST 

CL-USER 32 > (setf *unsorted-lst* '(1 2 3)) 
(1 2 3) 

CL-USER 33 > (reset-to-unsorted-list) 
after reset: (1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44) 
NIL 

CL-USER 34 > (setf (second *unsorted-lst*) 100) 
100 

CL-USER 35 > (reset-to-unsorted-list) 
after reset: (1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44) 
NIL 
+0

Я люблю тебя, ребята, я всегда могу получить обратную связь :) Lisp - это язык, на котором я уделял больше времени, чем изучению других языков, и это всегда подрывает мое понимание компьютерного языка. –

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