Как оценить код Common Lisp в буферах без слизи?

Я хотел бы иметь возможность получить мой SBCL 1.4.5 (Linux x86_64) Emacs 'inferior-lisp-process' для оценки S-выражения (sexp) в некотором буфере Emacs, который не является буфером 'слизи' - у меня есть последний quicklisp и slime-2.20.

Я думал, что это та же проблема, что и в: Как запустить код Common Lisp со Slime в Emacs Lisp, но это не так - моя проблема в том, что когда я пытаюсь запустить slime-eval или любой слайм, запускаемый в методе inferior-lisp-process, ВСЕ символы похоже, ищут ТОЛЬКО в пространстве имен SWANK-IO-PACKAGE:

 In my Emacs '*scratch*' buffer:

    (slime-eval '(symbolp '+) "CL-USER")

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

   The function SWANK-IO-PACKAGE::SYMBOLP is undefined.
   [Condition of type UNDEFINED-FUNCTION]

   Restarts:
   0: [CONTINUE] Retry calling SWANK-IO-PACKAGE::SYMBOLP.
   1: [USE-VALUE] Call specified function.
   2: [RETURN-VALUE] Return specified values.
   3: [RETURN-NOTHING] Return zero values.
   4: [*ABORT] Return to SLIME's top level.
   5: [ABORT] abort thread (#<THREAD "worker" RUNNING {100262C8E3}>)

   Backtrace:
   0: ("undefined function" SWANK-IO-PACKAGE::+)
   1: (SB-INT:SIMPLE-EVAL-IN-LEXENV \
   (SWANK-IO-PACKAGE::SYMBOLP (QUOTE SWANK-IO-PACKAGE::+)) \
    #<NULL-LEXENV>)
   2: (EVAL (SWANK-IO-PACKAGE::SYMBOLP (QUOTE SWANK-IO-PACKAGE::+)))

Не имеет значения, делаю ли я:

    (slime-eval '(symbolp :+) "CL-USER")

OR

    (slime-eval '(symbolp '+))

Я по-прежнему получаю ту же ошибку, потому что '+ и: + всегда ищутся только в пространстве имен SWANK-IO-PACKAGE.

Я нашел это, просто попытавшись запустить свой первый тест:

     (slime-eval '(+ 2 2) "CL-USER")

который печатает в выходном буфере еще одну обратную трассировку

     The function SWANK-IO-PACKAGE::+ is undefined.
     [Condition of type UNDEFINED-FUNCTION]

Я попробовал фрагмент кода из вопроса № 22456086:

    (require 'slime)
    (defun slrepl (str)
     "Eval STR as Common Lisp code."
    (unless (slime-current-connection)
      (let ((wnd (current-window-configuration)))
        (slime)
        (while (not (and (slime-current-connection)
                   (get-buffer-window (slime-output-buffer))))
        (sit-for 0.2))
    (set-window-configuration wnd)))
    (let (deactivate-mark)
    (cadr (slime-eval `(swank:eval-and-grab-output ,str)))))

Так поступаем:

    (slrepl '(symbol-function '+))^X^E

Тем не менее приводит к:

    The function SWANK-IO-PACKAGE::SYMBOL-FUNCTION is undefined.
    [Condition of type UNDEFINED-FUNCTION]

Доступ к пространству имен SB_INT по умолчанию, похоже, запрещен.

Как включить его в таких случаях?

Я хотел бы иметь возможность отправлять формы и читать результаты одного и того же emacs inferior-lisp-process (sbcl) из любого буфера, а не только из буфера slime repl sbcl. Есть какой-либо способ сделать это?

Очевидно, я могу написать функцию Emacs Lisp, чтобы переключиться на буфер повторного слайма и выполнить оценку в этом буфере. Конечно, все приведенные выше примеры, например. (eval '(symbolp' +)), отлично работают в буфере slime-repl. Я полагаю, что нет никакого способа переключиться на буфер замены слизи?

Это может прояснить:

В "царапине":

     (slime-eval '(SB-INT:symbolp 'SB-INT:+) "CL-USER")^X^E

В буфере вывода слизи:

    Invalid protocol message:
    The symbol "SYMBOLP" is not external in the SB-INT package.

            Line: 1, Column: 26, File-Position: 26

            Stream: #<SB-IMPL::STRING-INPUT-STREAM {1002A1CD63}>

    (:emacs-rex (SB-INT:symbolp (quote SB-INT:+)) "CL-USER" t 78)

Итак, в буфере slime-repl я могу:

    CL-USER> (PROGN (IN-PACKAGE "COMMON-LISP-USER") (+ 2 2))
    4
    CL-USER> (PROGN (IN-PACKAGE "SB-IMPL") (symbol-function '+))
    #<FUNCTION +>
    CL-USER> (PROGN (IN-PACKAGE "SB-IMPL") (symbol-function '+))
    #<FUNCTION +>
    SB-IMPL> (PROGN (IN-PACKAGE "SB-INT") (symbol-function '+))
    #<FUNCTION +>

Но если я попытаюсь запустить ту же функцию slime-eval в любом другом буфере, например. 'царапина':

    (slime-eval '(PROGN (COMMON-LISP-USER:IN-PACKAGE "COMMON-LISP-USER") 
                        (symbol-function '+)) :COMMON-LISP-USER)

    Invalid protocol message:
    The symbol "IN-PACKAGE" is not external in the 
    COMMON-LISP-USER package.

    Line: 1, Column: 46, File-Position: 46

Я пробовал ВСЕ возможные имена ПАКЕТОВ, перечисленные выше в slime-eval, с теми же результатами. То же самое происходит независимо от того, использую ли я фрагмент кода slrepl или просто slime-eval - стандартные символы синтаксиса Lisp недоступны. Мне нужно загрузить таблицу синтаксиса lisp или что-то в этом роде?

RE: могу ли я переключиться на буфер реплики слизи и сделать это? : НЕТ ! :

    (require 'slime)
    (let ((slbuf (get-buffer "*slime-repl sbcl*")))
     (if (eq nil slbuf)
      (error "please start slime (M-x slime)")
      (progn (set-buffer slbuf)(slime-eval '(+ 2 2) "COMMON-LISP-USER"))
     )
    )^X^E

Тем не менее приводит к:

    The function SWANK-IO-PACKAGE::+ is undefined.
    [Condition of type UNDEFINED-FUNCTION]

Я ржавый / вернувшийся пользователь LISP и новичок в SBCL и слизи. Я действительно хотел бы интегрировать прекрасные средства редактирования и управления файлами Emacs и взаимодействия с внешними инструментами CL XML и генерации и анализа HTML. Но для начала я бы хотел разобраться в корне этой проблемы ...


person JVD    schedule 25.03.2018    source источник
comment
Глядя на исходный код, вы могли обнаружить ошибку. Сообщения всегда читаются в swank-io-package, то есть (emacs-rex (swank-io-package::symbolp swank-io-package::+) "CL-USER")), а затем внутренняя форма передается eval-for-emacs, пока пакет связывается, но в этот момент символы уже интернированы в swank -io-пакет. Это отличается от подхода C-x C-e, который примерно запускает (slime-eval-print "(symbolp +)"). Я могу исследовать немного дальше, прежде чем пытаться дать окончательный ответ (но не сейчас ...)   -  person coredump    schedule 25.03.2018


Ответы (2)


Общие символы Lisp, такие как + и symbolp, находятся в пакете COMMON-LISP. Краткое название CL. Эти символы обычно не экспортируются из пакета CL-USER. Таким образом, на symbolp можно ссылаться как на cl:symbolp. Эти символы доступны в пакете CL-USER, но не экспортируются оттуда. Таким образом, вы также можете ссылаться на cl:symbolp как на cl-user::symbolp -> обратите внимание на два двоеточия.

ВЫЗОВ IN-PACKAGE в форме не влияет на саму форму, поскольку форма уже прочитана. Хотя он имеет эффект, вызывающий функции чтения или такие функции, как find-symbol.

CL-USER 5 > (defpackage "FOO" (:use))
#<The FOO package, 0/16 internal, 0/16 external>

CL-USER 6 > (progn (in-package "FOO")
              (list 'bar (read-from-string "BAR")))
(COMMON-LISP-USER::BAR BAR)    ; we now print from package "FOO"

Использование SLIME-EVAL в Emacs Lisp

Лучше всего использовать его с формой, которая читает выражение на стороне Common Lisp и не задействует читатель / принтер Emacs Lisp:

ELISP> (slime-eval '(cl:eval (cl:read-from-string "(+ 1 2)")) "CL-USER")
3 (#o3, #x3, ?\C-c)
ELISP> (slime-eval '(cl:eval (cl:read-from-string "'foo")) "CL-USER")
common-lisp-user::foo

Но здесь вы видите, что результат возвращается в Emacs Lisp через программу чтения Emacs Lisp, где пакетов не существует.

Таким образом, SLIME-EVAL не имеет смысла как простой интерфейс удаленного выполнения ...

person Rainer Joswig    schedule 25.03.2018
comment
Ага! да, вот и все! Предварительное ожидание cl: для всех символов действительно работает! - person JVD; 25.03.2018
comment
@JVD: посмотрите мою вторую часть ответа на очередной «взлом» - person Rainer Joswig; 25.03.2018

Теперь это работает! Спасибо !

    (require 'slime)
    (defun CL$ (str)
      (let ((slbuf (get-buffer "*slime-repl sbcl*")))
        (if (eq nil slbuf)
            (error "Please start slime (M-x slime).")
            (progn
             (set-buffer slbuf)
             (slime-eval str "CL")
            )
         )
      )
   )
   (CL$ '(cl:+ 2 2))
   => 4

Но я не совсем понимаю, почему я должен добавлять все символы с помощью CL или почему это все еще не работает:

    (slime-eval '(+ 2 2) "CL")

но это делает: (slime-eval '(cl: + 2 2) "CL")

Я думал, третий параметр должен быть включен в текущий пакет? Так зачем мне добавлять cl к каждому символу? Но спасибо за помощь и отличный слайм + sbcl.

person JVD    schedule 25.03.2018
comment
Обратите внимание, что это тоже взлом, поскольку Emacs Lisp не имеет концепции пакетов. Итак, cl:+ в Emacs Lisp означает символ с именем cl:+. Если вы вызываете SLIME-EVAL с формой, эта форма уже читается и затем печатается как форма Emacs Lisp, а не как форма Common Lisp. Таким образом, чтобы на самом деле выполнить код CL, вам может потребоваться что-то, что отправляет строку. - person Rainer Joswig; 25.03.2018