Common Lisp 中的 getter/accessors 等价物

问题描述

我正在编写一个程序,每次访问布尔值时,无论它如何访问,它的值都会反转(即使只是打印它)。在 OOP 语言中,我将通过为此方法定义访问器/获取函数来完成此操作。我怎样才能在普通的 lisp 中做到这一点。

这是我使用 lisp 宏编写的一些示例代码,它输出预期值,但要求所有引用都像 Room 一样包装。它还需要我为每个布尔值定义一个新的宏。如果可能,我想避免这两个问题。

import pandas as pd
import numpy as np

# sample df
df = pd.DataFrame(np.random.default_rng().integers(0,100,size=(100,2)),columns=['one','two'])

# create column with difference (two - one)
df['dif'] = abs(df['two'] - df['one'])

# get max difference index
print(df['dif'].idxmax()) # can store in a variable as well

解决方法

根据我的理解,您想要一些从 TRUE 切换到 FALSE 的变量。从上面的代码片段我不太明白发生了什么,所以我会在下面提出建议,我希望你能找到适合你的。

  1. 保持简单并使用简单的 boolean
(defparameter var1 nil)
(defparameter var2 nil)

(format t "== SIMPLE WAY == ~%")
(format t "STEP 1~%")
(format t "A -> ~A~%" var1)
(format t "B -> ~A~%" var2)

(setf var1 (not var1))
(setf var2 (not var2))

(format t "STEP 2~%")
(format t "A -> ~A~%" var1)
(format t "B -> ~A~%" var2)

(setf var1 (not var1))
(setf var2 (not var2))

(format t "STEP 3~%")
(format t "A -> ~A~%" var1)
(format t "B -> ~A~%" var2)
  1. 您想更进一步深入structures
  2. 的世界
(format t "== STRUCT AND FUNCTIONS == ~%")

(defstruct status
    (flag nil))

;; function to toggle the 'flag' from structure of type 'status'
;; Returns the new status
(defun toggle-flag (status-object)
  (let ((previous-flag (status-flag status-object))) ;; get the current flag
    (let ((new-flag (not previous-flag)))            ;; calculate the new flag
      (setf (status-flag status-object) new-flag)    ;; update the new flag
      ;; return value
      new-flag)))
    
(defparameter var1 (make-status)) ;; create a new object status
(defparameter var2 (make-status)) ;; create a new object status

(format t "STEP 1~%")
(format t "A -> ~A~%" (status-flag var1))
(format t "B -> ~A~%" (status-flag var2))

(format t "STEP 2~%")
(format t "A -> ~A~%" (toggle-flag var1))
(format t "B -> ~A~%" (toggle-flag var2))

(format t "STEP 3~%")
(format t "A -> ~A~%" (toggle-flag var1))
(format t "B -> ~A~%" (toggle-flag var2))
  1. 您喜欢 OOP 冒险并且想要使用 classesmethods
(format t "== CLASSES == ~%")

(defclass state ()           ;; define a new class 'state'
   ((flag                    ;; with a field 'flag'
       :accessor state-flag  ;; accessible with the function (state-flag)
       :initform nil)))      ;; initialized with nil

;; Method to toggle the 'flag' from object of type 'state'
;; Will return the new status
(defmethod toggle ((object state))
  (let ((previous-status (state-flag object)))
    (let ((new-status (not previous-status)))
      (setf (state-flag object) new-status)
      ;; return value
      new-status)))

(defparameter var1 (make-instance 'state)) ;; create a new object state
(defparameter var2 (make-instance 'state)) ;; create a new object state
 
(format t "STEP 1~%")
(format t "A -> ~A~%" (state-flag var1))
(format t "B -> ~A~%" (state-flag var2))

(format t "STEP 2~%")
(format t "A -> ~A~%" (toggle var1))
(format t "B -> ~A~%" (toggle var2))

(format t "STEP 3~%")
(format t "A -> ~A~%" (toggle var1))
(format t "B -> ~A~%" (toggle var2))

所有这些例子都应该给你预期的结果:

STEP 1
A -> NIL
B -> NIL
STEP 2
A -> T
B -> T
STEP 3
A -> NIL
B -> NIL
  1. 我能提供的最后一个选项是使用惊人的 closures
(defun make-toggler ()
  (let ((flag nil)) ;; create a new variable (available only to the closure)
    (lambda ()      ;; return a function... which toggle the variable!
      (setf flag (not flag))
      ;; return value
      flag)))

(defparameter var1 (make-toggler))
(defparameter var2 (make-toggler))

(format t "STEP 1~%")
(format t "A -> ~A~%" (funcall var1))
(format t "B -> ~A~%" (funcall var2))

(format t "STEP 2~%")
(format t "A -> ~A~%" (funcall var1))
(format t "B -> ~A~%" (funcall var2))

(format t "STEP 3~%")
(format t "A -> ~A~%" (funcall var1))
(format t "B -> ~A~%" (funcall var2))