Калькулятор стек в Racket


У меня реализован стек калькулятор на основе этого программирования задач. Я подумал, что более опытный рэкетир мог дать мне обратную связь и скажите мне, если я пропускаю что-нибудь в ракетки, которые позволили бы решение было более элегантным.

#lang racket

(define (inc n)
  (+ n 1))

(define (print-value s)
  (begin
    (display s)
    (display " ")))

(define (exec l (stack empty) (opcount 1))
  "executes a stack based program."
  (cond
    [(empty? l) (void)]

    ;; push number onto stack
    [(number? (string->number (first l)))
     (exec (rest l)
           (cons (string->number (first l)) stack)
                 (inc opcount))]

    ;; pop number from stack
    [(equal? (first l) ".")
     (begin
       (print-value (first stack))
       (exec (rest l) (rest stack)
       (inc opcount)))]

    ;; mathmatical operators
    [(equal? (first l) "+")
     (exec (rest l) (cons
                     (+ (first stack) (second stack))
                     (rest (rest stack))) (inc opcount))]
    [(equal? (first l) "-")
     (exec (rest l) (cons
                     (- (first stack) (second stack))
                     (rest (rest stack))) (inc opcount))]
    [(equal? (first l) "*")
     (exec (rest l) (cons
                     (* (first stack) (second stack))
                     (rest (rest stack))) (inc opcount))]
    [(equal? (first l) "/")
     (exec (rest l) (cons
                     (/ (first stack) (second stack))
                     (rest (rest stack))) (inc opcount))]

    ;; duplication operator
    [(equal? (string-downcase (first l)) "dup")
     (exec (rest l)
           (cons (first stack) stack) (inc opcount))]
    [else
     (~a "Error: operation " opcount " invalid")]))

(define program (string-split "64 DUP * ."))

(exec program)


Комментарии
1 ответ

Ошибка

В - и / операторы интерпретируют операнды назад от типичных РПН заказа. То есть, я надеюсь "10 7 -" следует производить 3но ведь на самом деле производит -3.

Рекурсия

Ваш код-это ужасно однообразные, потому что обработчик для каждого оператора должен принести оператору ((first l)), выполнить операцию, затем сделать рекурсивный вызов ((exec (rest l) … (inc opcount))). Было бы целесообразно определить вспомогательную функцию, которая применяет оператор в стек.

(define (apply-op op stack)
(cond
[(number? (string->number op))
(cons (string->number op) stack)]
[(equal? op ".")
(begin
(display (first stack))
(display " ")
(rest stack))]
[(equal? op "+")
(cons (+ (second stack) (first stack)) (rest (rest stack)))]
[(equal? op "-")
(cons (- (second stack) (first stack)) (rest (rest stack)))]
[(equal? op "*")
(cons (* (second stack) (first stack)) (rest (rest stack)))]
[(equal? op "/")
(cons (/ (second stack) (first stack)) (rest (rest stack)))]
[(equal? (string-downcase op) "dup")
(cons (first stack) stack)]
[else
(~a "operation '" op "' invalid")]))

Тогда exec функция просто должен вызвать его и загнать рекурсии.

(define (exec ops (stack empty) (opcount 1))
"executes a stack based program."
(cond
[(empty? ops) (void)]
[else
(let ([next-stack (apply-op (first ops) stack)])
(if (string? next-stack)
(~a "Error at operator " opcount ": " next-stack)
(exec (rest ops) next-stack (+ opcount 1))))]))

1
ответ дан 19 февраля 2018 в 07:02 Источник Поделиться