如何在Guile Scheme REPL中让GOOPS对象实现友好打印
让Guile GOOPS的对象在REPL中美观打印
这个问题我太熟悉了——Guile的GOOPS对象默认只会输出#<...>这种模糊的占位符,根本看不到实际数据。不过我们可以通过自定义对象的打印逻辑来解决,有两种常用的方法:
方法1:定义类时使用#:print关键字参数
这是GOOPS专门提供的便捷方式,直接在define-class里指定打印函数:
(use-modules (oop goops)) (define-class <vec3> () (e0 #:init-value 0.0 #:init-keyword #:e0) (e1 #:init-value 0.0 #:init-keyword #:e1) (e2 #:init-value 0.0 #:init-keyword #:e2) #:print (lambda (obj port) (format port "#<vec3 ~a ~a ~a>" (slot-ref obj 'e0) (slot-ref obj 'e1) (slot-ref obj 'e2)))) (define (make-point x y z) (make <vec3> #:e0 x #:e1 y #:e2 z))
测试一下:
scheme@(guile-user)> (define p0 (make-point 1 2 3)) scheme@(guile-user)> p0 $1 = #<vec3 1 2 3>
这样就能直接看到对象的三个分量了,清晰很多。你还可以调整format的字符串,比如改成"(point ~a ~a ~a)",打印出来就是(point 1 2 3),更贴近Scheme的语法风格。
方法2:为类定义write方法
write方法 Guile的REPL在打印值时会调用标准的write过程,我们可以为<vec3>类自定义这个方法:
(use-modules (oop goops)) (define-class <vec3> () (e0 #:init-value 0.0 #:init-keyword #:e0) (e1 #:init-value 0.0 #:init-keyword #:e1) (e2 #:init-value 0.0 #:init-keyword #:e2)) (define-method (write (obj <vec3>) port) (format port "#<vec3 ~a ~a ~a>" (slot-ref obj 'e0) (slot-ref obj 'e1) (slot-ref obj 'e2))) (define (make-point x y z) (make <vec3> #:e0 x #:e1 y #:e2 z))
这个方法和第一种效果完全一致,只是实现方式不同——#:print本质上也是帮你注册了对应的打印方法,而直接定义write方法更符合Scheme的标准过程扩展逻辑。
内容的提问来源于stack exchange,提问作者tkf
相关产品推荐
相关产品推荐

