Существует ли стандартный способ запуска внешней программы в Common Lisp?

В clisp работает следующий код:

(defun hit-history () (shell "tail ssqHitNum.txt"))

Однако в Clozure CL функция shell не поддерживается!


person z_axis    schedule 11.10.2011    source источник


Ответы (6)


Нет, стандартного способа нет, но есть библиотеки, предоставляющие эту функциональность для важных реализаций. Например, в Quicklisp есть тривиальная оболочка, которая предоставляет shell-command. (На самом деле я ее не тестировал, но она входит в число рекомендуемых библиотек на CLiki.) Также есть внешняя программа. Обновление: inferior-shell кажется предпочтительным в наши дни, как указывает Эвинс. в комментарии и его собственном ответе.

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

CCL имеет ccl:run-program, например:

CL-USER> (run-program "whoami" '() :output *standard-output*)
foobar
#<EXTERNAL-PROCESS (whoami)[NIL] (EXITED : 0) #xC695EA6>
person danlei    schedule 11.10.2011
comment
Обратите внимание, что вам не нужен Quicklisp для использования превосходной библиотеки trivial-shell. Кроме того, я не уверен в причинах предложения условных выражений времени чтения, поскольку это именно то, что делает тривиальная оболочка. (Вот почему такие библиотеки называются тривиальными-*.) - person Ken; 17.10.2011
comment
Кен, да, не нужно использовать Quicklisp, но это то, что обычно рекомендуется для установки библиотек Lisp в наши дни. Не стесняйтесь добавлять свой собственный ответ, объясняющий, как установить вручную. Я упомянул условия времени чтения, потому что OP может по какой-то причине не захотеть использовать библиотеку, и также полезно знать об этом, если, например, для подобных проблем не существует тривиального *. (И, конечно же, есть и другие способы использования условных выражений во время чтения, так что в любом случае полезно знать о них.) - person danlei; 18.10.2011
comment
trivial-shell устарел и заменен на inferior-shell, который просто использует uiop run-program (синхронизация). Для асинхронности см. launch-program uiop. - person Ehvince; 27.12.2016
comment
@Ehvince Ну, если вы думаете, что из-за этого мой ответ заслуживает отрицательного голоса, пусть будет так. Тем не менее, он по-прежнему правильно отвечает на фактический вопрос. - person danlei; 03.01.2017
comment
@daniel Я бы хотел, чтобы у новых ответов было больше голосов, но, возможно, отрицательный голос - это не решение, извините. Я отменил его (тем более, что вы отредактировали свой вопрос). - person Ehvince; 04.01.2017
comment
@Ehvince Понятно. Лично я отрицаю ответ только тогда, когда он действительно неправильный или очень плохого качества. Когда я предпочитаю другой ответ принятому, я обычно просто поддерживаю его и оставляю принятый в покое. Но я согласен, что есть проблема с изменениями языка или экосистемы, когда у вас есть устаревший ответ сверху, а лучшие ответы не видны. В любом случае, я рад, что вы оставили комментарий, чтобы сообщить мне, что происходит. Что я действительно ненавижу, так это отрицательные голоса, когда я понятия не имею, что кто-то считает неправильным в моем ответе. Также спасибо за отмену отрицательного голоса. - person danlei; 04.01.2017

Да, с UIOP, который должен быть включен во все современные реализации.

  • синхронные команды: uiop:run-program
  • асинхронные команды: uiop:launch-program

Так например

(uiop:run-program (list "firefox" "http:url") :output t)

or

(defparameter *shell* (uiop:launch-program "bash" :input :stream :output :stream))

где вы можете отправлять ввод и читать вывод.

Подробнее о них можно прочитать здесь: https://lispcookbook.github.io/cl-cookbook/os.html#running-external-programs

trivial-shell устарела и заменена на inferior-shell, которая внутренне использует переносимый uiop run-program (синхронно), поэтому мы можем использовать только это.

person Ehvince    schedule 26.12.2016

(defun dot->png (fname thunk)
   (with-open-file (*standard-output*
       fname
       :direction :output
       :if-exists :superseded)
     (funcall thunk))
   (ccl:run-program "dot" (list "-Tpng -O" fname))
)

я добиваюсь успеха в ccl (clozure), когда изучаю землю lisp p123

person lin yuansen    schedule 12.08.2012
comment
Это помогло мне, когда я читал тот же отрывок для Land of Lisp. Я использовал SBCL и должен был изменить последнюю строку на (sb-ext:run-program "/usr/bin/dot" (list "-Tpng" "-O" fname))) - person dpritch; 01.04.2018

Ниже показан пример вызова wget из common lisp:

https://diasp.eu/posts/1742240

Вот код:

(sb-ext:run-program "/usr/bin/wget" '("-O" "<path-to-output-file>" "<url-link>") :output *standard-output*) 
person baby-lisper    schedule 09.04.2014
comment
Пожалуйста, скопируйте соответствующие фрагменты кода в сам ответ, чтобы гниение ссылок не сделало ответ бесполезным. - person EWit; 10.04.2014

Взгляните на пакет inferior-shell.

(Получите его через всемогущего менеджера пакетов quicklisp.)

Это работает в интерпретаторе, если у вас есть интернет:

(require 'inferior-shell)
(inferior-shell:run/s '(curl icanhazip.com))
person sjas    schedule 28.04.2015

CL21 определяет простые методы:

(in-package :cl21-user)
(use-package :cl21.process)

Затем либо с помощью run-process, либо с помощью макроса чтения #`:

(run-process '("ls" "-l"))
;-> total 0
;   drwxrwxrwt    5 root         wheel   170 Nov  1 18:00 Shared
;   drwxr-xr-x+ 174 nitro_idiot  staff  5916 Mar  5 21:41 nitro_idiot
;=> #<PROCESS /bin/sh -c ls -l /Users (76468) EXITED 0>

or

#`ls -l /Users`
;=> "total 0
;   drwxrwxrwt    5 root         wheel   170 Nov  1 18:00 Shared
;   drwxr-xr-x+ 174 nitro_idiot  staff  5916 Mar  5 21:41 nitro_idiot
;   "
;   ""
;   0

В источнике показана реализация для SBCL и CCL.

person Ehvince    schedule 23.07.2017