大约一年前,@ soegaard提供了一个有趣问题的答案 - 如何获取字符串并返回该字符串中指定的过程。解决方案简单而优雅。
输入键入的球拍并扭转。
只要它只返回具有相同arity的函数(例如#lang racket
(provide string->procedure add square)
(define (add x y)
(+ x y))
(define (square x)
(sqr x))
(define ns (variable-reference->namespace (#%variable-reference)))
(define (string->procedure s)
(define sym (string->symbol s))
(eval sym ns))
(string->procedure "add")
((string->procedure "add") 1 2)
((string->procedure "square") 5)
),我可以使它在类型球拍中工作,但是如果我尝试让它能够返回具有不同arities的函数,如下所示,我无法弄清楚如何使require / typed调用工作。
这是修改过的文件,我的第二个函数具有不同的arity。
#lang typed/racket
(require/typed "string-procedure.rkt"
[string->procedure
(-> String (-> Number Number Number))]
[add (-> Number Number Number)]
[square (-> Number Number)])
以下是仅适用于"添加"功能或任何其他带两个数字并返回一个数字的函数。
case->
我尝试过使用case->
和工会无济于事。至少使用case
作为返回类型会运行但是它会使所有调用失败。
如果您认为我尝试这样做,我尝试做的就是获取数据库调用的结果,字符串,并确定调用以访问相应数据的正确过程结构中的元素。我可以用很长的try:
first, = list_with_len_1
except ValueError:
first = None
语句来做,但我希望有一个更优雅的解决方案。
谢谢。
答案 0 :(得分:2)
我不认为您想使用eval,或者以这种方式解决这个问题。具体来说:如果数据库包含引用不存在的函数的字符串,或者您不希望调用的函数,该怎么办?这就是安全问题的产生方式。
我会说,在这种情况下,您可能愿意指定" legal"的程序名称,并且您可以使用不具有&#的宏轻松地执行此操作。 39;严重的卫生条件:
#lang typed/racket
;; defines the 'db-callable' syntax. Put this in a library file...
(define-syntax (db-callable stx)
(syntax-case stx ()
[(_ fun-name [id ...])
(with-syntax ([(id-strs ...)
(for/list ([id-stx (in-list (syntax->list #'(id ...)))])
(symbol->string (syntax-e id-stx)))])
#'(define (fun-name str)
(match str
[id-str id] ...)))]))
;; here are some functions we want the DB to be able to call
(define (f x) 3)
(define (g x) 4)
;; here's the list of functions we want the db to be able to call:
(db-callable getfun [f g])
((getfun "f") 9)
((getfun "g") 123)