英文:
Racket: How do you use the value of an argument as a symbol?
问题
我理解了您的请求,以下是您提供的代码部分的翻译:
#lang racket
(define (ul . xs) `(div ,@xs))
(define (make-list list-type)
(if (equal? 'something 'something-else)
(λ args (apply list-type args)) ; 真分支:调用函数 "ul"
(λ args (list* list-type args)))) ; 假分支:如何使用 'ul 而不调用 "ul" 函数?
(define make-ul (make-list 'ul))
请注意,我已经将 ul
从 'ul
更改为 'ul
,以确保它被识别为符号。
英文:
I'm new to Racket, and am struggling to find the right words to explain what I'm trying to do. The best I can come up with is this: How do I use the value of an argument as a symbol, without calling the function which has the same name as the value of the argument, and without just quoting the name of the argument?
Here is a minimal example to show this.
There is a function called ul
which does something.
There is another function called make-list
which has a single parameter, list-type
.
There is a third function, make-ul
, which calls make-list
with an argument ul
.
In the true branch, the function ul
is applied. Good so far.
In the false branch, I want to be able to use the value of the argument, which in this case is 'ul
, as a symbol. In effect, this line of code would run (λ args (list* 'ul args))
. How do I achieve this?
#lang racket
(define (ul . xs) `(div ,@xs))
(define (make-list list-type)
(if (equal? 'something 'something-else)
(λ args (apply list-type args)) ; true branch: call the function "ul"
(λ args (list* list-type args)))) ; false branch: how to use `ul without calling the "ul" function?
(define make-ul (make-list ul))
答案1
得分: 2
If your goal is to write good Racket code, then the best answer is don't.
Add a separate argument to take the symbol, like this:
;; make-list: Procedure Symbol -> Any ... -> Any
(define (make-list proc tag-sym)
(if ....
proc ;; (λ args (apply proc args)) simplifies to just proc
(λ args (list* tag-sym args))))
(define make-ul (make-list ul 'ul))
Or if the branch is independent of args
, you could just have a single argument of type (U Procedure Symbol)
instead:
;; make-list: (U Procedure Symbol) -> Any ... -> Any
(define (make-list list-type)
(cond [(procedure? list-type)
;; (λ args (apply list-type args))
list-type]
[(symbol? list-type)
(λ args (list* list-type args))]))
(define make-ul (make-list ul))
(define make-li (make-list 'li))
If you want to explore Racket features, there are two main ways to do it.
- You can make a macro that takes a procedure name and uses it both as a reference and quotes it as a symbol. For example, using the first version of
make-list
above:
(define-syntax-rule (make-list* proc-name) (make-list proc-name (quote proc-name)))
(define make-ul (make-list* ul)) ;; => (define make-ul (make-list ul 'ul))
- You can call
object-name
on a procedure to ask what Racket thinks its name is. For example,(object-name list)
returns'list
, and(object-name ul)
should return'ul
. But(object-name make-ul)
will not return'make-ul
, because Racket tracks names at compile time, not at run time. (I would advise against writing code that depends onobject-name
; it makes your code very fragile.)
英文:
If your goal is to write good Racket code, then the best answer is don't.
Add a separate argument to take the symbol, like this:
;; make-list : Procedure Symbol -> Any ... -> Any
(define (make-list proc tag-sym)
(if ....
proc ;; (λ args (apply proc args)) simplifies to just proc
(λ args (list* tag-sym args))))
(define make-ul (make-list ul 'ul))
Or if the branch is independent of args
, you could just have a single argument of type (U Procedure Symbol)
instead:
;; make-list : (U Procedure Symbol) -> Any ... -> Any
(define (make-list list-type)
(cond [(procedure? list-type)
;; (λ args (apply list-type args))
list-type]
[(symbol? list-type)
(λ args (list* list-type args))]))
(define make-ul (make-list ul))
(define make-li (make-list 'li))
If you want to explore Racket features, there are two main ways to do it.
-
You can make a macro that takes a procedure name and uses it both as a reference and quotes it as a symbol. For example, using the first version of
make-list
above:(define-syntax-rule (make-list* proc-name) (make-list proc-name (quote proc-name))) (define make-ul (make-list* ul)) ;; => (define make-ul (make-list ul 'ul))
-
You can call
object-name
on a procedure to ask what Racket thinks its name is. For example,(object-name list)
returns'list
, and(object-name ul)
should return'ul
. But(object-name make-ul)
will not return'make-ul
, because Racket tracks names at compile time, not at run time. (I would advise against writing code that depends onobject-name
; it makes your code very fragile.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论