LINUX.ORG.RU

Вопрос начинающего лиспера (elisp)


0

0

Никогда бы не подумал, что разные реализации лисп так сильно отличаются. К примеру задумал я следующее: сделать функцию для jabber.el, чтобы status-message рандомно выбирался из текстового файла - базы статусов. Накодил следующее:

(defun jabber-set-random-status ()
  "Set random jabber status from database."
  (interactive)
  (setf db-status-array (make-array 5 :fill-pointer 0 :adjustable t :element-type 'string))
  (let ((db-status-file (open "~/.emacs-jabber-status" :if-does-not-exist nil)))
    (when db-status-file
      (loop for db-status-line = (read-line db-status-file nil)
	    while db-status-line do (vector-push-extend db-status-line db-status-array))
      (close db-status-file)))
  (setq *jabber-current-show* "xa" *jabber-current-status* (elt db-status-array (random (- (length db-status-array) 1))))
  (jabber-send-current-presence))

Когда тестирую в обычном clisp - все работает. В elisp же матерится на open, make-array и т.д. Сильно не бейте, но подскажите - как реализовать это на elisp? А именно: прочитать текстовый файл в массив и присвоить значение рандомного элемента этого массива - переменной.

★★★★★

прибавлю немного жару:

from random import randint
def jabber-set-random-status():
    with open("~/.emacs-jabber-status") as ifile:
        lines = ifile.readlines()
        return lines[randint(0, len(lines))]
val-amart ★★★★★
()

> Когда тестирую в обычном clisp - все работает. В elisp же матерится на open, make-array и т.д. Сильно не бейте, но подскажите - как реализовать это на elisp?

В Emacs есть пакет для совместимости с CL. Только название не помню :)

tailgunner ★★★★★
()

elisp != common lisp (как в случае clisp'а). читайте introduction to emacs lisp

ott ★★★★★
()
Ответ на: комментарий от val-amart

да ну )) я решил вопрос проще. у меня теперь база статусов - это lisp-файл:

(setf db-status-array (list 
"статус1"
"статус2"
...
"статусN"
))

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

да потому что начинающий :( и потому что setf - универсально, как написано в PCL.

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

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

>«статус1» «статус2» ... «статусN»

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

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

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

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

по мере возможности свяжусь :) дело оч. полезное.

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

>потому что setf - универсально, как написано в PCL.
SETF это оператор присваивания.
Присваивание без объявления переменной это BASIC-стайл.

Love5an
()
Ответ на: комментарий от val-amart

Вместо randint лучше использовать choice из того же модуля. В таком случае последняя строка будет такой:

return choice(lines)

По поводу лиспа. Какой вариант лучше всего использовать для обучения? Сейчас понаставлял кучу всего, но чтобы не натыкаться на грабли желательно бы знать заранее.

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

>Присваивание без объявления переменной это BASIC-стайл.
Кривая аналогия. SETF в лиспе не то же самое, что = в basic. Так тоже часто пишут.

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

Если чего-то не забыл с курса ФП, в лиспе это один из основных примитивов.

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

>Присваивание без объявления переменной это BASIC-стайл.
Как ты представляешь «объявления переменной» в лиспе? Это же не C++.

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

>Какой вариант лучше всего использовать для обучения?
Вообще, сначала надо бы выбрать конкретный диалект.
Они друг от друга очень, очень сильно отличаются.

Если вопрос о реализации - в случае с CL - clisp довольно нуб-френдли, у него хорошая локализация, несколько встроенных модулей для базовых вещей, не включенных в стандарт, например регексы, биндинги к zlib и т.п.(хотя, конечно, есть cl-ppcre, а zlib можно через cffi без особых сложностей дергать, практика показывает, что новичкам не так уж просто с asdf освоиться, особенно на винде, например); хотя можно и сразу SBCL ставить, там тоже все довольно понятно, особенно если за пределы стандарта не выходить.
Если говорить о схеме - PLT scheme, наверное, самая вменяемая реализация.
Ну а Emacs Lisp, например, довольно легко осваивается после CL.

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

setq(то, т.е., во что setf раскрыается) без предшествующего defvar или defparameter(ну или let) это мало того, что плохой стиль, это еще и UB, строго говоря. Где-то в стандарте описано, что setq на необъявленную переменную компилятор волен трактовать как ему угодно; в том плане, что он эту переменную может сделать глобально динамической; а может и не сделать.

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

насколько я понимаю, ABCL не предоставляет автоматического распараллеливания кода?

насчет тормозов - особо их не вижу, особенно если это дело сначала откомпилировать в .class

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

UB это Undefined Behavior.

Почему же тогда в исходниках лиспа SETQ регулярно используется для этого? Пруфлинк - http://shepik.pp.ru/lisp/mulisp/COMMON.LSP

Каких нахер исходниках лиспа?
Это какая-то непонятная хрень, 89 года прошлого века выпуском. ANSI стандарт CL - 1994 год. Судя по названию, диалект там - mulisp. Как там хендлилось присваивание я понятия не имею. И еще меньшее понятие я имею о том, как это относится к современным диалектам и реализациям.

Да и вообще, там даже название языка неправильно написано.

Common LISP

LISP


facepalm.jpg

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

>Это какая-то непонятная хрень, 89 года прошлого века выпуском. ANSI стандарт CL - 1994 год.
Но с тех пор же в основах лиспа поменялось не так много? Если не считать либ и расширений. По крайней мере то, что было в справочнике финнов, до сих пор работает.

Да и вообще, там даже название языка неправильно написано.

Common LISP


Это мелочи.

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

>в основах лиспа
Что такое основы лиспа?

в справочнике финнов

Дерьмовая это книженция.

до сих пор работает.

Удивительно, но в CL есть места, которые и на LISP 1.5 работали.

Это мелочи.

Нет, не мелочи. Это, как минимум, невежественность, а она раздражает.

И, вообще, я не понимаю - что ты пытаешься оспорить? Что присваивание без предварительной декларации переменной это плохой стиль? Что это UB? Или, может, что писать «LISP», подразумевая современные диалекты или все это семейство языков, некрасиво?

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

>Дерьмовая это книженция.
Обосновать есть чем?

И, вообще, я не понимаю - что ты пытаешься оспорить? Что присваивание без предварительной декларации переменной это плохой стиль?

Что не стоит переносить особенности Common Lisp на все лиспы.

И попутно пытаюсь разобратся с CL. Учить с нуля не хочется, хочу узнать, в чем он отличается от того, к чему привык.

И не стоит зря хаять mulisp, он очень даже неплох. Лисп, заточенный для написания математического софта.

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

>Нет, не мелочи. Это, как минимум, невежественность, а она раздражает.
Да брось, наверное, тогда так писали.

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

>Обосновать есть чем?
Это довольно сложно конкретизировать, не скатываясь к банальным оскорблениям, но, возможно, как-нибудь позже.

Что не стоит переносить особенности Common Lisp на все лиспы.

«Все лиспы» это, фактически, CL, схема, и вон, возможно, clojure. Но последние два императивный быдлокод в стиле бейсика одобряют еще меньше, чем CL.

Учить с нуля не хочется, хочу узнать, в чем он отличается от того, к чему привык.

CL даже при переходе со схемы, к примеру, приходится учить практически с нуля. Не говоря уже о других языках. И к чему, кстати, привык?

Учить с нуля не хочется, хочу узнать, в чем он отличается от того, к чему привык.

Я не то, чтобы его хаю, но он по-моему, сдох уже два десятилетия как. И что же там особенно полезного для математического софта?

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

>Это довольно сложно конкретизировать, не скатываясь к банальным оскорблениям, но, возможно, как-нибудь позже.
Обычная отмазка.

CL даже при переходе со схемы, к примеру, приходится учить практически с нуля. Не говоря уже о других языках. И к чему, кстати, привык?

Паскаль, Си, ассемблер и мулисп.

Я не то, чтобы его хаю, но он по-моему, сдох уже два десятилетия как.

В учебе используется себе и дальше. Смысла менять нет.

И что же там особенно полезного для математического софта?

Был сильно быстрее других лиспов, ел меньше памяти.

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

Обычная отмазка.

Нет, действительно сложно. Примерно как «почему образование в России - говно». Ну, т.е. вроде интуитивно понятно, но разбираться в деталях - долго.

Паскаль, Си, ассемблер и мулисп.

Ну, от первых трех CL отличается настолько, что знания оттуда принесенные вряд ли как-то помогут(кроме некоторых вопросов оптимизации, но это довольно advanced topic, т.к. в таком высокоуровневом языке, как CL, этот вопрос не так прозрачно решается, как, например, в сишке, и уж точно implementation dependent). Но, вцелом, ничего сложного в нем нет, страхи об «учить с нуля» не совсем понятны.

В учебе используется себе и дальше. Смысла менять нет.

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

Был сильно быстрее других лиспов, ел меньше памяти.

