scheme - Mi código señala el error "aplicación: no es un procedimiento" o "llamada a no procedimiento"
runtime-error racket (1)
Porque esta sucediendo
Las llamadas a procedimiento / función de esquema se ven así:
(operator operand ...)
Tanto el operador como los operandos pueden ser variables como
test
y
+
que se evalúan con diferentes valores.
Para que una llamada al procedimiento funcione, debe ser un procedimiento.
Del mensaje de error parece probable que la
test
no sea un procedimiento sino la lista
(1 2 3)
.
Todas las partes de un formulario también pueden ser expresiones, por lo que algo como
((proc1 4) 5)
es una sintaxis válida y se espera que la llamada
(proc1 4)
devuelva un procedimiento que luego se llama con
5
como único argumento.
Errores comunes que producen estos errores.
Intentando agrupar expresiones o crear un bloque
(if (< a b)
((proc1)
(proc2))
#f)
Cuando el predicado / prueba es verdadero, Scheme asume que intentará evaluar tanto
(proc1)
como
(proc2)
luego llamará al resultado de
(proc1)
debido a los paréntesis.
Para crear un bloque en Scheme, use
begin
:
(if (< a b)
(begin
(proc1)
(proc2))
#f)
En esto
(proc1)
se llama solo por efecto y el resultado de la forma será el resultado de la última expresión
(proc2)
.
Procedimientos de sombreado
(define (test list)
(list (cdr list) (car list)))
Aquí el parámetro se llama
list
que hace que la
list
procedimientos no esté disponible durante la duración de la llamada.
Una variable solo puede ser un procedimiento o un valor diferente en Scheme y el enlace más cercano es el que obtiene tanto en la posición del operador como en la del operando.
Este sería un error típico cometido por common-lispers ya que en CL pueden usar
list
como argumento sin meterse con la
list
funciones.
envolviendo variables en
cond
(define test #t) ; this might be result of a procedure
(cond
((< 5 4) result1)
((test) result2)
(else result3))
Si bien, además de la expresión de predicado
(< 5 4)
(test)
parece correcta, ya que es un valor que se verifica para thurthness, tiene más en común con el término
else
y debería escribirse así:
(cond
((< 5 4) result1)
(test result2)
(else result3))
Un procedimiento que debería devolver un procedimiento no siempre
Dado que Scheme no exige el tipo de devolución, su procedimiento puede devolver un procedimiento en una situación y un valor que no es de procedimiento en otra.
(define (test v)
(if (> v 4)
(lambda (g) (* v g))
''(1 2 3)))
((test 5) 10) ; ==> 50
((test 4) 10) ; ERROR! application: not a procedure
Valores indefinidos como
#<void>
,
#!void
#<undef>
,
#<undef>
y
#<unspecified>
#<undef>
#<unspecified>
¡Estos son generalmente valores devueltos por formas mutantes como
set!
,
set-car!
,
set-cdr!
,
define
.
(define (test x)
((set! f x) 5))
(test (lambda (x) (* x x)))
¡El resultado de este código es indeterminado desde que se
set!
puede devolver
cualquier valor
y sé que algunas implementaciones de esquemas como MIT Scheme en realidad devuelven el valor enlazado o el valor original y el resultado sería
25
o
10
, pero en muchas implementaciones obtienes un valor constante como
#<void>
y dado que no es un procedimiento obtiene el mismo error.
Confiar en un método de implementación de usar bajo especificación hace que usted obtenga un código no portátil.
Pasar argumentos en orden incorrecto
Imagina que tienes una función como esta:
(define (double v f)
(f (f v)))
(double 10 (lambda (v) (* v v))) ; ==> 10000
Si por error intercambió los argumentos:
(double (lambda (v) (* v v)) 10) ; ERROR: 10 is not a procedure
En las funciones de orden superior, como
fold
y
map
no pasar los argumentos en el orden correcto producirá un error similar.
Intentando aplicar como en lenguajes derivados de Algol
En lenguajes algol, como JavaScript y C ++, cuando se trata de aplicar
fun
con argumentos
arg
se ve así:
fun(arg)
Esto se interpreta como dos expresiones separadas en Scheme:
fun ; ==> valuates to a procedure object
(arg) ; ==> call arg with no arguments
La forma correcta de aplicar
fun
con
arg
como argumento es:
(fun arg)
Paréntesis superfluos
Este es el general "atrapar todos" otros errores.
Un código como
((+ 4 5))
no funcionará en Scheme ya que cada conjunto de paréntesis en esta expresión es una llamada a procedimiento.
Simplemente no puede agregar tantos como desee y, por lo tanto, debe mantenerlo
(+ 4 5)
.
¿Por qué permitir que ocurran estos errores?
Las expresiones en la posición del operador y permiten llamar variables como funciones de biblioteca le dan poderes expresivos al lenguaje. Estas son características que te encantarán tener cuando te hayas acostumbrado.
Aquí hay un ejemplo de
abs
:
(define (abs x)
((if (< x 0) - values) x))
Esto cambió entre hacer
(- x)
y
(values x)
(identidad que devuelve su argumento) y, como puede ver, llama al resultado de una expresión.
Aquí hay un ejemplo de
copy-list
usando cps:
(define (copy-list lst)
(define (helper lst k)
(if (null? lst)
(k ''())
(helper (cdr lst)
(lambda (res) (k (cons (car lst) res))))))
(helper lst values))
Observe que
k
es una variable a la que le pasamos una función y que se llama como una función.
Si pasamos algo más que una función allí, obtendría el mismo error.
¿Es esto exclusivo de Scheme?
De ningún modo. Todos los idiomas con un espacio de nombres que pueden pasar funciones como argumentos tendrán desafíos similares. A continuación se muestra un código JavaScript con problemas similares:
function double (f, v) {
return f(f(v));
}
double(v => v * v, 10); // ==> 10000
double(10, v => v * v);
; TypeError: f is not a function
; at double (repl:2:10)
// similar to having extra parentheses
function test (v) {
return v;
}
test(5)(6); // == TypeError: test(...) is not a function
// But it works if it''s designed to return a function:
function test2 (v) {
return v2 => v2 + v;
}
test2(5)(6); // ==> 11
Durante la ejecución de mi código obtengo los siguientes errores en las diferentes implementaciones de Scheme:
Raqueta:
application: not a procedure;
expected a procedure that can be applied to arguments
given: ''(1 2 3)
arguments...:
Ikarus:
Unhandled exception
Condition components:
1. &assertion
2. &who: apply
3. &message: "not a procedure"
4. &irritants: ((1 2 3))
Pollo:
Error: call of non-procedure: (1 2 3)
Gambito:
*** ERROR IN (console)@2.1 -- Operator is not a PROCEDURE
((1 2 3) 4)
Esquema MIT:
;The object (1 2 3) is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
Esquema Chez:
Exception: attempt to apply non-procedure (1 2 3)
Type (debug) to enter the debugger.
Engaño:
ERROR: In procedure (1 2 3):
ERROR: Wrong type to apply: (1 2 3)
Chibi:
ERROR in final-resumer: non procedure application: (1 2 3)