| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Непонятное поведение цикла по списку

Непонятное поведение цикла по списку

Ответ
Поиск в этой теме
Непрочитано 25.03.2012, 09:42 #1
Непонятное поведение цикла по списку
swkx
 
Регистрация: 22.01.2010
Сообщений: 311

День добрый.

Имеем список из 4-х элементов: ((1 T) (2 T) (3 T) (4 T))
В первом же шаге цикла меняю T на nil для элементов списка с 1-м значением >=3, т.е. получаем
((1 T) (2 T) (3 nil) (4 nil))
В цикле должны обрабатываться только те элементы, у которых 2-е значение = T,
поэтому я рассчитывал увидеть на экране:
elem: (1 T)
elem: (2 T)
но вместо этого увидел
elem: (1 T)
elem: (2 T)
elem: (3 T)
elem: (4 T)

Почему условие (if (cadr elem) ...) так нагло игнорируется ?
Такое впечатление, что в памяти образуется два экземпляра списка lst.
Проясните, плиз, такое поведение.

Код:
[Выделить все]
 (defun test ()
(setq lst (list '(1 T) '(2 T) '(3 T) '(4 T)))
(foreach elem lst
	(if (cadr elem)
	(progn
		(princ "\n elem: ") (princ elem)

		(setq lst2 (vl-remove-if
						(function (lambda (e)
								  	(< (car e) 3)
							  )
							)
						lst
						))
			
		(if lst2
			(foreach elem2 lst2
				(if (cadr elem2)
					(setq oldelem (car (vl-member-if (function (lambda (e) (equal e elem2))) lst))
						  newelem (subst nil T oldelem)
						  lst (subst newelem oldelem lst))
				)
			)
		)
			
	)
	)
)
(princ)
)
Просмотров: 7168
 
Непрочитано 25.03.2012, 12:26
#2
5hev

roads
 
Регистрация: 22.12.2010
msk
Сообщений: 121
<phrase 1= Отправить сообщение для 5hev с помощью Skype™


В строке 06 выводятся элементы списка lst, а не lst2.

Код:
[Выделить все]
 (defun test  ()
  (setq lst '((1 T) (2 T) (3 T) (4 T)))
  (mapcar '(lambda (x)
	     (if (and (> (car x) 2) (cadr x))
	       (setq lst (subst (list (car x) nil) x lst))))
	  lst)
  (foreach x lst (princ "\nElem: ")(princ x))
  (princ))
5hev вне форума  
 
Непрочитано 25.03.2012, 12:49
#3
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Код:
[Выделить все]
 (mapcar	'(lambda (x)
	   (if (< 2 (car x))
	     (list (car x) (not (cadr x)))
	     (progn (princ "\n elem: ") (princ x))
	   )
	 )
	(list '(1 T) '(2 T) '(3 T) '(4 T))
)
gomer вне форума  
 
Автор темы   Непрочитано 25.03.2012, 19:20
#4
swkx


 
Регистрация: 22.01.2010
Сообщений: 311


Вы меня не поняли, уважаемые.
Перед началом цикла список выглядит так: ((1 T) (2 T) (3 T) (4 T))
Уже после 1-го шага он выглядит так: ((1 T) (2 T) (3 nil) (4 nil))

Почему же на 3-м и 4-м шаге значение elem составляет (3 T) и (4 T) соответственно, как будто цикл ничего не знает о внесенных в список изменениях ?
swkx вне форума  
 
Непрочитано 25.03.2012, 19:35
#5
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Цитата:
Сообщение от swkx Посмотреть сообщение
Перед началом цикла список выглядит так: ((1 T) (2 T) (3 T) (4 T))
Уже после 1-го шага он выглядит так: ((1 T) (2 T) (3 nil) (4 nil))
Список не изменяемая структура - он не может на одном шаге выглядеть так, а на другом этак - если списки отличаються значит они РАЗНЫЕ (просто в Вашем случае Вы разным спискам присваиваете одинаковые имена) - то как Вы пытаетесь сделать "не кашерно" с точки зрения лиспа - Вам два примера уже дали вчетверо короче чем Ваш - а Вы все пытаетесь "блох" выловить.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Автор темы   Непрочитано 25.03.2012, 19:57
#6
swkx


 
Регистрация: 22.01.2010
Сообщений: 311


