2012-02-19 3 views
4

Я пытаюсь сделать рекурсивное определение, которое считывает и выполняет пользовательские выражения, такие как (3 + 5). Все работает, за исключением одной проблемы с арифметическим символом.Проблемы с оценкой выражений из пользовательского ввода

мне удалось воспроизвести ошибку в более простом примере:

(define v '(1 + 3)) 

((cadr v) 2 4) 

(cadr v) является + символом, но по какой-то причине процедура не может быть выполнена на двух аргументах, которые следовали. Я что-то упускаю?

+2

Символ '' + 'не совпадает с функцией' + '; используйте 'eval', как объяснил Оскар и проверка души, чтобы превратить первое в последнее. –

+1

Я не думаю, что «eval» - правильный выбор здесь - я больше болтаю ниже. –

ответ

3

Я думаю, что это потому, что

(cadr v) 

возвращает '+ не + (дословный + не + функция).

Вам необходимо оценить его, прежде чем применять его к аргументам.

Это должно работать:

((eval (cadr v)) 2 4) 
^evaluates the '+ to + 

редактировать Это работало в ракетку в интерактивном режиме.

Я не совсем уверен, что разница, но сделал это работать в режиме r5rs рэкетом (сценарий):

#lang r5rs 

;required by r5rs 
(define user-initial-environment (scheme-report-environment 5)) 

(define v '(1 + 2)) 

;eval expects a quoted expression 
;(it seems that if it's a function it has to have arguments too) 
;and evaluation environment. 
((eval (cadr v) user-initial-environment) 2 4) 
+0

Я пробовал использовать eval, но он не работает, как я надеялся. Это потому, что я задал свой язык R5RS? –

+0

У меня новая ошибка, процедура meval: ожидает 2 аргумента, учитывая 1: + –

+0

@OrieStone извините, я попробовал это в ракетке и clojure. eval работает по-разному. – soulcheck

0

Попробуйте это:

(define v '(1 + 3)) 

(let ((operator (eval (cadr v))) 
     (operand1 (car v)) 
     (operand2 (caddr v))) 
    (apply operator (list operand1 operand2))) 
0

Вы можете это сделать это путь с eval в коварстве:

(define (infix-eval v) 
    (eval (list (cadr v)(car v)(caddr v)) 
     (interaction-environment))) 

> (infix-eval '(1 + 2)) 
3 

Вместо того чтобы использовать interaction-environment, вы могли бы поставить еще окр гладкость для оценки, где вы также могли бы определить некоторые другие символы, не найденные в стандартной схеме, так что выражения, подобные (7 % 3) и (2^6), также будут работать.

1

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

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

Вопрос, конечно, в том, что вы должны с этим поделать. Некоторые из них предложили использовать «eval»; это, вероятно, плохая идея, по причинам, по которым я думаю, что Мэтью Флатт элегантно улавливается в his blog post on the topic.

Вместо этого вы, вероятно, должны написать простую функцию сопоставления. Вот как я его напишу. Если вы используете мой код в задании, обязательно запишите мне :).

#lang racket 

;; a mapping from symbols to operators 
(define operator-hash 
    (hash '+ + 
     '- - 
     '* *)) 
;; ... and whatever other operators you want. 

;; example of using it: 
(hash-ref operator-hash '+) ;; ==> + 
Смежные вопросы