LINUX.ORG.RU

Lisp и хранение настроек

 


0

2

У меня есть хэш-таблица *h* такого вида:

item1 = '(:A a1 :B b1 :C c1)
item2 = '(:A a2 :B b2 :C c2)
то есть, ключи - список объектов, а значения - свойства объекта в виде plist. Далее, в программе такой код:
(defun foo (var)
  (let* ((var1 (gethash var *h*))
 	 (var2 (getf var1 :a)))
    (тут какой-то код)))
(foo 'item1)
то есть, сперва я получаю список свойств item1, а потом из этого списка я хочу получить поле :a. В var1 всё хорошо: там содержится нужный список. а вот в var2 всегда nil. Более того, если выполнить в repl
(getf (gethash 'item1 *h*) :a)
, будет nil. Однако, если выполнить
(gethash 'item1 *h*)
, потом скопировать полученый список в repl, и выполнить (getf скопированный-список :a), то результат будет правильный (то есть a1)

В связи с этим 2 вопроса:
1) как получить нужное значение
2) как правильно хранить и загружать какие-то конфиги. не в json-е же их хранить.


Ответ на: комментарий от Artificial_Thought

так?

'((item1 . (a1 b1 c1)) 
  (item2 . (a2 b2 c2)))
тогда как получать нужный список для item-ов? в цикле? это как-то не очень. да и нифига не наглядно

memnek
() автор топика
Ответ на: комментарий от buddhist

а зачем мне ещё одна сущность, если я могу всё хранить в обычных s-exp, а потом в самой программе делать из этого хэш (для удобства). просто я не могу понять, почему при выполнении gethash всё нормально, а если к результату gethash применить getf, то значения куда-то теряются

memnek
() автор топика
(defparameter *x*
  '((:item item1 :A a1 :B b1 :C c1)
    (:item item2 :A a2 :B b2 :C c2)))

