如何在仅IPv6网络上使用Clozure CL?

Ale*_*nko 3 common-lisp clozure-cl

我在使用IPv6网络时尝试用Clozure CL替换SBCL,但是遇到了类似的错误:

MIGRATIONS> (ignore-errors (ccl:make-socket :remote-host "ya.ru" :remote-port 443))
NIL
#<CCL:NO-APPLICABLE-METHOD-EXISTS #x302005215E5D>
MIGRATIONS> (ignore-errors (ccl:make-socket :remote-host "ya.ru" :remote-port 443 :address-family :internet))
NIL
#<CCL:NO-APPLICABLE-METHOD-EXISTS #x3020052549AD>
MIGRATIONS> (ignore-errors (ccl:make-socket :remote-host "ya.ru" :remote-port 443 :address-family :internet6))
#<BASIC-TCP-STREAM ISO-8859-1 (SOCKET/16) #x3020051D4A9D>
Run Code Online (Sandbox Code Playgroud)

问题是许多库在使用CCL:MAKE-TCP-SOCKET时不指定address-family或指定:internet.

是否有一种方法可以ccl:make-socket在运行时修补以覆盖此设置?

Rai*_*wig 5

建议一个功能

Common Lisp的几个实现允许建议( - > 修补)正常函数.建议是一种非标准功能,不同的实现方式略有不同.CLOS泛型函数的相关机制是标准化的:before,:after和:around方法.

目的是在定义函数之后向函数添加一个或多个补丁,而不更改原始源代码.

通常,这要求不对内联函数调用此函数.

Clozure Common Lisp中的宏ADVISE

Clozure CL中的修补功能可以通过宏完成ADVISE.请参阅文档以获取建议.

假设我们有一个功能FOOBAR:

? (defun foobar (a b &key c (d :foobar)) (list a b c d))
FOOBAR
Run Code Online (Sandbox Code Playgroud)

FOOBAR被内部调用TEST:

? (defun test (a) (foobar a 20 :c 30))
TEST

? (test 10)
(10 20 30 :FOOBAR)
Run Code Online (Sandbox Code Playgroud)

我们现在想要修补FOOBAR,以便:D使用不同的值调用命名的arg .

我们更改arglist以在两个必需的args之后插入新的命名参数:

? (advise foobar (let ((arglist (list* (first arglist)
                                       (second arglist)
                                       :d :ipv6
                                       (cddr arglist))))
                   (:do-it))   ; calling the original function
          :when :around     ; advise around it
          :name :ipv6)      ; the name of this advise
#<Compiled-function (CCL::ADVISED 'FOOBAR) (Non-Global)  #x3020010D1CCF>
Run Code Online (Sandbox Code Playgroud)

现在我们可以调用我们的TEST函数,它将调用建议的函数FOOBAR.

? (test 10)
(10 20 30 :IPV6)
Run Code Online (Sandbox Code Playgroud)

建议CCL:MAKE-SOCKET

你可以写一个类似的建议CCL:MAKE-SOCKET.

未经测试:

(advise ccl:make-socket (let ((arglist (list* :address-family
                                              :internet6
                                              arglist)))
                          (:do-it))
        :when :around
        :name :internet6)
Run Code Online (Sandbox Code Playgroud)