Это мой код, и я немного запутался, почему я получаю эту ошибку. Мой код просто чтобы найти корни для квадратного уравнения.

(define (roots a b c)
  (define det
    (- (* b b) (* 4 a c))
  )
  (if (> det 0) (
                  (display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
                  (display (/ (- (* b -1) (sqrt det)) (* 2 a)))
                )
  )
  (if (= det 0) (
                   (display (/ (* b -1) (* 2 a)))
                  (display (/ (* b -1) (* 2 a)))
                )
  )
  (if (< det 0) (
                  (display "complex roots")
                  (display (/ (+ (* b -1) sqrt(* det -1)) (* 2 a)))
                  (display (/ (- (* b -1) sqrt(* det -1)) (* 2 a)))
                )               
  )
)

(roots -2 4 5)
(roots -2 4 -5)
1
Krit Phosamritlert 28 Май 2017 в 08:33

2 ответа

Лучший ответ

Я полагаю, вы хотели добавить begin в тело вашего вооруженного солдата. Процедура display имеет возвращаемое значение void, и дополнительные скобки попытаются применить значение в качестве процедуры. Вы можете воспроизвести ошибку, запустив ((display 5)). Использование begin позволит вам вместо этого оценивать выражения в последовательности.


Этот код будет отображать значения без каких-либо исключений:

(define (roots a b c)
  (define det
    (- (* b b) (* 4 a c))
  )
  (if (> det 0) (begin
                  (display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
                  (display (/ (- (* b -1) (sqrt det)) (* 2 a)))
                )
  )
  (if (= det 0) (begin
                   (display (/ (* b -1) (* 2 a)))
                  (display (/ (* b -1) (* 2 a)))
                )
  )
  (if (< det 0) (begin
                  (display "complex roots")
                  (display (/ (+ (* b -1) sqrt(* det -1)) (* 2 a)))
                  (display (/ (- (* b -1) sqrt(* det -1)) (* 2 a)))
                )               
  )
)
2
qfwfq 28 Май 2017 в 05:53

Скобки в схеме очень особенные. Они означают apply:

(define (test arg) arg)

((test +) 4 5) ; ==> 9

То же самое в JavaScript:

const plus = (a, b) => a+b; // Needed since + is not a function in JS
const test = arg => arg

test(plus)(4,5) // ==> 9

В вашем коде у вас есть:

((display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
 (display (/ (- (* b -1) (sqrt det)) (* 2 a))))

К сожалению, выражение в позиции оператора return #<undef>. На самом деле, согласно спецификации, он может вернуть что угодно , потому что он не определен в спецификации. Ибо ваша конкретная реализация, хотя это не функция, поэтому она выглядит так:

((test 'symbol) 4 5); ==> Error: symbol is not a function

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

Теперь есть макросы, которые используют круглые скобки для чего-то другого, кроме приложения, и для этого вам просто нужно знать или читать документацию. Примером является cond

(cond ((= 3 5) #t)
      (else #f))
; ==> #f

Если вы никогда не видели cond раньше, легко предположить, что ((= 3 5) #t) является выражением, и, конечно, если посмотреть на него, оно не будет работать, поскольку (= 3 5) не будет вычислять функциональный объект, но логическое. Однако каждый термин в cond оценивает его car, а затем каждый элемент в остальной части термина по порядку, если он оказался истинным значением.

Чтобы сделать больше выражений по порядку и вернуть значение последнего выражения, используйте begin:

(begin 1 2 3)
; ==> 3

Здесь вычисление 1 и 2 явно мертвый код, поскольку он ничего не делает. Таким образом, его наследование заключается в том, что использование begin подразумевает побочный эффект, когда возвращаемое значение не имеет значения, но побочный эффект есть. Я не думаю, что ваша функция действительно нуждается в побочных эффектах:

(define (roots a b c)
  (define det
    (- (* b b) (* 4 a c)))
  (cond ((> det 0)
         (list (/ (+ (* b -1) (sqrt det)) (* 2 a))
               (/ (- (* b -1) (sqrt det)) (* 2 a))))
        ((= det 0)
         (list (/ (* b -1) (* 2 a))))
        ((< det 0)
         (list (/ (+ (* b -1) (make-rectangular 0 (sqrt (* det -1)))) (* 2 a))
               (/ (- (* b -1) (make-rectangular 0 (sqrt (* det -1)))) (* 2 a))))))

(roots -1 4 -4) ; ==> (2 -2)
(roots 1 0 -4)  ; ==> (2)
(roots 4 0 4)   ; ==> (0+1i 0-1i)
2
Sylwester 28 Май 2017 в 19:26