键入的球拍 - 重新访问动态函数调用(字符串到过程)

时间:2017-03-29 18:55:37

标签: scheme racket typed

大约一年前,@ 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 语句来做,但我希望有一个更优雅的解决方案。

谢谢。

1 个答案:

答案 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)