Цитата:
Сообщение от Дима_ Посмотреть сообщение
просто в Вашем случае Вы разным спискам присваиваете одинаковые имена
Никогда бы не подумал, что такое возможно
swkx вне форума  
 
Непрочитано 25.03.2012, 19:58
#7
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Цитата:
Сообщение от swkx Посмотреть сообщение
Вы меня не поняли, уважаемые.
мы вас поняли... смиритесь с таким положением дел, вот маленький пример:

Код:
[Выделить все]
 (defun test (lst)
  (foreach elem lst
    (princ lst) (princ "  ") (print elem)
    (setq lst (cons -1 lst))
  )
)
(test '(0 2 4 8 6))

Последний раз редактировалось gomer, 25.03.2012 в 20:10.
gomer вне форума  
 
Автор темы   Непрочитано 25.03.2012, 20:14
#8
swkx


 
Регистрация: 22.01.2010
Сообщений: 311


Что значит "смиритесь" ?))
Мне вполне достаточно знать, что это штатное поведение и оно таким и останется во всех подобных случаях, а не какой-нибудь глюк.
Не забыть бы только)...
swkx вне форума  
 
Непрочитано 25.03.2012, 21:00
#9
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Цитата:
Сообщение от swkx Посмотреть сообщение
Мне вполне достаточно знать, что это штатное поведение и оно таким и останется во всех подобных случаях, а не какой-нибудь глюк.
Вам бы неплохо понять почему оно такое. В вашем примере выдает ровно то, что Вы просите, посмотрите внимательней.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Автор темы   Непрочитано 25.03.2012, 21:14
#10
swkx


 
Регистрация: 22.01.2010
Сообщений: 311


Цитата:
Сообщение от Дима_ Посмотреть сообщение
Вам бы неплохо понять почему оно такое
Пока я только понял, что все изменения, вносимые в список во время цикла по этому списку, нельзя использовать для анализа в самом этом цикле.
Наверное, этого достаточно. В конце концов всегда есть несколько способов решения задачи.
swkx вне форума  
 
Непрочитано 25.03.2012, 21:24
#11
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Цитата:
Сообщение от swkx Посмотреть сообщение
Пока я только понял, что все изменения, вносимые в список....
Список НИКАК НЕВОЗМОЖНО изменить, все далее следствие непонимания этого.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Автор темы   Непрочитано 25.03.2012, 21:35
#12
swkx


 
Регистрация: 22.01.2010
Сообщений: 311


Цитата:
Сообщение от Дима_ Посмотреть сообщение
Список НИКАК НЕВОЗМОЖНО изменить
Так я этого и не знал. И что могут параллельно мирно сосуществовать два разных списка с одинаковыми именами - тоже не знал.
swkx вне форума  
 
Непрочитано 25.03.2012, 22:09
#13
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Цитата:
Сообщение от swkx Посмотреть сообщение
И что могут параллельно мирно сосуществовать два разных списка с одинаковыми именами
Тут вернее сказать могут, но не желательны - чтоб не путаться кто где.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 25.03.2012, 22:12
#14
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,787


Цитата:
Сообщение от Дима_ Посмотреть сообщение
Список НИКАК НЕВОЗМОЖНО изменить, все далее следствие непонимания этого.
Тогда переведи для сирых - что делает subst?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 25.03.2012, 23:41
#15
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Offtop: Алексей это Вы спрашиваете???
(subst x y z) Возращает НОВЫЙ список на основе z с измененными элеметами равными y на x,
логический аналог можно представить так (не оптимальный вариант, но "проще" всех показывает логику):
Код:
[Выделить все]
 (defun recsubst(x y z)
  (if z
      (cons (if (equal (car z) y) x (car z))
            (recsubst x y (cdr z)))))
з.ы. Хотя так наверное и наглядней:
Код:
[Выделить все]
 (defun mysubst(x y z)
  (mapcar '(lambda (a) (if (equal a y) x a)) z))
__________________
Когда в руках молоток все вокруг кажется гвоздями.

Последний раз редактировалось Дима_, 26.03.2012 в 00:33.
Дима_ вне форума  
 
Непрочитано 26.03.2012, 01:38
#16
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
Тогда переведи для сирых - что делает subst?
изменяет переменную lst в выражениях ( 3 аргумент функции foreach) второй аргумент она не может изменить по определению (не та область видимости). Поэтому, Дима_, в принципе, правильно написал, что это разные списки
gomer вне форума  
 
Автор темы   Непрочитано 26.03.2012, 07:07
#17
swkx


 
Регистрация: 22.01.2010
Сообщений: 311


Как у вас тут всё лихо закручено


Код:
[Выделить все]
 (setq lst '()
	  lst (cons (list 1 2 3) lst)
	  lst (cons (list 4 5 6) lst))
По вашему выходит, что это три разных списка. Какой в этом смысл, если, обращаясь к нему как к lst, всегда получите последний вариант ?
Т.е. по сути имеете дело всегда с одним списком.
swkx вне форума  
 
Непрочитано 26.03.2012, 08:36
#18
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Цитата:
Сообщение от swkx Посмотреть сообщение
По вашему выходит, что это три разных списка.
По "нашему" в этом коде вы трижды переопределяете переменную lst. Offtop: и сейчас полетят тухлые помидоры А по моему SETQ в автолиспе это "злейшие зло" благодаря которому все как-бы "упрощают" задачу, но тем самым закрывая самому себе дорогу понимания к ОСНОВАМ лиспа.
з.ы. Без присваивания (setq) конечно не возможны глобальные переменные и есть еще пара "узких" мест (по сути тоже возможны, но тут дело выходит за рамки "модели" автолиспа), но "втыкать" ее везде и всюду - ИХМО признак плохого тона и как минимум нечитаемости, "уязвимости" (когда без отладчика хрен поймешь что тут где) кода.
з.з.ы. To Gomer по моему ВАЖНО понимать разницу между изменением переменной lst и переопределением (ведь она по сути тоже неизменна).
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Автор темы   Непрочитано 26.03.2012, 08:43
#19
swkx


 
Регистрация: 22.01.2010
Сообщений: 311


Цитата:
Сообщение от Дима_ Посмотреть сообщение
ВАЖНО понимать разницу между изменением переменной lst и переопределением
И какая же между ними разница ???
swkx вне форума  
 
Непрочитано 26.03.2012, 08:54
#20
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Если Вы, например, двух своих сыновей (дочерей) двойняшек одинаковыми именами назовете - измениться ли у Вас количество детей?? Но с обращением к ним у Вас возникнут некоторые проблемы. Если делать аналогию с классическим (императивным) представлением в программировании, то lst это ссылка на список, а не изменяем он для того, чтоб не было разницы между ссылкой и содержимым (сколько-бы "копий" этого списка мы не создали - физически это одни и те-же данные). Переоперделить данные мы можем локально ((lambda (lst) (здесь уже другой lst)) '(1 2 3)), это же не значит что мы локально "изменили" список.
В автолиспе ИЗМЕНИТЬ мы можем, например, свойства объекта (entmod или vla-put), сама объектная (и DXF) модель разработанна под императивное программирование (имеет изменяемые состояния) - из за чего при обращении (изменении) к последней необходимо вводить vla-startundomark и учитывать в каком "состоянии" она находиться (но есть конечно и плюсы от этого подхода).
__________________
Когда в руках молоток все вокруг кажется гвоздями.

Последний раз редактировалось Дима_, 26.03.2012 в 09:00.
Дима_ вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Непонятное поведение цикла по списку

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Непонятное поведение многострочного атрибута блока Нитонисе AutoCAD 2 11.09.2010 17:35
Непонятное поведение функции strlen, и вообще об unicode в txt-файлах batmax Программирование 4 01.09.2010 19:08
Непонятное поведение SCADа Engineer SV Расчетные программы 1 06.08.2010 23:37
Как ввести ключевое слово в командную строку при выполнении цикла lisp'ом? Дмитрий_Leo LISP 8 15.05.2010 09:44