Ну, не знаю, может в 89'м и был. Хотя и то, вряд ли. Там уже были крутые компиляторы того же Maclisp, и это не говоря даже о лисп-машинах.

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

; disassembly for TEST
; 24C56BBA:       31C0             XOR EAX, EAX               ; no-arg-parsing entry point
;      BBC:       EB39             JMP L1
;      BBE: L0:   DDD8             FSTPD FR0
;      BC0:       D94201           FLD [EDX+1]
;      BC3:       DDD9             FSTPD FR1
;      BC5:       D94701           FLD [EDI+1]
;      BC8:       D9C9             FXCH FR1
;      BCA:       D8C1             FADDD FR1
;      BCC:       9B               WAIT
;      BCD:       D95701           FST [EDI+1]
;      BD0:       DDD8             FSTPD FR0
;      BD2:       D94205           FLD [EDX+5]
;      BD5:       DDD9             FSTPD FR1
;      BD7:       D94705           FLD [EDI+5]
;      BDA:       D9C9             FXCH FR1
;      BDC:       D8C1             FADDD FR1
;      BDE:       9B               WAIT
;      BDF:       D95705           FST [EDI+5]
;      BE2:       DDD8             FSTPD FR0
;      BE4:       D94209           FLD [EDX+9]
;      BE7:       DDD9             FSTPD FR1
;      BE9:       D94709           FLD [EDI+9]
;      BEC:       D9C9             FXCH FR1
;      BEE:       D8C1             FADDD FR1
;      BF0:       9B               WAIT
;      BF1:       D95709           FST [EDI+9]
;      BF4:       83C004           ADD EAX, 4
;      BF7: L1:   39F0             CMP EAX, ESI
;      BF9:       7CC3             JL L0
;      BFB:       BA0B001022       MOV EDX, 571473931
;      C00:       8BE5             MOV ESP, EBP
;      C02:       F8               CLC
;      C03:       5D               POP EBP
;      C04:       C3               RET
Практически ничего лишнего.

Love5an
()

>Вопрос начинающего лиспера

Дядька Грэм завещал лисперам начинать и заканчивать питоном. Аминь.

разные реализации лисп так сильно отличаются

Ты удивишься, сколько всего не входит в hyperspec: процессы, потоки, сокеты — словом, куча всего. Правда отсуствие make-array указывает на неполноценность elisp.

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

Вообще говоря, присваивание необъявленной (свободной) переменной в CL очень даже определено — это банальное связывание символа и значения. Я даже не знаю, как по другому в CL правильно присвоить значение глобальной статической переменной.

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

связывание символа и значения это (set 'symbol value) или (setf (symbol-value 'symbol) value)
переменная и слот-значение у символа это разные вещи.

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

>Нахера в 2009-м году нужны инструкции SSE?
Когда, во-первых, на PPC, SPARC, DEC Alpha и MIPS тоже будет SSE, и во-вторых, GCC научиться автоматической векторизации, тогда и будешь умничать.

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

>Вообще говоря, присваивание необъявленной (свободной) переменной в CL очень даже определено — это банальное связывание символа и значения. Я даже не знаю, как по другому в CL правильно присвоить значение глобальной статической переменной.

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

Нахера в 2009-м году нужны инструкции SSE?

http://github.com/nikodemus/sb-cga — вот тут пример того, как научить SBCL юзать SSE для сложения векторов.

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

>насчет тормозов - особо их не вижу, особенно если это дело сначала откомпилировать в .class

Особых и нет, если везде задавать типы вручную (ну или отслеживать где типы неправильно выводятся /* а они выводятся? */ и там их конкретизировать - что, по-моему, ещё сложнее) и если массово не использовать массивы простых типов. Ну и если чрезмерно использовать «функциональные фенечки» - это тоже скорости (выполнения программы а не написания кода) не прибавляет. И да - по сравнению с «голой жабкой».

Можно посмотреть в форуме clojure на googlegroups.com - там периодически поднимались топики по поводу скорости кода. В отдельных случаях «красивый компактный функциональный код» начинает тормозить на пару порядков (опять-же - все сравнения с «жабкой»).

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

А в чем разница между глобальной статической переменной и значением символа, если и то и другое использует set для присваивания?

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

Насколько я знаю, в CL всегда определяется глобальная лексичeская переменная в таких случаях. Правда, в спецификации я ничего на эту тему не нашел, могу сослаться только на финнов.

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

А в каких реализациях именно CL в таких случаях определяется динамическая переменная? И как в них ведет себя defvar? Как в таких реализациях полагается определять глобальные лексические переменные?

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