![]() |
|
![]() ![]() ![]() |
|
s1nn |
|
||||
Новичок Профиль Группа: Участник Сообщений: 2 Регистрация: 4.2.2009 Репутация: нет Всего: нет |
Помогите с функцией.
Функция удаления повторных вхождений элементов в список (на верхнем уровне).
Есть список ((a b) d (e) (a b) d) при вызове функции delrep получается такая фигня ((a b) d (e))
Эта функция должна удалять только на верхнем уровне, а она удаляет и подсписки. При правильной работе должно получиться ((a b) d (e) (a b)). |
||||
|
|||||
VH_ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 182 Регистрация: 31.10.2006 Репутация: 10 Всего: 11 |
Элементом списка может быть <атом и> список. Так что удаление подсписков как элементов верхнего уровня происходит вполне корректно. Вот если бы в подсписках удалялись элементы, соответствующие элементам верхнего уровня - это было бы (для представленной функции) действительно некузявно.
Есть <немного более> простая версия требующейся функции: Хювёнен-Сеппянен "Мир Лиспа" т.1
Это сообщение отредактировал(а) VH_ - 5.2.2009, 14:22 |
|||
|
||||
VH_ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 182 Регистрация: 31.10.2006 Репутация: 10 Всего: 11 |
Однако функция (MAKESET) имеет два «недостатка»:
1) в множестве остаются элементы, расположенные ближе к концу исходного списка. Но ведь для множества в математическом смысле это несущественно; 2) функция пользуется неявным свойством применяемой функции (member) сравнивать элементы списка <по крайней мере в CommonLisp> посредством (EQL), то есть определять тождественность символов и равенство чисел (и то однотипных) и НЕ ОПРЕДЕЛЯТЬ одинаковость списков. При изменении поведения (member), например, при сравнении посредством (EQUAL), либо в другом диалекте повторные подсписки на верхнем уровне оставаться не будут.
|
|||
|
||||
adejneka |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 8.7.2005 Где: Москва, Россия Репутация: 9 Всего: 11 |
Еще один недостаток первой версии состоит в том, что в Common Lisp функция EQL определяет ТОЖДЕСТВЕННОСТЬ двух списков, т.е. результатом (let ((x '(a b c))) (makeset (list x 'e x))) будет (E (A B C)), а не ((A B C) E (A B C)). |
|||
|
||||
VH_ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 182 Регистрация: 31.10.2006 Репутация: 10 Всего: 11 |
«...функция EQL определяет ТОЖДЕСТВЕННОСТЬ двух списков...»
Позвольте не согласиться с данным утверждением. Речь идет об одинаковости в логическом отношении. В приведенном Вами примере (member) сравнивает посредством (EQL) не списки '(a b c) '(a b c), а символы x и x - а они действительно тождественны. Контрпример (комментарии мои):
|
|||
|
||||
adejneka |
|
||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 8.7.2005 Где: Москва, Россия Репутация: 9 Всего: 11 |
Хорошо, возможно, слово "тождественны" действительно неудачно (я имел в виду CLHS-термин "identical"). Но я не согласен с тем, что EQL сравнивает символы, сравниваются именно списки:
PRINT не показывает никаких X.
Если бы EQL сравнивал иксы, результат здесь был бы очень странный ![]() |
||||||
|
|||||||
VH_ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 182 Регистрация: 31.10.2006 Репутация: 10 Всего: 11 |
Обратимся к Common Lisp HyperSpec (восклицательные знаки мои - VH.):
Function EQL Syntax: eql x y => generalized-boolean Arguments and Values: x --- an object. y --- an object. generalized-boolean --- a generalized boolean. Description: The value of eql is true of two objects, x and y, in the folowing cases: 1. If x and y are eq. 2. If x and y are both numbers(!) of the same type and the same value. 3. If they are both characters(!) that represent the same character. Otherwise(!) the value of eql is false. If an implementation supports positive and negative zeros as distinct values, then (eql 0.0 -0.0) returns false. Otherwise, when the syntax -0.0 is read it is interpreted as the value 0.0, and so (eql 0.0 -0.0) returns true. Examples: (eql 'a 'b) => false (eql 'a 'a) => true (eql 3 3) => true (eql 3 3.0) => false (eql 3.0 3.0) => true (eql #c(3 -4) #c(3 -4)) => true (eql #c(3 -4.0) #c(3 -4)) => false (eql (cons 'a 'b) (cons 'a 'c)) => false (eql (cons 'a 'b) (cons 'a 'b)) => false (eql '(a . b) '(a . b)) => true OR => false (progn (setq x (cons 'a 'b)) (eql x x)) => true (progn (setq x '(a . b)) (eql x x)) => true (eql #\A #\A) => true (eql "Foo" "Foo") => true OR => false (eql "Foo" (copy-seq "Foo")) => false (eql "FOO" "foo") => false Normally (eql 1.0s0 1.0d0) is false, under the assumption that 1.0s0 and 1.0d0 are of distinct data types. However, implementations that do not provide four distinct floating-point formats are permitted to «collapse» the four formats into some smaller number of them; in such an implementation (eql 1.0s0 1.0d0) might be true. Side Effects: None. Affected By: None. Exceptional Situations: None. See Also: eq, equal, equalp, =, char= Notes: eql is the same as eq, except that if the arguments are characters or numbers of the same type then their values are compared. Thus eql tells whether two objects are conceptually the same, whereas eq tells whether two objects are implementationally identical. It is for this reason that eql, not eq, is the default comparison predicate for operators that take sequences as arguments. eql may not be true of two floats even when they represent the same value. = is used to compare mathematical values. Two complex numbers are considered to be eql if their real parts are eql and their imaginary parts are eql. For example, (eql #C(4 5) #C(4 5)) is true and (eql #C(4 5) #C(4.0 5.0)) is false. Note that while (eql #C(5.0 0.0) 5.0) is false, (eql #C(5 0) 5) is true. In the case of (eql #C(5.0 0.0) 5.0) the two arguments are of different types, and so cannot satisfy eql. In the case of (eql #C(5 0) 5), #C(5 0) is not a complex number, but is automatically reduced to the integer 5. |
|||
|
||||
adejneka |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 8.7.2005 Где: Москва, Россия Репутация: 9 Всего: 11 |
Надо было мне привести такой пример:
Здесь уж точно никакие символы не сравниваются. |
|||
|
||||
VH_ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 182 Регистрация: 31.10.2006 Репутация: 10 Всего: 11 |
Счас посмотрим. Немного минут можете подождать? Попробую картинку нарисовать - потому что это действительно красиво выглядит.
Это сообщение отредактировал(а) VH_ - 6.2.2009, 20:10 |
|||
|
||||
VH_ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 182 Регистрация: 31.10.2006 Репутация: 10 Всего: 11 |
Картинка к сожалению требует какой-то http:// - присоединяю файл с картинкой (Vingrad ругнулся на bmp - переименуйте файл в LISP.bmp).
В общем, дело в том, что список L2 создается посредством (LET) таким образом, что поле CAR первого элемента содержит указатель на ту же списочную структуру (A B C), что и поле CAR последнего элемента того же списка. Соответственно (member) сравнивает посредством (EQL) объекты (воспользуемся CLHS-style), физически представляющие одно и то же (identical). Потому и результат (makeset) такой. Присоединённый файл ( Кол-во скачиваний: 7 ) ![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума LISP | |
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Void. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | LISP | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |