Как я могу снова использовать gethash поиск в языке Common LISP?

Если необходимо управлять им на стороне клиента, Вы не можете использовать Свойство видимости на стороне сервера. Вместо этого установите его стиль отображения CSS ни на "один". Например:

<asp:Label runat="server" id="Label1" style="display: none;" />

Затем Вы могли сделать его видимым на стороне клиента с:

document.getElementById('Label1').style.display = 'inherit';

Вы могли сделать скрытым снова с:

document.getElementById('Label1').style.display = 'none';

Имеют в виду, что могут быть проблемы с ClientID, являющимся более сложным, чем "Label1" на практике. Необходимо будет использовать ClientID с getElementById, не серверный идентификатор, если они будут отличаться.

8
задан Johan Kotlinski 3 March 2012 в 13:39
поделиться

5 ответов

Не делайте ничего особенного, потому что реализация делает это за вас.

Конечно, этот подход зависит от реализации, и производительность хеш-таблицы зависит от реализации. (Но тогда вопросы оптимизации всегда зависят от реализации.)

Следующий ответ относится к SBCL. Я рекомендую проверить, выполняют ли ваши хеш-таблицы Lisp такую ​​же оптимизацию. Если они этого не сделают, пожалуйтесь своему поставщику!

В SBCL происходит то, что хеш-таблица кэширует последний индекс таблицы , к которому получил доступ GETHASH.

Когда PUTHASH (или эквивалентно (SETF GETHASH)) ) вызывается, он сначала проверяет, является ли ключ в этом кешированном индексе EQ к ключу, который вы передаете.

Если да, вся процедура поиска по хеш-таблице пропускается, и PUTHASH сохраняет непосредственно в кешированном индексе .

10
ответ дан 5 December 2019 в 15:25
поделиться

Единственное, что вы могли бы сделать, это использовать defstruct для создания значения, на которое указывает каждая запись в вашей хеш-таблице. Ваш список значений (который вы нажимаете в своем текущем примере) может храниться внутри там. Создание структуры может быть выполнено либо в этом первоначальном вызове gethash (как значение по умолчанию), либо может быть выполнено вручную, если вы заметите, что там нет значения. Затем объект может быть обработан так же, как и вы.

(Это игнорирует вопрос о том, действительно ли вы хотите использовать такие сложные значения, как ключи хэш-таблицы, или есть ли способ Например, вы можете использовать в качестве ключей структуры / объекты CLOS вместо сложных списков, а затем вместо этого использовать хэш-таблицу EQ. Но это во многом зависит от того, что вы делаете.)

0
ответ дан 5 December 2019 в 15:25
поделиться

Возможны следующие обходные пути:

Если общий шаблон - поиск -> найти-это -> перезаписать-это, то вы можете заменить тип значения на список, содержащий тип значения. Затем, найдя объект значения для ключа, просто деструктивно замените его первый элемент, например

(defun try-add (i)
  (let ((old-i-list (gethash complex-list table nil)))
    (if (may-add (first old-i-list))
      (setf (first old-i-list) i)                     ; overwrite without searching again
      (setf (gethash complex-list table) (list i))))) ; not there? too bad, we have to gethash again

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


EDITED: отвечая на вопрос в комментариях: идея состоит в том, что вместо ключей хэш-таблицы, отображающей значения, хэш-таблица теперь будет отображать ключи в списки с одним элементом, где элемент является значением. Затем вы можете изменить содержимое этих списков, не касаясь самой хеш-таблицы. Следующее взято из SBCL:

* (defparameter *my-hash* (make-hash-table))
*MY-HASH*

* (setf (gethash :my-key *my-hash*) (list "old-value"))
("old-value")

* (gethash :my-key *my-hash*)
("old-value")
T

* (defparameter old-value-container (gethash :my-key *my-hash*))
OLD-VALUE-CONTAINER

* (setf (first old-value-container) "new value")
"new value"

* (gethash :my-key *my-hash*)
("new value")
T
0
ответ дан 5 December 2019 в 15:25
поделиться

Возможно, мне не хватает чего-то очевидного, но:

(defun try-add (i)
  (let ((old-i (gethash complex-list table)))
    (when (may-add old-i)
      (push i old-i))))

поскольку:

  • nil уже является значением по умолчанию для GETHASH
  • GETHASH извлекает весь объект, поэтому вы можете просто изменить его на месте, а не сообщать PUSH, как его искать снова
  • (точка стиля: используйте WHEN вместо IF, когда нет else-clause)

Edit: ой, я был: я пропустил случай, когда old-i равно нулю. Но если это не обычный случай, то это все равно может быть победой, поскольку вам нужно выполнить поиск только в этом случае:

(defun try-add (i)
  (let ((old-i (gethash complex-list table)))
    (when (may-add old-i)
      (if old-i
         (push i old-i)
        (push i (gethash complex-list table))))))

Хм, это работает?

0
ответ дан 5 December 2019 в 15:25
поделиться

«Профилирование показывает, что одинаковые тесты занимают много времени»

Да, но вы проверили, что поиск по хэш-таблице # 'EQUAL также занимает много времени времени?

Скомпилировали ли вы это для ускорения на оптимизирующем компиляторе, таком как SBCL, и просмотрели примечания к компилятору?

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

0
ответ дан 5 December 2019 в 15:25
поделиться