(defun foo (var)
  (let* ((var1 (find var *x* 
		     :key #'(lambda (x) (getf x :item))))
	 (var2 (getf var1 :B)))
    ;some code))
ados ★★★★★
()
Ответ на: комментарий от memnek

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

memnek
() автор топика
Ответ на: комментарий от ados
(defparameter *x*
  '((:item item1 :A a1 :B b1 :C c1)
    (:item item2 :A a2 :B b2 :C c2)
    (:A :ito :C no :item YO :B bee)))

HTPE> (foo 'yo)

BEE
ados ★★★★★
()
* (defparameter *h* (make-hash-table))

*H*
* (setf (gethash 'item1 *h*) '(:A a1 :B b1 :C c1))

(:A A1 :B B1 :C C1)
* (setf (gethash 'item2 *h*) '(:A a1 :B b1 :C c1))

(:A A1 :B B1 :C C1)
* (getf (gethash 'item1 *h*) :a)

A1
* (getf (gethash 'item2 *h*) :c)

C1

Что-то где-то не так.

quasimoto ★★★★
()
Ответ на: комментарий от memnek

так?

Да, можно как-то так:

(
  ...
  (:item1 :a a1 :b b1 :c c1)
  (:item2 :a a2 :b b2 :c c2)
  ...
)

Без quote и как можно в более простом формате. Потом прочитать конфиг read-ом и построить хэш-таблицу (возможно, вложенную) одним (и более) loop-ом. Eval при этом не нужен.

Ещё можно писать в конфиге

(my-config *foo*
  ...
  (:item1 :a a1 :b b1 :c c1)
  (:item2 :a a2 :b b2 :c c2)
  ...)

для этого написать

(defmacro my-config (name &body body)
  `(defparameter ,name ,(тут парсим body и строим хэш-таблицу)))

тогда (load «that-config.lisp») автоматически будет определять переменную *foo* с уже готовой таблицей, так как код прочитается, макрос раскроется, то есть напишет код разбора конфига в таблицу и нужный defparameter потом выполнится.

quasimoto ★★★★
()

Всем спасибо. Сделал так

;; config.lisp
((item1 . (:a "a1" :b "b1")
 (item2 . (:a "a2" :b "b2"))
;; сама программа:
(defun load-config (&optional (filename "config.lisp"))
  (let ((lst (with-open-file (fin filename)
	       (read fin)))
	(h (make-hash-table)))
    (loop :for i :in lst :do
      (setf (gethash (car i) h) (cdr i)))
    h))	
;; и функция
(defun foo (item)
  (let* ((config (load-config))
	 (item (gethash item config))
	 (a (getf item :a))
	 (b (getf item :b)))
    (format t "~a ~a" a b)))
(foo 'item1) => "a1 b1"
ошибка была в том, что plist был квотирован. убрал апостроф - всё заработало

memnek
() автор топика
Ответ на: комментарий от memnek
(x . (...)) == (x ...)

так что можно просто

;; config.lisp
((item1 :a "a1" :b "b1")
 (item2 :a "a2" :b "b2"))
quasimoto ★★★★
()
Ответ на: комментарий от ados

А какой есть суффикс для s-exp конфигов?

read и load всё равно, так что на усмотрение программы - lisp, sexp, elc (enterprise lisp config) и т.п. Если в файле просто s-выражение (можно сделать read, но нельзя eval), то, наверно, sexp, если там что-то специфичное - можно выбрать специфичный суффикс (foo.vertex, bar.edge, baz.face, qux.path}, если там вариант с макросом, так что предполагается делать load, то разумно оставить *.lisp.

quasimoto ★★★★
()

Вопрос к ТС: сколько времени надо, чтоб развернуть свой мозг (читай изучить) в направлении Lisp

KennyMinigun ★★★★★
()
Ответ на: комментарий от memnek

Вариант с макросом:

(defun parse-config (sexp)
  (let ((table (make-hash-table)))
    (loop :for exp :in sexp :do
      (assert (symbolp (first exp)))
      (setf (gethash (first exp) table) (rest exp)))
    table))

(defmacro define-config (name &body body)
  `(defparameter ,name ,(parse-config body)))

сам конфиг:

(define-config *2items*
  (item1 :a "a1" :b "b1")
  (item2 :a "a2" :b "b2"))

и потом

> (load "config.lisp")
T
> *2items*
#<HASH-TABLE :TEST EQL :COUNT 2 {1002B5D281}>
> (getf (gethash 'item1 *2items*) :b)
"b1"
quasimoto ★★★★
()
Ответ на: комментарий от ados

Код, данные, какая разница?

Разница может быть, если данные которые мы вкладываем в s-выражения нужно валидировать, то есть они по структуре намного проще s-выражений. Ещё если сами конфиги должны выглядеть не как s-выражения, то нужно либо писать свой парсер в s-выражения (возможно, вешать его на reader macros), либо писать парсер напрямую в нужные структуры данных (хэш-таблицы, классы/структуры и т.п.) вообще без задействования s-выражений.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Ну и с валидацией:

(defstruct item
  (a nil :type string)
  (b nil :type string))

(defun parse-config (sexp)
  (let ((table (make-hash-table)))
    (loop :for exp :in sexp :do
      (let* ((first (first exp))
             (rest (rest exp))
             (a (getf rest :a))
             (b (getf rest :b)))
        (assert (symbolp first))
        (assert (stringp a))
        (assert (stringp b))
        (setf (gethash first table) (make-item :a a :b b))))
    table))

(defmacro define-config (name &body body)
  `(defparameter ,name ,(parse-config body)))
(define-config *2items*
  (item1 :a "a1" :b "b1")
  (item2 :a "a2" :b "b2"))
> (type-of *2items*)
HASH-TABLE
> (type-of (gethash 'item1 *2items*))
ITEM
> (item-b (gethash 'item2 *2items*))
"b2"
quasimoto ★★★★
()
Ответ на: комментарий от KennyMinigun

сколько времени надо, чтоб развернуть свой мозг (читай изучить) в направлении Lisp

По традиции - http://norvig.com/21-days.html.

Допустим я знаю C/C++, bash, perl, python

python

Тогда именно в лиспе (вообще) почти нечего учить - только quote и макросы могут быть в новинку. В CL/Clojure/Racket, конечно, много своих особенностей.

quasimoto ★★★★
()
Ответ на: комментарий от KennyMinigun

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

memnek
() автор топика
Ответ на: комментарий от KennyMinigun

в направлении Lisp

Помимо всего вышеперечисленного в это широкое направление впадает секс с emacs'ом и ФП с scheme.

ados ★★★★★
()
Ответ на: комментарий от KennyMinigun

сколько времени надо, чтоб развернуть свой мозг (читай изучить) в направлении Lisp

Первые три главы Practical Common Lisp. Дальше само пойдет, если есть свои задачи, к которым будешь применять полученные знания.

anonymous
()
Ответ на: комментарий от anonymous

сколько времени надо, чтоб развернуть свой мозг (читай изучить) в направлении Lisp

Первые три главы Practical Common Lisp. Дальше само пойдет, если есть свои задачи, к которым будешь применять полученные знания.

Не понимаю всеобщей любви к Practical Common Lisp. Я вот на ЛОР-е обчитался дифирабм к этой книге, скачал и начал читать.

Первая глава - мусор. Ну это наверное политика издательства, а не вина автора. (В том смысле, что целая глава тратиться на то, чтобы описать как сделать sudo apt-get install sbcl). Ну ладно, пропустили I главу.

Вторая глава (про REPL)- не мусор, но и ничего дельного не говорит. Т.е. если бы я не был знаком со схемкой, то ничего бы из этой главы не понял, ну просто перепечатал бы примеры. В главе очень много разного материала, но суть вещей не объясняется. Ладно, прочитали II главу, но ничего нового не узнали.

Третья глава - оооофииигенннноооооо! Ну т.е., черт с ней, то что там говорят о том, что якобы делают базу данных, и я на ЛОРе видел анона, который утверждал, что может после чтения 3 глав PCL сделать свою собственную РСУБД, но материала в этой главе ну очень много. Пока ее читал, даже возбудился — думал про себя всего навсего 3-ая глава, а уже столько интересного. Ну и разумеется читать её приходилось так: прочитал страницу — еще час гуглил по встречающим на этой странице вещам. Когда я дочитал 3-ую главу (убил на это выходные!), я подумал ого, что же будет когда дочитаю книгу до конца.

И вдруг такое разочарование: в следующих главах подробно говорится то, о чем была 3-ая глава и то, что я фактически уже нагуглил. На 8-ой главе, мне эта клоунада (ну зачем так ужасно писать книги?) уже порядком надоела и я нафиг выбросил эту книжку.

Я уже думал, что нормальной литературы по CL нету, как всё же решил рискнуть и начал читать «ANSI Common Lisp» — как оказалось, отличная книжка без клоунады с разделамы и без пафоса как в PCL. Материал отлично структурирован в ANSI Common Lisp и в общем всех советую именно эту книжку для введения в CL. Потом уже можно читать такие крышесносящие книжки, как PAIP и AMOP

anonymous
()
Ответ на: комментарий от buddhist

man SXML

Для тех, кто употребляет XML и его выкидыш SXML, в аду уготовлена специальная программа.

anonymous
()
Ответ на: комментарий от anonymous

Первая глава - краткий обзор и немного истории. Про apt-get ты перепутал что-то. Можно пропустить.

Вторая глава - введение в Emacs и Slime. Самое главное.

Третья - для затравки, небольшое Lisp-шоу, необязательно там досконально всё понимать.

А дальше уже свободный полёт, кому что интересно.

ANSI Common Lisp, Common Lisp The Language - справочники, краткий и подробный.

Practical Common Lisp, Land of Lisp, Paradigms of Artificial Intelligence Programming - практика.

On Lisp, Let Over Lambda, The Art of the Metaobject Protocol - продвинутый уровень.

Ну и самое главное - иметь цель, где применять знания, остальное приложится.

и я на ЛОРе видел анона, который утверждал, что может после чтения 3 глав PCL сделать свою собственную РСУБД

Это был я, и я говорил про «простенькую СУБД», ту что в главе. :)

anonymous
()
Ответ на: комментарий от anonymous

Третья - для затравки, небольшое Lisp-шоу, необязательно там досконально всё понимать.

Зачем такая клоунада нужна? Без них в лиспе никак? Да вот, в ANSI CL, PAIP и AMOP нету клоунады, и вроде норм.

ANSI Common Lisp, Common Lisp The Language - справочники, краткий и подробный.

CLTL - справочник, а вот «ansi common lisp» - учебник. и нифига не краткая. и с заданиями лучше чем в PCL.

Это был я, и я говорил про «простенькую СУБД», ту что в главе. :)

Бладж, если ты реально думаешь, что описанная в третьей главе чухашка имеет что-то общее с СУБД - то ты конченный клоун.

anonymous
()
Ответ на: комментарий от anonymous

дай-ка угадаю: ты тот самый анон, который глубоко уверен в том, что «надо запрыгнуть в отрасль обработки больших объемов данных пока не поздно» и при этом, думает что clojure и scala — единственные годные для этого инструменты? даже не знаю в какую палату тебя направить, клоунидзе!

anonymous
()
Ответ на: комментарий от anonymous

Бладж, если ты реально думаешь, что описанная в третьей главе чухашка имеет что-то общее с СУБД - то ты конченный клоун.

Ну не «чухашкой» же её называть. Ну ладно-ладно, расскажи нам про Oracle, так и быть.

anonymous
()
Ответ на: комментарий от anonymous

На самом деле нужны только Clojure и Scala

Кложа после CL за пару дней осваивается.

А так да, у тебя, чувак, культ карго - лечись.

anonymous
()
Ответ на: комментарий от anonymous

Ну не «чухашкой» же её называть.

Chapter 3. Practical: A Simple Chuhashka.
Вроде лучше так, чем называть (list :a 1 :b 2 :c 3) базой данных.

anonymous
()
Ответ на: комментарий от anonymous

Да видел я Land of Lisp. Понятно, что у книги есть определенный коммерческий успех, но зачем такое инженеру — ума не приложу.

Practical Common Lisp — не клоунада, но многие вещи мне там не понравились, к примеру, структура книги, а чем я уже сказал. Еще всякие бредни вроде «The Story of Mac: A Just-So Story», тоже нафиг можно было бы выкинуть оттуда.

Я лишь говорю, что не понимаю всеобщую мастурбацию именно на эту книгу, когда есть варианты получше: ANSI Common Lisp + On Lisp для введения, потом AMOP, а потом практика-практика-практика.

anonymous
()
Ответ на: комментарий от anonymous

не нужны. clojure - какой-то извращённый лисп. куча синтаксического сахара, типа квадратных и фигурных скобок. в чём приемущество? якобы кроссплатформенность? да sbcl поддерживает больше архитектур, чем jvm. а по скорости, код, скомпиленный sbcl не медленнее явы (а обычно быстрее). библиотеки? для CL написано не меньше.

а scala - какая-то неудачная попытка сделать нормальный язык для jvm. синтаксис там просто ужасный

memnek
() автор топика
Ответ на: комментарий от memnek

мнение профи, сразу видно, особенно аргументация богата на изящество

anonymous
()
Ответ на: комментарий от memnek

библиотеки? для CL написано не меньше.

Чем для JVM? Да ты шутишь.

korvin_ ★★★★★
()
Ответ на: комментарий от memnek

sbcl поддерживает больше архитектур, чем jvm.
код, скомпиленный sbcl не медленнее явы (а обычно быстрее).
библиотеки? для CL написано не меньше.

Это всё ложь.

archimag ★★★
()
Ответ на: комментарий от archimag

1) если не брать в расчёт jmee и android, то платформ меньше (java для bsd тут я не вижу

2) судя по моим замерам, lisp быстрее

3) возможно. но какой библиотеки не хватает для лиспа, но которая есть для java (имеется в виду не java и lisp-специфичные)?

memnek
() автор топика
Ответ на: комментарий от memnek

Покажи использование CL в продакшене. Для Clojure и Scala есть отдельные страницы с именами крупных компаний, которые используют эти языки. А где CL? И преимущество обоих (не в последнюю очередь) в простом написании многопоточных приложений. И одним из бонусов является наличие огромного количества библиотек и фреймворков для платформы Java.

anonymous
()
Ответ на: комментарий от anonymous

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

> в простом написании многопоточных приложений
вот тут скалка то и не очень как раз. так что не приемущество. ну а на счёт библиотек, назови не java-специфичную любу, которой нет для CL.

memnek
() автор топика
Ответ на: комментарий от anonymous

abcl (cl на java) сейчас развивается... я даже на днях в slime запустил. работает.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.