unix

INPUT-STREAM-P, STREAM-ELEMENT-TYPE... vs. CLOSE

Обнаружил, что SBCL после закрытия stream'а теряет все возможности интроспекции на нём: INPUT-STREAM-P, OUTPUT-STREAM-P => NIL, остальное ругается на попытку ввода-вывода с закрытым stream'ом (например, STREAM-ELEMENT-TYPE). Это категорически не кажется правильной вещью. Но прежде, чем бросаться репортить и фиксить, хочу посоветоваться с сообществом: правильно ли я понимаю, что вышеописанное не только «нехорошо», но и non-conforming? Я считаю, что это подтверждается тем, что про OPEN-STREAM-P написано Affected by: Close, а про всю интроспекцию -- Affected by: None.

Clozure CL, CLISP, ECL не делают такой бяки. У кого есть под рукой другие реализации -- как с этим делом принято?

Extended loop: for .. while .. for

Никак не могу понять одной вещи про extended loop -- прямо мозги вытекают :(

Допускается ли стандартом использование termination test clauses (e.g. while) *между* for? Так, чтобы если условие завершения наступило, stepping от «нижних» for бы не выполнялся (у меня довольно часто многоэтажный loop построен так, что «нижние» for не способны сделать stepping без ошибки, если вовремя не вывалиться).

Если начать исследовать CLHS с того места, где расписан как-бы-BNF extended loop, кажется, что такого делать просто нельзя. Если закопаться внутрь, однако, попадаются (или, возможно, приглючиваются) намёки, что так делать можно. SBCL и CCL такое проглатывают и работают ожидаемым образом, но мне вспоминается печальный опыт с чем-то вроде ECL, который (если я правильно помню) потребовал подвинуть while вниз, а это уже потащило за собой переписывание всего подряд. В общем, совершенно нехарактерная для Common Lisp засада -- когда можно пользоваться нестандартным расширением несколько лет, и внезапно об этом узнать. Такая перспектива мне не нравится. (Взбрык ECL, опять же, совершенно не показатель -- дело было давно, он был моложе и глупее и вполне мог быть non-conforming в этом плане. Проверять заново не тянет: сейчас хочется выяснить, как оно *должно* быть, а тут такие проверки не помогут)

Ну и такой вопрос -- если я сделаю вместо WHILE какой-нибудь FOR () = (WHEN кирдык (LOOP-FINISH)) -- оно-то уж точно предотвратит stepping в последующих FOR? (тогда, с одной стороны, становится непонятно, на фига не разрешили там WHILE (если и вправду нельзя), но зато понятно, на что его менять, чтобы обойтись без революций).

(no subject)

Привет!
В общем вот какое дело:
emacs + slime + clisp + windows
пишет каракули при выводе кириллицы
я это лечу,
(set-process-coding-system (get-process "inferior-lisp") 'cp1251 'cp1251)
ну или хоткеем (просто первый вариант длиннее, ну вы понимаете)

А как это куда-нибудь вписать чтобы не приходилось этого делать вообще.
Потому, что если я явно указываю все параметры кодировок в .emacs, то он перестает автоматически распознавать и потом каракули из буфера обмена лезут и вообще.

проблема с parenscript

здравствуйте, уважаемые.
собираюсь я начать работу с parenscript, запускаю clisp, выполняю следующее:

(dolist (x '(:hunchentoot :cl-who :parenscript :cl-fad))
(asdf:oos 'asdf:load-op x))


пакеты грузятся нормально. особое внимание обращаю на parenscript:

; loading system definition from /usr/share/common-lisp/systems/parenscript.asd into #<PACKAGE ASDF0>
;; Loading file /usr/share/common-lisp/systems/parenscript.asd ...
; registering #<SYSTEM :PARENSCRIPT #x20CD1A6E> as PARENSCRIPT
WARNING: Модифицируется родовая функция #<STANDARD-GENERIC-FUNCTION PERFORM>, которая уже была вызвана.
; registering #<SYSTEM :PARENSCRIPT.TEST #x20CD921E> as PARENSCRIPT.TEST
;; Loaded file /usr/share/common-lisp/systems/parenscript.asd
;; Loading file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/package.fas ...
;; Loaded file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/package.fas
;; Loading file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/utils.fas ...
;; Loaded file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/utils.fas
;; Loading file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/defgenerics.fas ...
;; Loaded file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/defgenerics.fas
;; Loading file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/js.fas ...
;; Loaded file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/js.fas
;; Loading file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/js-html.fas ...
;; Loaded file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/js-html.fas
;; Loading file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/css.fas ...
;; Loaded file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/css.fas
;; Loading file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/compile-js.fas ...
;; Loaded file /var/cache/common-lisp-controller/1000/clisp/parenscript/src/compile-js.fas
0 ошибок, 0 предупреждений
0 ошибок, 0 предупреждений
NIL


затем ввожу следующее:
(defpackage "PS-TUTORIAL"
(:use "COMMON-LISP" "HUNCHENTOOT" "CL-WHO" "PARENSCRIPT" "CL-FAD"))


и получаю сообщение об ошибке:
*** - SYSTEM::%FIND-PACKAGE: Нет пакетов с именем "PARENSCRIPT".
Имеются следующие варианты продолжения:
USE-VALUE :R1 Вы можете ввести новое значение для использования.
ABORT :R2 Abort main loop


в sbcl -- то же самое.
как быть?

Синтаксические сладости

Кросс-пост: http://lisper.ru/forum/thread/134

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

Вот, например, if с bind'ингом и it'ом:
(defun iif-lform-gather (lst)
  (cond
    ((null lst) nil)
    ((listp (car lst))
       (if (and (keywordp (caar lst)) (eq (caar lst) :bind))
           (prog1 (cons (cons (cadar lst) (cddar lst))
                        (iif-lform-gather (cdr lst)))
                  (setf (car lst) (caddar lst)))                  
           (nconc (iif-lform-gather (car lst))
                  (iif-lform-gather (cdr lst)))))
    (t (iif-lform-gather (cdr lst)))))
         
         
(defmacro iif (arg tform nform)
  `(let ((it ,arg) ,@(iif-lform-gather arg))
     (if it ,tform ,nform)))


Примеры использования:
(iif (< (:bind xx (+ 12 x)) 34) (1+ xx) (-1 xx))
(iif some-variable (cons 'a it) '(a))
R
  • love5an

(no subject)

А оговаривается ли где-то в стандарте порядок раскрытия макросов?
Репост отсюда вот:
http://lisper.ru/forum/thread/126

Дело в том, что ради интереса попробовал реализовать вот такую штуку
(eval-when (:compile-toplevel :load-toplevel :execute) 
  (defvar *cleaners* '())) 
 
(defmacro with-cleaners ((&rest resources) &body body) 
  "Each resource is of form (name value)" 
  (setf *cleaners* '()) 
  `(let ,resources 
     (macrolet ((add-cleaner (&body cleaner-body) 
                  (push cleaner-body *cleaners*) 
                  nil) 
                (invoke-cleaners () 
                  `(progn ,@(reduce #'nconc *cleaners*) 
                          ,(setf *cleaners* '())))) 
       (unwind-protect 
         (progn ,@body) 
         (invoke-cleaners))))) 

и обнаружил, что оно не везде работает так, как хотелось(должно вычислять все cleaner формы в конце области видимости)(оно полагается на порядок раскрытия слева-направо; соответственно, например, Clozure CL оно работает, а в SBCL, например - нет(и это только в случае с unwind-protect, как я понял. Если вместо него обычная функция, порядок - слева направо))
  • zhengxi

Как интернить не только строки ?

Хочется иметь функцию, которая бы работала как string->symbol, но для всех типов данных.
То есть, если x и y equal?-равны (по значению), то (intern x) и (intern y) будут eq?-равны (по ссылке).

Зачем это надо?
Для того же, что и string->symbol: экономить память, если ожидается много одинаковых иммутабельных оьъектов и быстро их сравнивать (eq? вместо equal?)

Написал я такую функцию (PLT Scheme)
(define *internat* (make-weak-hash))

; not thread safe
(define (intern x [internat *internat*])
  (let ([e (hash-ref internat x #f)])
    (if e
        (ephemeron-value e)
        (let ([e (make-ephemeron x x)])
          (hash-set! internat x e)
          (ephemeron-value e)))))

(define (interned? x [internat *internat*])
  (let ([e (hash-ref internat x #f)])
    (if e
        (eq? x (ephemeron-value e))
        #f)))

; набор тестов тут: http://paste.lisp.org/display/90896


Хотя она делает что нужно, она мне очень не нравится.
Даже в таком упрощённом (не thread safe) варианте она сильно медленнее, чем string->symbol.

Как это можно сделать лучше ?
М.б. есть реализации Scheme (или CL), где string->symbol (или intern) уже работает для всех типов ?

UPD: это задача не про подсчёт хеш-суммы, и дальнейшей работой с хеш-суммой вместо объекта.

Это задача про удаление дубликатов иммутабельных объектов:
(define a "AAA")
(intern a) ; возвращает a
(define b "AAA")
(intern b) ; возвращает a

Должно быть true не только
(eq? (intern "AAA") (intern "AAA"))
но и
(equal? (intern "AAA") "AAA")
Мумбаса
  • tinedel

композиция

Доброе утро.
А есть в эхотаге композиция функций?
В варианте, например,

(funcall (composition #'reverse #'car #'1+) '(1 2 3 4)) -> 5

Нет, я её конечно сам написал для функций одного аргумента (мне больше не надо, а думать над тем как оно будет в общем виде было неохота), но вдруг она есть, а я её не нашел.

АПД: судя по ответам - в стандарт не входит. Реализована как минимум в виде функций metatilities:compose и alexandria:compose.

спасибо
genius
  • kmmbvnr

Пятничное

А можно ли сделать пакет по свойствам похожий на пакет keyword?


Так, чтобы получилось, что наш пакет содержит любой символ и значением любого символа из этого пакета было бы, скажем, строковое представление этого символа?

> (symbol-value (ourpackage:any_symbol))
"any_symbol"