EVAL в СХЕМЕ - PullRequest
       21

EVAL в СХЕМЕ

5 голосов
/ 25 июня 2009

Питер Норвиг в PAIP говорит:
«в современных буксирах ... eval используется реже (на самом деле, в Scheme вообще нет eval)» «если вы обнаружите, что используете eval, вы, вероятно, поступаете неправильно».

Каковы некоторые из способов обойти использование eval в схеме? Есть ли случай, когда eval абсолютно необходим?

Ответы [ 7 ]

7 голосов
/ 26 июня 2009

В некоторых случаях необходимо eval, но они всегда включают сложные программы, которые выполняют такие вещи, как динамическая загрузка некоторого кода (например, сервлет на веб-сервере). Что касается способа «обойти» его использование - это зависит от конкретной проблемы, которую вы пытаетесь решить, не существует волшебного решения, позволяющего избежать eval, кроме ... eval.

(Кстати, я предполагаю, что PAIP был написан давным-давно, до того, как eval был добавлен в отчет схемы.)

4 голосов
/ 25 июня 2009

Он не прав. Конечно, в схеме eval.

3 голосов
/ 13 декабря 2011

Утверждение, что в Схеме нет eval, является неточным, по крайней мере, для самых последних версий стандарта Схемы (R5RS и более поздних версий). Обычно вместо этого требуется макрос, который генерирует код во время компиляции.

Это правда, что eval следует избегать. Для начала, я никогда не видел удовлетворительного определения того, как он должен вести себя, например:

  1. В каких выражениях среды следует оценивать, когда среда не передается?
  2. Когда вы проходите в среде, как они работают? Например, стандарты не указывают, каким образом вы можете предварительно связать значение в этом объекте среды.

Тем не менее, я работал с приложением Scheme, которое использует eval для динамической генерации кода во время выполнения для случаев, когда структура вычисления не может быть известна во время компиляции. Намерение состояло в том, чтобы заставить систему Scheme скомпилировать код во время выполнения по соображениям производительности, и трудность заключается в том, что не существует стандартного способа сказать системе Scheme "скомпилировать этот код".

Само собой разумеется, что eval может быть огромной угрозой безопасности. Вы никогда не должны eval ничего, что не имеет огромной стены отделения от пользовательского ввода. По сути, если вы хотите безопасно использовать eval, вы должны делать это в контексте этапа генерации кода системы, подобной компилятору, после того, как вы проанализировали некоторые входные данные (используя всесторонне определенную грамматику!).

3 голосов
/ 24 октября 2010

Вам понадобится eval в очень редком случае. Сначала приходит на ум случай, когда вы соберете программу с программой, а затем выполните ее. Это происходит в основном с генетическим алгоритмом , например. В этом случае вы создаете много случайных программ, которые вам нужно будет выполнить. Наличие eval в сочетании с кодом, являющимся данными, делает lisp самым простым языком программирования для создания генетического алгоритма.

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

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

1 голос
/ 25 июня 2009

Во-первых, PAIP написан для Common Lisp, а не для Scheme, поэтому я не знаю, что он сказал бы то же самое. Макросы CL делают то же самое, что и eval, хотя во время компиляции, а не во время выполнения, и есть другие вещи, которые вы могли бы сделать. Если бы вы показали мне пример использования eval в Common Lisp, я мог бы попытаться придумать другие способы сделать то же самое.

Я не программист Scheme. Я могу говорить только с точки зрения Норвига, как программиста на Common Lisp. Я не думаю, что он говорил о Схеме, и я не знаю, знал ли он или знает Схему особенно хорошо.

Во-вторых, Норвиг говорит, что «вы, вероятно, делаете не то», а не «вы делаете не то». Это означает, что, насколько он знает, бывают ситуации, когда eval - это правильная вещь. На языке, подобном C, я бы сказал то же самое о goto, хотя они довольно полезны в некоторых ограниченных обстоятельствах, но большинство goto используют люди, которые не знают ничего лучше.

0 голосов
/ 27 июня 2009

Одним из применений, которое я видел для 'eval' в средах сценариев, является параметризация некоторого кода со значениями времени выполнения. например, в псевдо-C:

param = read_integer();
fn = eval("int lambda(int x) { 
            int param = " + to_string(param) + "; 
            return param*x; }");

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

(define make-my-fn
  (lambda (param)
    (lambda (x)  (* param x)))

(let* ([ param  (read-integer) ]
       [ fn     (make-my-fn param ])
  ;; etc.
 )

Как уже упоминалось, динамическая загрузка кода и тому подобное все еще требует eval, но параметризованный код и состав кода могут быть получены с помощью функций первого класса.

0 голосов
/ 25 июня 2009

Вы можете написать интерпретатор схемы в схеме. Такое конечно возможно, но это не практично.

Конечно, это общий ответ, поскольку у меня нет используемой схемы, но, тем не менее, он может вам помочь. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...