Как создать динамический список символов и команд в схеме без использования eval-строки? - PullRequest
3 голосов
/ 07 июля 2011

Я пытаюсь вызвать функцию, используя данные, которые я прочитал из входного файла.У меня есть следующая функция, которая принимает список вершин и произвольное количество команд.(Я немного упростил эту функцию).

(create-graph vertex-list cmd0 cmd1 ... cmdn)

Мой входной файл будет выглядеть примерно так:

(2
(vertex-create "Paris")
(vertex-create "London"))

, где 2 - количество вершин.

С этим вводом я хотел бы вызвать create-graph как

(create-graph
  '(v1 v2)
  (set! v1 (vertex-create "Paris"))
  (set! v2 (vertex-create "London"))
)

, где v1 и v2 - символы, созданные для каждой вершины.

Теперь у меня есть возможность построить всю функциюв качестве строки и использовать eval-string.Но есть ли способ сделать этот вызов функции без использования eval-string?Использование Eval для некоторых частей должно быть хорошо.Точнее говоря, я думаю, что мне нужно уметь динамически :

  • создавать список символов и
  • создавать команды (например, (установить! v1 (vertex-create "Paris")))

Буду признателен за ваш вклад.Спасибо!

Ответы [ 2 ]

2 голосов
/ 07 июля 2011

Да, вы можете сделать это без eval. Да, это гораздо лучшая идея. Важно понимать, что каждая программа может рассматриваться как интерпретатор для ее входных данных, но как только вы поймете eval, вам больше никогда не следует ее использовать ....

Ваша программа может выглядеть примерно так:

#lang racket

(define cmds (file->value input-file))

(define vertex-names (for ([i (in-range (length cmds))])
                       (string->symbol (format "v~s" i))))

(create-graph
 (for/list ([v (in-list vertex-names)]
            [cmd (in-list cmds)])
   (list
    v
    (match cmd
      [(list 'vertex-create str) (vertex-create str)]
      ... other choices? ...
      ))))

Я предположил, что вместо того, чтобы указывать количество вершин, вы бы просто вывели его из длины списка команд. Кроме того, я не вижу, какие еще могут быть «команды». Также, Ваши наборы! ненужны и противны :).

1 голос
/ 07 июля 2011

Макрос, который можно использовать для создания такого списка:

(define-syntax make-create-graph-call
  (syntax-rules ()
    ((_ symbol-count commands) 
     (let* ((sym-list (create-sym-list symbol-count))
            (cmds (let loop ((slist sym-list) 
                             (cms commands)
                             (res '()))
                    (if (not (null? slist))
                        (loop (cdr slist) (cdr cms)
                              (cons `(set! ,(car slist) ,(car cms)) res))
                        (reverse res)))))
       `(create-graph ',sym-list ,@cmds))))) 

Где create-sym-list определяется как:

(define (create-sym-list count)
  (let loop ((c 0) (res '()))
    (if (< c count)
        (loop (+ 1 c) (cons (string->symbol 
                             (string-append "v" (number->string (+ 1 c)))) res))
        (reverse res))))

Использование:

(make-create-graph-call 2 '((vertex-create "Paris") (vertex-create "London")))

=> (create-graph '(v1 v2) (set! v1 (vertex-create "Paris")) 
                          (set! v2 (vertex-create "London")))
...