LINUX.ORG.RU

common lisp, потоки, slime


0

0

Добрый вечер. Помогите разобраться в проблеме - при вызове функции, которая читает из одного потока и пишет в другой вылетает slime (Lisp connection closed unexpectedly: connection broken by remote peer). Вот ф-ция -


(defun write-mp3 (name from to)
(format t "~&writing mp3 from ~a to ~a with name ~a~%" from to name)
(let* ((to (merge-pathnames to name))
(in (open from :element-type '(unsigned-byte 8)
:if-does-not-exist :error))
(out (open to :direction :output
:element-type '(unsigned-byte 8) :if-exists :overwrite)))
(when (and in out)
(loop for i = (read-byte in nil) when i
do (print i) else
do (return)))
(and (close in) (close out))))


Для проверки(работает + чтение не стад преводить, но всё норм) -
(defun foo-c ()
(let ((out (open "music/exam++.mp3" :direction :output
:element-type '(unsigned-byte 8)
:if-exists :overwrite)))
(write-byte 128 out)
(close out)))

Заранее спасибо :)

Re: common lisp, потоки, slime

Не совсем понятно, что функция делает вообще. Читать то она читает из in, а пишет почему на stdout? И в чем сакральный смысл параметров? В том смысле, что name и to нельзя совместить? Тут просто, если файл не существовал, и в if-exists стоит :overwrite, а :if-does-not-exist не задан, open сигналит ошибку. Почему у тебя это отключает рантайм от емакса, правда, не совсем понятно.

Для работы с файлами, кстати, пользуйся with-open-file, и про open и close забудь. И, это самое, если тебе файл не надо именно частично перезаписать, а надо перезаписать полностью, ставь не :overwrite, а :supersede.

Вот исправленный вариант, который ошибок не выкидывает:

(defun write-mp3 (name from to)
  (format t "~&writing mp3 from ~a to ~a with name ~a~%" from to name)
  (with-open-file (in from :element-type #1='(unsigned-byte 8))
    (with-open-file (out (merge-pathnames to name)
                         :direction :output
                         :element-type #1#
                         :if-exists :overwrite
                         :if-does-not-exist :create)
      (loop for b = (read-byte in nil)
            while b do (write-byte b out)))))
guest-3484-2009 ()
Ответ на: Re: common lisp, потоки, slime от guest-3484-2009

Re: common lisp, потоки, slime

смысл ф-ции в том, чтобы записать файл из одного места в другое :). имя выбирается в другой ф-ции:

 
(defun add-track (from to db)
  (let ((name (vector-pop (slot-value db 'unusing))))
    (write-mp3 name from to)
    (vector-push-extend name (slot-value db 'using))))
область имён ограничена, т.к. пишется это дело на айпод, который не читает 'не официально' залитые файлы)

Про with-open-file знаю, сначала было примерно так и сделано, потом захотелось потестить разные варианты и вышло что создание вручную 2 отдельных потоков, создание echo-потока либо two-way потока обрывает рантайм. вот только интересно почему и что означает, и какие есть, и где посмотреть это: (setq swank:*communication-style* :fd-handler)

про #1='() -> #1# спасибо, удобный сахар))

pseudo-cat ★★★ ()
Ответ на: Re: common lisp, потоки, slime от pseudo-cat

Re: common lisp, потоки, slime

Теперь стало ясно почему такое происходило. Добавил в свою старую ф-цию :if-does-not-exist :create и всё норм заработало:

(defun write-mp3 (name from to) 
  (format t "~&writing mp3 from ~a to ~a with name ~a~%" from to name)
  (let* ((in-out (make-echo-stream 
        (open from :element-type #1='(unsigned-byte 8))
        (open (merge-pathnames to name)
         :direction :output
         :element-type #1#
         :if-exists :overwrite
         :if-does-not-exist :create))))
    (loop for b = (read-byte in-out nil) 
       unless b do (return))))
if-does-not-exist---one of :error, :create, or nil. [b]The default is :error[/b]
значит вызов ошибки приводит к вылету, видимо)

pseudo-cat ★★★ ()
Ответ на: Re: common lisp, потоки, slime от pseudo-cat

Re: common lisp, потоки, slime

Ничего не понял про потоки.
with-open-file это open, и close, завернутый в unwind-protect. Настоятельно рекомендую использовать этот макрос для работы с файлами.

guest-3484-2009 ()
Ответ на: Re: common lisp, потоки, slime от guest-3484-2009

Re: common lisp, потоки, slime

ну да, но не всегда же он подходит. К примеру если нужно передавать поток по цепочке ф-ций.
echo-stream и two-way-stream по-моему удобны, если не забывать их закрывать (или завернуть в макросе в протэкт).

pseudo-cat ★★★ ()
Ответ на: Re: common lisp, потоки, slime от guest-3484-2009

Re: common lisp, потоки, slime

а ну да, если все ф-ции вызывать внутри этой конструкции, то не как

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