从标识符而不是扩展中获取名称

时间:2013-11-16 21:53:14

标签: scheme racket identifier

我有一个编程项目,我试图为其编写一些测试用例。

简单来说,我编写了一个运行这些测试用例的方法:

(define print-case
  (lambda (st1 st2 func)
    (begin
      (if (equal? func intersection)
          (display "Intersection ")
          (display "Union "))
      (display " of ")
      ;???
      (print (func st1 st2))
      (newline)
      )
    )
  )

我定义了几个要运行的列表和两个方法。

以下是一些列表:

(define set1 '(1 4 9 7 20))
(define set2 '(15 4 7 25 99))

但是,为了省事,我想要打印集合和函数的名称,而不是它们的扩展。这可能吗?

我尝试(display st1),但显然只是将st1扩展到列表中。在st1前面放一个引号只会导致它打印st1,而不是我传入的集合的名称。

提前致谢。

3 个答案:

答案 0 :(得分:3)

在您的示例中,set1内的名称set2print-case不可知,因此无法实现。您可以显式传递名称,也可以使用宏来包装它:

(define-syntax-rule (call-print-case s1 s2)
  (apply print-case `(s1 ,s1 s2 ,s2)))

(define set1 '(1 4 9 7 20))
(define set2 '(15 4 7 25 99))

(define print-case
  (lambda (st1name st1 st2name st2)
    (display st1name)
    (displayln st1)
    (display st2name)
    (displayln st2)))

然后

(call-print-case set1 set2)
=>
set1(1 4 9 7 20)
set2(15 4 7 25 99)

答案 1 :(得分:2)

您知道可以使用rackunit进行单元测试:

(require rackunit)
(check-eq? (car '(b b)) 'a "car-test")
==>
--------------------
FAILURE
actual:     b
expected:   a
name:       check-eq?
location:   (unsaved-editor1044 5 0 35 38)
expression: (check-eq? (car '(b b)) 'a)
message:    "car-test"

无论如何,如果你想自己动手,你需要使用一个宏:

(define-syntax unit-test
  (syntax-rules ()
    ((_ (form . args) expected-result) 
     ;; insteadof this let one could make a procedure to handle it and pass expression quoted and unquoted.
     (let ((res (form . args))
           (exp expected-result))
       (when (not (equal? res expected-result))
         (display "Error: ")
         (display '(form . args))
         (newline)
         (display "Got result '")
         (display res)
         (display "' expected '")
         (display exp)
         (display "'")
         (newline))))))

(unit-test (+ 4 5) 10)

==> 
Error: (+ 4 5)
Got result '9' expected '10'

答案 2 :(得分:1)

在Common Lisp中,您可以将变量set1set2定义为defparameterdefvardefconstant的全局变量,并使用符号valueto使用命名它的符号获取变量的值。例如,

(defparameter set1 '(1 4 9 7 20))
(defparameter set2 '(15 4 7 25 99))

(defun print-case (name)
  (format t "~a ~a" name (symbol-value name))

在Scheme中,你将无法做到这一点。如果您希望能够获取符号并获取相应的值,通常,您需要构建某种将符号与值相关联的结构。您可以使用关联列表:

(define sets '((set1 1 2 3 4 5)
               (set2 0 1 3 5 7)))

(cdr (assoc 'set1 sets))
;=> (1 2 3 4 5)

(cdr (assoc 'set2 sets))
;=> (0 1 3 5 7)

或者,您可以使用哈希表:

(define sets
  (hash 'set1 '(1 2 3 4 5)
        'set2 '(0 1 3 5 7)))

(hash-ref sets 'set1)
;=> '(1 2 3 4 5)

(hash-ref sets 'set2)
;=> '(0 1 3 5 7)

在任何情况下,您都需要提供某种从符号映射到列表的结构。

如果你不需要这样的通用解决方案,你可以使用一些宏,如uselpa's answer演示的那样,并且可以以这样的方式包装测试函数,即你可以访问这两个符号。调用test函数和带有该名称的变量的值。这不会以相同的方式从符号“映射”到值,但是您的测试函数将获得它需要的四个值(两个名称和两个值),并且对于编写测试用例,这是可能就够了。