小编IgS*_*lov的帖子

Common Lisp:按值传递与按引用传递

我想用 Common Lisp 编写一个函数,它会破坏性地修改它的参数。在 C 或 Rust 中,我将使用指向对象的指针/引用,该对象可以在函数体内取消引用。在 CL 中我写道:

(defun foo (lst)
  (setf lst NIL))
Run Code Online (Sandbox Code Playgroud)

但在评估此表格后:

(let ((obj (list "a" "b")))
  (foo obj)
  obj) => ("a" "b")
Run Code Online (Sandbox Code Playgroud)

可以看到该函数foo没有任何效果。我可以解释按值传递语义,即我们修改推入函数堆栈的参数的本地副本。如果我们定义另一个函数:

(defun bar (lst)
  (setf (car lst) NIL))
Run Code Online (Sandbox Code Playgroud)

并评估类似的形式

(let ((obj (list "a" "b")))
  (bar obj)
  obj) => (NIL "b")
Run Code Online (Sandbox Code Playgroud)

我们将清楚地看到 已lst被修改,就好像我们将使用按引用传递语义一样。所以,(setf lst NIL)没有工作,但(setf (car lst) NIL)做了。您能解释一下原因吗?

lisp common-lisp pass-by-reference pass-by-value

2
推荐指数
1
解决办法
855
查看次数

Common Lisp 中的对象内存布局

我知道 Common Lisp 不鼓励程序员接触原始内存,但我想知道是否可以查看对象如何在字节级别存储。当然,垃圾收集器在内存空间中移动对象,并且函数的两次后续调用(obj-as-bytes obj)可能会产生不同的结果,但让我们假设我们只需要内存快照。你会如何实现这样的功能?

我对 SBCL 的尝试如下:

(defun obj-as-bytes (obj)
  (let* ((addr (sb-kernel:get-lisp-obj-address obj)) ;; get obj address in memory
         (ptr (sb-sys:int-sap addr))                 ;; make pointer to this area
         (size (sb-ext:primitive-object-size obj))   ;; get object size 
         (output))
    (dotimes (idx size)
      (push (sb-sys:sap-ref-64 ptr idx) output))     ;; collect raw bytes into list
    (nreverse output)))                              ;; return bytes in the reversed order
Run Code Online (Sandbox Code Playgroud)

咱们试试吧:

(obj-as-bytes #(1)) =>
(0 2 0 0 0 0 0 0 0 0 0 0 0 …
Run Code Online (Sandbox Code Playgroud)

memory sbcl common-lisp

2
推荐指数
1
解决办法
464
查看次数