Recentemente, quando aprendi sozinho o curso MIT 6.5151, li pela primeira vez a Unidade 0 do CS 61AS como preparação. Em seguida, li o SICP 1 a 2.1 (com notas de aula relacionadas) conforme exigido pelo ps0 (leia também 2.2.1 conforme as notas do CS 61A exigem) e, em seguida, Prólogo de Design de Software para Flexibilidade (SDF) , capítulo 1 e parcialmente Apêndice sobre Esquema.
Eu uso o esquema MIT.
Atualmente estou lendo o capítulo 2 do SDF e fazendo o exercício 2.5 (b).
O código a seguir tem resultados estranhos gerando erros ";O objeto quadrado não é aplicável." e ";O objeto (lambda(x)(quadrado x)) não é aplicável.". Aqui func_polynomial_minimal_unit
calcula algo como (f(f(g(x)))
ao ligar(func_polynomial_minimal_unit '((f . 2) (g . 1)))
(define (compose f g)
(define (the-composition . args)
(call-with-values (lambda () (apply g args))
f))
the-composition)
(define (iterate n)
(define (the-iterator f)
(if (= n 0)
identity
(compose f ((iterate (- n 1)) f))))
the-iterator)
(define (identity x) x)
(define (func_polynomial_minimal_unit . func_pow_pair_lst)
(if (null? (car func_pow_pair_lst)) ; contain one null pair
identity
(let ((cur_func_pow (caar func_pow_pair_lst)))
(newline)
(display cur_func_pow)
(compose
((iterate (cdr cur_func_pow)) (car cur_func_pow))
(func_polynomial_minimal_unit (cdr func_pow_pair_lst))))))
;; equivalent lambda for the following `func_polynomial_minimal_unit`.
((lambda (x) (expt (* x 9) (expt 2 3))) 3)
;; these works
((compose ((iterate 3) (lambda (x) (square x))) (lambda (x) (* 3 x))) 3)
((compose ((iterate 3) square) (lambda (x) (* 3 x))) 3)
;; these doesn't work
((func_polynomial_minimal_unit '((square . 3) ((lambda (x) (* 3 x)) . 2))) 3)
((func_polynomial_minimal_unit '(((lambda (x) (square x)) . 3) ((lambda (x) (* 3 x)) . 2))) 3)
Mas, como mostra o código acima, esses procedimentos podem ser aplicáveis. Então, por que esses erros são lançados?
Símbolos e variáveis são coisas diferentes. Os símbolos simples no código são variáveis (ou sintaxe semelhante
let
) e os mesmos símbolos em uma lista entre aspas são apenas símbolos que não têm nada a ver com a variávelsquare
ou com a variávela
Quando você escreve código como
(square a)
Scheme avalia o operador, a variávelsquare
. Como avalia um procedimento, ele avalia a variávela
e depois aplica o procedimento com os operandos avaliados.Agora, se eu fizesse uma lista, por exemplo.
to-apply
like(define to-apply '(square a)))
e tente imprimir isso,(display to-apply)
você verá exatamente o mesmo que escreveu porque o citou.(apply (car to-apply) (cdr to-apply))
fornecerá exatamente a mesma mensagem de erro que você encontrou, pois o símbolosquare
não é um procedimento.No entanto, se você definir como
(define to-apply (list square a)))
e então(display to-apply)
você verá algo como(#<procedure-suqare> 3)
e(apply (car to-apply) (cdr to-apply))
lhe dará9
Em vez disso,
list
você pode usar a sintaxe quaiquote:Como os números são autoavaliados, você não precisa retirá-los das aspas, mas se usar uma variável, precisará fazê-lo lá também :-)