scheme runtime-error racket

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)