哪种方法最容易扩展Lisp,只需在计算中进行少量修改?

哪种方法最容易扩展Lisp,只需在计算中进行少量修改?,lisp,common-lisp,racket,eval,dsl,Lisp,Common Lisp,Racket,Eval,Dsl,我想尝试扩展一些Lisp(Scheme、Racket、Clojure、any)来运行外部命令,如下所示: ; having (define foo ...) (define bar ...) ; on command (ls (foo bar) baz) ; this lisp should evaluate (foo bar) as usual, with result "foobar", then (ls foobar baz) ; here "ls" is not defined ; in

我想尝试扩展一些Lisp(Scheme、Racket、Clojure、any)来运行外部命令,如下所示:

; having
(define foo ...)
(define bar ...)
; on command
(ls (foo bar) baz)
; this lisp should evaluate (foo bar) as usual, with result "foobar", then
(ls foobar baz)
; here "ls" is not defined
; instead of rising "undefined identifier" exception
; it must look for "ls" command in the directories
; in the "PATH" environment variable
; and launch the first found "ls" command
; with strings "foobar" and "baz" on input
我只想无论如何运行它,而不进行从lisp的数据结构到字符串的正确转换,也不处理退出代码和
stdout/stderr
中的命令输出

我认为没有办法在正常环境中扩展它(比如一直捕获“未定义”的异常)。必须更改解释器本身的
eval
过程


哪种Lisp最好像这样扩展它,它是如何实现的?可能已经存在一个执行类似操作的项目了?

Common Lisp有一个标准错误系统,可用于实现该系统

在提供
使用值
存储值
的常见Lisp实现中,针对
未定义函数类型的错误重新启动

* (defun provide-a-function-hook (c hook)
    (declare (ignore hook))
    (typecase c
      (undefined-function (use-value (lambda (arg)
                                       (format t "~%dummy function with arg ~a~%" arg))
                                     c))))
PROVIDE-A-FUNCTION-HOOK

* (setf *debugger-hook* #'provide-a-function-hook)
#<FUNCTION PROVIDE-A-FUNCTION-HOOK>

* (this-function-does-not-exist "foo")
; in: THIS-FUNCTION-DOES-NOT-EXIST "foo"
;     (THIS-FUNCTION-DOES-NOT-EXIST "foo")
; 
; caught STYLE-WARNING:
;   undefined function: THIS-FUNCTION-DOES-NOT-EXIST
; 
; compilation unit finished
;   Undefined function:
;     THIS-FUNCTION-DOES-NOT-EXIST
;   caught 1 STYLE-WARNING condition

dummy function with arg foo
NIL
示例

CL-USER 69 > (flet ((call-use-value-restart (c)
                      (use-value (lambda (arg)
                                   (format t "~%dummy function with arg ~a~%" arg))
                                 c)))
               (handler-bind ((undefined-function #'call-use-value-restart))
                 (this-function-does-not-exist "foo")))

dummy function with arg foo
NIL
在上述示例中,函数
此函数不存在
不存在。如您所见,将处理错误并调用另一个函数,然后执行一些输出

如果我们单独调用未定义的函数,我们会得到一个错误:

CL-USER 70 > (this-function-does-not-exist "foo")

Error: Undefined operator THIS-FUNCTION-DOES-NOT-EXIST in form (THIS-FUNCTION-DOES-NOT-EXIST "foo").
  1 (continue) Try invoking THIS-FUNCTION-DOES-NOT-EXIST again.
  2 Return some values from the form (THIS-FUNCTION-DOES-NOT-EXIST "foo").
  3 Try invoking something other than THIS-FUNCTION-DOES-NOT-EXIST with the same arguments.
  4 Set the symbol-function of THIS-FUNCTION-DOES-NOT-EXIST to another function.
  5 Set the macro-function of THIS-FUNCTION-DOES-NOT-EXIST to another function.
  6 (abort) Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.

CL-USER 71 : 1 > 

在球拍中,您可以覆盖
#%top

#朗球拍
(提供
(合并)
(外拍除外(全部外拍)#%top)
(重命名为[shell curry#%top]))
(需要球拍/系统)
(定义(字符串化a)
(~a(if(cmd?a)(cmd name a)a)))
(结构cmd(名称proc)
#:属性属性:过程
(结构字段索引过程)
#:透明
#:方法gen:自定义写入
[(定义(写入进程x端口模式)
(显示(字符串附加“#”)端口)])
(定义(外壳名称)
(定义(cmd proxy.args)
(定义cmd
(字符串连接(映射字符串化(cons name args))
" "))
(系统命令)
cmd代理)
(定义语法shell curry
(语法规则()
(id)
(cmd'id(shell'id(()())))
将其另存为shell.rkt,并将其置于同一目录中:

#lang s-exp“shell.rkt”
(定义测试(list/bin/ls/usr/bin/file))
(第二次测试);==>#
(第一次测试);==>#
((第二次测试)(第一次测试))
; ==> t(打印/bin/ls是我的系统上的可执行文件)

现在从这里开始,制作一个
#lang myshell
或类似的东西非常简单

太好了!我现在接受球拍版本。我将尝试创建一个通用的lisp实现,并对它的运行情况进行评论。