Scheme 如何获取函数名作为符号?

Scheme 如何获取函数名作为符号?,scheme,racket,Scheme,Racket,我试图定义一个函数func->symbol,它接受一个函数并将其名称作为符号返回。例如: (define (pythagoras a b) (sqrt (+ (* a a) (* b b)))) ;; #1 (func->symbol pythagoras) ; Returns: 'pythagoras ;; #2 (func->symbol (if #t pythagoras sqrt)) ; Returns: 'pythagoras ;; #3 (let ((f (

我试图定义一个函数func->symbol,它接受一个函数并将其名称作为符号返回。例如:

(define (pythagoras a b)
  (sqrt (+ (* a a) (* b b))))

;; #1
(func->symbol pythagoras)  ; Returns: 'pythagoras

;; #2
(func->symbol (if #t pythagoras sqrt))  ; Returns: 'pythagoras

;; #3
(let ((f (if #t pythagoras sqrt)))
  (func->symbol f))  ; Returns: 'pythagoras

;; #4
(let ((f (if #t pythagoras sqrt)))
  (let ((g f))
    (func->symbol g)))  ; Returns: 'pythagoras
这是一个仅涉及案例1的后续问题。对于情况1,一个简单的宏def->符号就足够了:

(define-syntax def->symbol
  (syntax-rules ()
    ((_ def) 'def)))

但是,此宏定义不通过案例2、3、4。是否可以定义func->symbol,或者Scheme的表达能力不够?

在Racket中,在许多情况下,可以使用对象名获取函数名。但是,除了调试之外,依赖此结果可能不是一个好主意。

在Racket中,在许多情况下,您可以使用对象名获取函数名。但是,除了调试之外,依赖这个结果可能是一个坏主意。

也许值得一个答案来说明为什么在任何具有一流函数的语言中都不可能做到这一点

我将定义我所说的具有一级函数的语言,因为有不同的定义

函数可以作为参数传递给其他函数,并作为值返回。 函数可以存储在变量和其他数据结构中。 有匿名函数或函数文本。 从这个意义上讲,Scheme显然具有一流的功能。现在考虑这个代码:

(define a #f)
(define b #f)

(let ((f (lambda (x)
           (+ x 1))))
  (set! a f)
  (set! b f))
假设有一个函数名函数,给定一个函数,它返回它的名称。返回的函数名应该是什么

答案是它在Racket中没有返回有用的值,object name a返回f,但这显然暴露了实现细节,这些细节可能对调试有用,但作为函数名过程的返回值会非常误导

这就是为什么这样一个过程一般不可能存在于具有一级函数的语言中:从名称映射到值的函数是多对一的,因此没有逆函数

这里有一个例子,你可以做一些恶心的黑客来让这个“工作”,以及为什么它是可怕的。以下是球拍特定代码:

(define-syntax define/naming
  ;; Define something in such a way that, if it's a procedure,
  ;; it gets the right name.  This is a horrid hack.
  (syntax-rules ()
    [(_ (p arg ...) form ...)
     (define (p arg ...) form ...)]
    [(_ name val)
     (define name (let ([p val])
                    (if (procedure? p)
                        (procedure-rename p 'name)
                        p)))]))
现在,考虑到

(define/naming a
  (let ([c 0])
    (thunk
     (begin0
       c
       (set! c (+ c 1))))))

(define/naming b a)
然后:


所以a和b有“正确”的名称,但因为它们不一定是同一个对象,我认为这在语义上是错误的:如果我看到定义a b,那么我想要eqv?我想是真的。但是a和b确实捕获了相同的词法状态,所以这至少是可行的。

也许值得一个答案来说明为什么这在任何具有一流函数的语言中都是不可能的

我将定义我所说的具有一级函数的语言,因为有不同的定义

函数可以作为参数传递给其他函数,并作为值返回。 函数可以存储在变量和其他数据结构中。 有匿名函数或函数文本。 从这个意义上讲,Scheme显然具有一流的功能。现在考虑这个代码:

(define a #f)
(define b #f)

(let ((f (lambda (x)
           (+ x 1))))
  (set! a f)
  (set! b f))
假设有一个函数名函数,给定一个函数,它返回它的名称。返回的函数名应该是什么

答案是它在Racket中没有返回有用的值,object name a返回f,但这显然暴露了实现细节,这些细节可能对调试有用,但作为函数名过程的返回值会非常误导

这就是为什么这样一个过程一般不可能存在于具有一级函数的语言中:从名称映射到值的函数是多对一的,因此没有逆函数

这里有一个例子,你可以做一些恶心的黑客来让这个“工作”,以及为什么它是可怕的。以下是球拍特定代码:

(define-syntax define/naming
  ;; Define something in such a way that, if it's a procedure,
  ;; it gets the right name.  This is a horrid hack.
  (syntax-rules ()
    [(_ (p arg ...) form ...)
     (define (p arg ...) form ...)]
    [(_ name val)
     (define name (let ([p val])
                    (if (procedure? p)
                        (procedure-rename p 'name)
                        p)))]))
现在,考虑到

(define/naming a
  (let ([c 0])
    (thunk
     (begin0
       c
       (set! c (+ c 1))))))

(define/naming b a)
然后:


所以a和b有“正确”的名称,但因为它们不一定是同一个对象,我认为这在语义上是错误的:如果我看到定义a b,那么我想要eqv?我想是真的。但是a和b确实捕获了相同的词法状态,所以至少可以这样做。

为什么需要这样做?函数没有名称。您可以将相同的函数分配给多个变量,就像您可以将相同的列表或数字分配给多个值一样。*分配给多个变量。我同意Barmar的评论:这闻起来像是一个XY问题:您可能在要求X,而实际需要的是Y。您能描述一下您试图解决的问题吗,因为正如您所说的,这个问题在Scheme或几乎任何Lisp中都没有解决方案,可能在Python&c中也没有解决方案。为什么需要这样做?函数没有名称。您可以将相同的函数分配给多个变量,就像您可以将相同的列表或数字分配给多个值一样。*分配给多个变量。我同意Barmar的评论:这闻起来像是一个XY问题:您可能在要求X,而实际需要的是Y。您能描述一下您试图解决的问题吗,因为正如您所说,这个问题在Scheme或几乎任何Lisp中都没有解决方案,可能在Python&c中也没有解决方案。