[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

# 37. Programación

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 37.1 Lisp y Maxima

Maxima fue escrito en Lisp, y es muy fácil tener acceso a funciones y variables Lisp desde Maxima y viceversa. Los símbolos Lisp y los símblos Maxima están claramente diferenciados por medio de una convención de nombres. Un símblo Lisp el cual comienza con un signo pesos `$` corresponde a un símbolo Maxima sin el signo pesos. Un símbolo Maxima el cual comienza con un signo de cierre de interrogación `?` corresponde a un símbolo Lisp sin dicho signo. Por ejemplo, el símbolo Maxima `foo` corresponde a el símbolo Lisp `$FOO`, mientras que el símbolo Maxima `?foo` corresponde a el símbolo Lisp `FOO`, tenga en cuenta que `?foo` esta escrito sin espacio entre `?` y `foo`; de otra manera se estaría invocando a `describe ("foo")`.

El guión `-`, asterisco `*`, u otros carácteres especiales en símbolos Lisp deben ser escritos mediante un backslash `\` si aparecen en código Maxima. Por ejemplo, el identificador Lisp `*foo-bar*` se debe escribir `?\*foo\-bar\*` en Maxima.

Se puede ejecutar código Lisp desde una sesión de Maxima. Una línea Lisp (que contenga una o más formas) puede ser ejecutada por medio de un comando especial `:lisp`. Por ejemplo,

    (%i1) :lisp (foo $x $y)

se llama a la función Lisp `foo` con variables Maxima `x` y `y` como argumentos. La instrucción `:lisp` puede aparecer en el prompt interactivo o en un archivo que sea procesado por `batch` o `demo`, pero no en un archivo que sea procesado por `load`, `batchload`, `translate_file` o `compile_file`.

La función `to_lisp()` abre una sesión interactiva con el interprete Lisp. Escribiendo `(to-maxima)` se cierra la sesión con Lisp y se retorna a Maxima.

Las funciones y variables Lisp las cuales esten para ser visibles en Maxima como funciones y variables con nombres oridinarios (sin una puntuación especial), deben tener nombres tipo Lisp que comiencen con el signo pesos `$`.

Maxima distingue entre letras minúsculas y mayúsculas en identificadores. Existen algunas reglas que gobiernan la traducción de nombres entre Lisp y Maxima.

1. Un identificador Lisp que no se encuentra encerrado en barras verticales corresponde a un identificador Maxima en minúscula. Que el idenficador Lisp esté en mayúscula, minúscula o una combinación de ambas, no afecta en nada. Por ejemplo, los identificadores Lisp `$foo`, `$FOO`, y `$Foo`, todos corresponden al identificador Maxima `foo`. Esto es así porque `$foo`, `$FOO` y `$Foo` se convierten por defecto al símbolo `$FOO` de Lisp.
2. Un identificador Lisp el cual se encuentre todo en mayúscula o todo en minúscula y encerrado entre barras verticales corresponde a un identicador Maxima con el caso contrario. Esto es, de mayúsculas cambia a minúsculas y de minúsculas cambia a mayúsculas. E.g., el identificador Lisp `|$FOO|` y `|$foo|` corresponden los identificadores Maxima `foo` y `FOO`, respectivamente.
3. Un identificador Lisp el cual esta escrito mezclando letras mayúsculas y minúsculas y se encuentra entre barras verticales corresponde a un identificador Maxima con la misma escritura. E.g., el identificador Lisp `|$Foo|` corresponde a el identificador Maxima `Foo`.

La macro Lisp `#$` permite el uso de expresiones Maxima dentro de código Lisp. `#$expr$` extiende a una expresión Lisp equivalente a la expresión Maxima expr.

    (msetq $foo #$[x, y]$)

Esto tiene el mismo efecto que:

    (%i1) foo: [x, y];

La función Lisp `displa` imprime una expresión en formato Maxima.

    (%i1) :lisp #$[x, y, z]$
    ((MLIST SIMP) $X $Y $Z)
    (%i1) :lisp (displa '((MLIST SIMP) $X $Y $Z))
    [x, y, z]
    NIL

Las funciones definidas en Maxima no son funciones Lisp ordinarias. La función Lisp `mfuncall` llama a una función Maxima. Por ejemplo:

    (%i1) foo(x,y) := x*y$
    (%i2) :lisp (mfuncall '$foo 'a 'b)
    ((MTIMES SIMP) A B)

Algunas funciones Lisp son compartidas en el paquete Maxima, las cuales se listan a continuación:

`complement`, `continue`, `//`, `float`, `functionp`, `array`, `exp`, `listen`, `signum`, `atan`, `asin`, `acos`, `asinh`, `acosh`, `atanh`, `tanh`, `cosh`, `sinh`, `tan`, `break`, y `gcd`.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 37.2 Recolector de basura

La computación simbólica tiende a crear una buena cantidad de basura (resultados temporales que ya no serán utilizados), y un manejo efectivo de esto puede ser crucial para el término exitoso de algunos programas.

Bajo GCL (GNU Common Lisp), en aquellos sistemas UNIX donde la llamada al sistema mprotect está disponible (incluyendo SUN OS 4.0 y algunas variantes de BSD) se dispone de un recolector de basura estratificado. Véase la documentación de GCL para ALLOCATE y GBC. A nivel Lisp, ejecutando (setq si::*notify-gbc* t) pemitirá determinar qué áreas necesitan más espacio.

En cuanto al resto de Lisps bajo los que funciona Maxima, se remite al lector a la documentación correspondiente para controlar la recolección de basura.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 37.3 Introducción a la programación

Maxima dispone de los bucles `do` para hacer iteraciones, así como estructuras más primitivas del estilo de `go`.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 37.4 Funciones y variables para la programación

Función: backtrace ()
Función: backtrace (n)

  Devuelve la pila de llamadas, esto es, la lista de funciones que han llamado a la función actualmente activa.

  La llamada a `backtrace()` devuelve la pila completa de llamadas.

  Ejemplos:

      (%i1) h(x) := g(x/7)$
      (%i2) g(x) := f(x-11)$
      (%i3) f(x) := e(x^2)$
      (%i4) e(x) := (backtrace(), 2*x + 13)$
      (%i5) h(10);
      #0: e(x=4489/49)
      #1: f(x=-67/7)
      #2: g(x=10/7)
      #3: h(x=10)
                                    9615
      (%o5)                         ----
                                     49

  La llamada `backtrace (n)` devuelve las n funciones más recientes, incluyendo a la función actualmente activa.

  Ejemplos:

      (%i1) h(x) := (backtrace(1), g(x/7))$
      (%i2) g(x) := (backtrace(1), f(x-11))$
      (%i3) f(x) := (backtrace(1), e(x^2))$
      (%i4) e(x) := (backtrace(1), 2*x + 13)$
      (%i5) h(10);
      #0: h(x=10)
      #0: g(x=10/7)
      #0: f(x=-67/7)
      #0: e(x=4489/49)
                                    9615
      (%o5)                         ----
                                     49

Operador especial: do

  La sentencia `do` se utiliza para realizar iteraciones. Debido a su generalidad la sentencia `do` se describirá en dos partes. En primer lugar se mostrará su forma más usual, análoga a la de otros lenguajes de programación (Fortran, Algol, PL/I, etc.); después se mencionarán otras formas de uso.

  Hay tres variantes de esta sentencia que se diferencian entre sí únicamente por las condiciones de fin de bucle. Son las siguientes:

  - `for variable: valor_inicial step incremento thru límite do cuerpo`
  - `for variable: valor_inicial step incremento while condición do cuerpo`
  - `for variable: valor_inicial step incremento unless condición do cuerpo`

  El valor_inicial, el incremento, el límite y el cuerpo pueden ser cualquier tipo de expresión válida de Maxima. Si el incremento es igual a la unidad (1) entonces "`step 1`" puede omitirse.

  La ejecución de la sentencia `do` se realiza asignando el valor_inicial a la variable (llamada de aquí en adelante variable-control). A continuación: (1) si la variable-control ha excedido el límite de la especificación dada por un `thru`, o si la condición impuesta por `unless` es verdadera (`true`), o si la condición dada por `while` es falsa (`false`) entonces la iteración `do` termina. (2) El cuerpo se evalúa. (3) El incremento es sumado a la variable-control. El proceso de (1) a (3) se repite hasta que la condición de fin de iteración se satisfaga. También es posible especificar varias condiciones de terminación del bucle, en cuyo caso `do` terminará cuando se satisfaga alguna de ellas.

  En general la condición `thru` se satisfará cuando la variable-control sea mayor que el límite si el incremento es no negativo, o cuando la variable-control sea menor que el límite cuando el incremento es negativo. El incremento y el límite pueden ser expresiones no numéricas, tanto en cuanto esta desigualdad pueda quedar determinada. Sin embargo, a menos que el incremento sea un número negativo en el momento de comenzar el cómputo de `do`, Maxima supondrá que se evaluará a una cantidad positiva. En caso de no ser efectivamente positivo, la sentencia `do` puede dar un resultado inesperado.

  Nótese que el límite, el incremento y la condición de terminación se evalúan en cada iteración del bucle. Así, si alguna de expresiones necesitan de muchos cálculos y devuelven un resultado que no va a cambiar durante toda la ejecución del cuerpo, será más eficiente dar este valor a una variable antes de comenzar la sentencia `do` y utilizarla luego durante su ejecución.

  El valor que habitualmente devuelva la sentencia `do` será el átomo `done`. Sin embargo, la función `return` puede usarse dentro del cuerpo para salir de `do` de forma prematura retornando un valor determinado. Nótese no obstante que un `return` dentro de un `do` que está dentro de un bloque (`block`) provocará una salida de `do` pero no de `block`. Repárese también en que la función `go` no puede usarse para salir de `do` e ir a algún lugar de `block`.

  La variable-control es siempre local respecto de `do`, por lo que se puede utilizar cualquier nombre de variable sin afectar el valor de cualquier otra variable externa a `do` y que tenga el mismo nombre. La variable-control no tendrá asignado ningún valor una vez se haya concluido el `do`.

      (%i1) for a:-3 thru 26 step 7 do display(a)$
                                   a = - 3

                                    a = 4

                                   a = 11

                                   a = 18

                                   a = 25

      (%i1) s: 0$
      (%i2) for i: 1 while i <= 10 do s: s+i;
      (%o2)                         done
      (%i3) s;
      (%o3)                          55

  Nótese que la condición `while i <= 10` es equivalente a `unless i > 10` y a `thru 10`.

      (%i1) series: 1$
      (%i2) term: exp (sin (x))$
      (%i3) for p: 1 unless p > 7 do
                (term: diff (term, x)/p,
                 series: series + subst (x=0, term)*x^p)$
      (%i4) series;
                        7    6     5    4    2
                       x    x     x    x    x
      (%o4)            -- - --- - -- - -- + -- + x + 1
                       90   240   15   8    2

  lo que da ocho términos del desarrollo de Taylor de la función `e^sin(x)`.

      (%i1) poly: 0$
      (%i2) for i: 1 thru 5 do
                for j: i step -1 thru 1 do
                    poly: poly + i*x^j$
      (%i3) poly;
                        5      4       3       2
      (%o3)          5 x  + 9 x  + 12 x  + 14 x  + 15 x
      (%i4) guess: -3.0$
      (%i5) for i: 1 thru 10 do
                (guess: subst (guess, x, 0.5*(x + 10/x)),
                 if abs (guess^2 - 10) < 0.00005 then return (guess));
      (%o5)                  - 3.162280701754386

  Este ejemplo calcula la raíz cuadrada negativa de 10 haciendo 10 iteraciones del método de Newton-Raphson. De no haberse alcanzado el criterio de convergencia el valor devuelto hubiese sido `done`.

  En lugar de añadir siempre una cantidad a la variable-control a veces se puede querer que cambie en cada iteración siguiendo algún otro criterio. En tal caso se puede hacer uso de `next expresión` en lugar de `step incremento`. Esto hará que a la variable-control se le asigne el resultado de evaluar la expresión en cada iteración del bucle.

      (%i6) for count: 2 next 3*count thru 20 do display (count)$
                                  count = 2

                                  count = 6

                                 count = 18

  En ocasiones puede interesar realizar una iteración en la que la variable-control no se utilice nunca. Se podrá entonces dar únicamente las condiciones de terminación del bucle omitiendo la inicialización y actualizando la información, tal como se hace en el siguiente ejemplo para calcular la raíz cuadrada de 5 utilizando un valor inicial alejado de la solución.

      (%i1) x: 1000$
      (%i2) thru 20 do x: 0.5*(x + 5.0/x)$
      (%i3) x;
      (%o3)                   2.23606797749979
      (%i4) sqrt(5), numer;
      (%o4)                   2.23606797749979

  Si así se quiere, incluso es posible omitir las condiciones de terminación completamente y escribir únicamente `do body`, lo que provocará entrar en un bucle infinito. En tal caso, debería usarse la función `return` a fin de terminar con la ejecución de `do`.

      (%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x),
                do (y: ev(df), x: x - f(x)/y,
                    if abs (f (x)) < 5e-6 then return (x)))$
      (%i2) sqr (x) := x^2 - 5.0$
      (%i3) newton (sqr, 1000);
      (%o3)                   2.236068027062195

  (En este ejemplo, cuando se ejecuta `return` obliga a que sea `x` el valor devuelto por `do`. Al salirse del bloque, `x` es también el valor que devuelve `block` por ser `do` la última sentencia del bloque.)

  Hay todavía otra forma de `do` en Maxima. Su sintaxis es:

      for variable in lista test_de_parada do cuerpo

  Los elementos de list son cualesquiera expresiones que se irán asignando sucesivamente a la variable en cada repetición del cuerpo. El test de parada end_tests (que es opcional) puede usarse para terminar la ejecución de `do`; de otro modo las iteraciones se pararán cuando la lista se haya agotado o cuando se ejecute un `return` dentro del cuerpo. (De hecho, la lista puede ser cualquier expresión no atómica, de la cual se irán extrayendo de forma sucesiva sus diferentes partes.)

      (%i1)  for f in [log, rho, atan] do ldisp(f(1))$
      (%t1)                                  0
      (%t2)                                rho(1)
                                           %pi
      (%t3)                                 ---
                                            4
      (%i4) ev(%t3,numer);
      (%o4)                             0.78539816

Función: errcatch (expr_1, ..., expr_n)

  Evalúa las expresiones expr_1, ..., expr_n una a una y devuelve `[expr_n]` (una lista) en caso de que no ocurra ningún error. En caso de aparecer algún error durante el cálculo de alguno de los argumentos, `errcatch` evita que el error se propague y devuelve la lista vacía `[]` sin evaluar más argumentos.

  La función `errcatch` es útil en ficheros `batch` donde se sospeche que pueda aparecer algún error, el cual provocaría la terminación de la ejecución del `batch` de no ser previamente detectado.

Función: error (expr_1, ..., expr_n)
Variable del sistema: error

  Calcula y devuelve expr_1, ..., expr_n, enviando posteriormente una seãl de error a Maxima o al `errcatch` más cercano.

  A la variable `error` se le asigna una lista con la descripción del error. El primer elemento de `error` es una cadena de formato, la cual une todas las cadenas de los argumentos expr_1, ..., expr_n, siendo los demás elementos de la lista los valores de los argumentos que no son cadenas.

  La llamada a `errormsg()` formatea e imprime `error`. Se reimprime así el mensaje de error más reciente.

Variable opcional: error_size

  Valor por defecto: 10

  La variable `error_size` modifica los mensajes de error de acuerdo con el tamaño de las expresiones que aparecen en él. Si el tamaño de una expresión (tal como lo determina la función Lisp `ERROR-SIZE`) es mayor que `error_size`, la expresión se reemplaza en el mensaje por un símbolo, asignándole a éste una expresión. Los símbolos se toman de la lista `error_syms`.

  En caso contrario, si la expresión es menor que `error_size`, la expresión se muestra en el propio mensaje.

  Véanse también `error` y `error_syms`.

  Ejemplo:

  El tamaño de `U`, tal como lo determina `ERROR-SIZE`, es 24.

      (%i1) U: (C^D^E + B + A)/(cos(X-1) + 1)$

      (%i2) error_size: 20$

      (%i3) error ("Example expression is", U);

      Example expression is errexp1
       -- an error.  Quitting.  To debug this try debugmode(true);
      (%i4) errexp1;
                                  E
                                 D
                                C   + B + A
      (%o4)                    --------------
                               cos(X - 1) + 1
      (%i5) error_size: 30$

      (%i6) error ("Example expression is", U);

                               E
                              D
                             C   + B + A
      Example expression is --------------
                            cos(X - 1) + 1
       -- an error.  Quitting.  To debug this try debugmode(true);

Variable opcional: error_syms

  Valor por defecto: `[errexp1, errexp2, errexp3]`

  En los mensajes de error, las expresiones mayores que `error_size` son reemplazadas por símbolos a los cuales se les asignas estas expresiones. Los símbolos se toman de la lista `error_syms`. La primera expresión que resulte ser demasiado larga se reemplaza por `error_syms[1]`, la segunda por `error_syms[2]` y así sucesivamente.

  Si hay más expresiones largas que elementos en `error_syms`, los símbolos se construyen automáticamente, siendo el n-ésimo símbolo equivalente a `concat ('errexp, n)`.

  Véanse también `error` y `error_size`.

Función: errormsg ()

  Reimprime el mensaje de error más reciente. La variable `error` guarda el mensaje y `errormsg` lo formatea e imprime.

Variable opcional: errormsg

  Valor por defecto: `true`

  Cuando `errormsg` vale `false` se suprimen los contenidos de los mensajes de error.

  La variable `errormsg` no se puede asignar a un valor local dentro de un bloque. El valor global de `errormsg` está siempre presente.

  Ejemplos:

      (%i1) errormsg;
      (%o1)                                true
      (%i2) sin(a,b);
      Wrong number of arguments to sin
       -- an error. To debug this try: debugmode(true);
      (%i3) errormsg:false;
      (%o3)                                false
      (%i4) sin(a,b);

       -- an error. To debug this try: debugmode(true);

  La variable `errormsg` no se puede asignar a un valor local dentro de un bloque.

      (%i1) f(bool):=block([errormsg:bool],
                           print ("value of errormsg is",errormsg))$
      (%i2) errormsg:true;
      (%o2)                                true
      (%i3) f(false);
      value of errormsg is true
      (%o3)                                true
      (%i4) errormsg:false;
      (%o4)                                false
      (%i5) f(true);
      value of errormsg is false
      (%o5)                                false

Operador especial: for

  Utilizado en las iteraciones. Véase `do` para una descripción de las técnicas de iteración en Maxima.

Función: go (etiqueta)

  Se utiliza dentro de un bloque (`block`) para transferir el control a la sentencia del bloque que esté etiquetada con el argumento de `go`. Una sentencia queda etiquetada cuando está precedida por un argumento de tipo átomo como cualquier otra sentencia de `block`. Por ejemplo:

      block ([x], x:1, tururu, x+1, ..., go(tururu), ...)

  El argumento de `go` debe ser el nombre de una etiqueta que aparezca en el mismo bloque (`block`). No se puede utilizar `go` para transferir el control a un bloque que no sea aquel que contenga la sentencia `go`.

Operador especial: if

  Evaluación condicionada. Se reconocen varias formas de expresiones `if`.

  La expresión `if cond_1 then expr_1 else expr_0` devuelve expr_1 si cond_1 vale `true`, en caso contrario la respuesta es `expr_0`.

  La expresión `if cond_1 then expr_1 elseif cond_2 then expr_2 elseif ... else expr_0` devuelve expr_k si cond_k vale `true` y todas las condiciones anteriores toman el valor `false`. Si ninguna de las condiciones vale `true`, la respuesta es `expr_0`.

  La falta de un `else` final se interpreta como un `else false`; esto es, la expresión `if cond_1 then expr_1` equivale a `if cond_1 then expr_1 else false`, y `if cond_1 then expr_1 elseif ... elseif cond_n then expr_n` equivale a su vez a `if cond_1 then expr_1 elseif ... elseif cond_n then expr_n else false`.

  Las alternativas expr_0, ..., expr_n pueden ser expresiones válidas de Maxima, incluidas expresiones `if` anidadas. Las alternativas ni se simplifican ni se evalúan, a menos que su condición asociada valga `true`.

  Las condiciones cond_1, ..., cond_n deben ser expresiones capaces de dar como resultado `true` o `false` al ser evaluadas. Si en un momento dado una condición no da como resultado un valor de verdad (`true` o `false`), el comportamiento de `if` se controla con la variable global `prederror`. Si `prederror` vale `true`, se considera un error que la condición evaluada no dé como resultado un valor de verdad; en caso contrario, las condiciones que no den como resultado un valor de verdad se aceptan, dándose el resultado como una expresión condicional.

  Las condiciones pueden contener operadores lógicos y relacionales, así como otros elementos, tal como se indica a continuación:

      Operación               Símbolo     Tipo

      menor que               <           operador relacional infijo
      menor o igual que       <=          operador relacional infijo
      igualdad (sintáctica)   =           operador relacional infijo
      negación de =           #           operador relacional infijo
      igualdad (por valor)    equal       operador relacional infijo
      negación de equal       notequal    operador relacional infijo
      mayor o igual que       >=          operador relacional infijo
      mayor que               >           operador relacional infijo
      y                       and         operador lógico infijo
      o                       or          operador lógico infijo
      no                      not         operador lógico prefijo

Función: map (f, expr_1, ..., expr_n)

  Devuelve una expresión cuyo operador principal es el mismo que aparece en las expresiones expr_1, ..., expr_n pero cuyas subpartes son los resultados de aplicar f a cada una de las subpartes de las expresiones; f puede ser tanto el nombre de una función de n argumentos como una expresión `lambda` de n argumentos.

  Uno de los usos que tiene `map` es la de aplicar (o mapear) una función (por ejemplo, `partfrac`) sobre cada término de una expresión extensa en la que normalmente no se podría utilizar la función debido a insuficiencias en el espacio de almacenamiento durante el curso de un cálculo.

      (%i1) map(f,x+a*y+b*z);
      (%o1)                        f(b z) + f(a y) + f(x)
      (%i2) map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2));
                                 1       1        1
      (%o2)                     ----- - ----- + -------- + x
                               x + 2   x + 1          2
                                               (x + 1)
      (%i3) map(ratsimp, x/(x^2+x)+(y^2+y)/y);
                                            1
      (%o3)                            y + ----- + 1
                                          x + 1
      (%i4) map("=",[a,b],[-0.5,3]);
      (%o4)                          [a = - 0.5, b = 3]

  Véase también `maperror` .

Función: mapatom (expr)

  Devuelve `true` si y sólo expr es tratado por las rutinas de mapeo como un átomo.

Variable opcional: maperror

  Valor por defecto: `true`

  Cuando `maperror` toma el valor `false`, hace que todas las funciones de mapeo, como por ejemplo

      map (f, expr_1, expr_2, ...)

  (1) paren cuando hayan terminado de procesar la expr_i más corta, a menos que todas ellas sean del mismo tamaño y (2) apliquen `f` a `[expr_1, expr_2, ...]` si es el caso que las `expr_i` no son todas del mismo tipo de objeto.

  Cuando `maperror` toma el valor `true` entonces se emite un mensaje de error cuando se presenta cualquiera de los dos casos anteriores.

Variable opcional: mapprint

  Valor por defecto: `true`

  Si `mapprint` vale `true`, se producirán ciertos mensajes por parte de las funciones `map`, `mapl` y `fullmap` en determinadas situaciones, como cuando `map` hace uso de `apply`.

  Si `mapprint` vale `false`, no se emitirán tales mensajes.

Función: maplist (f, expr_1, ..., expr_n)

  Devuelve una lista con las aplicaciones de f a las partes de las expresiones expr_1, ..., expr_n; f es el nombre de una función ou una expresión lambda.

  La función `maplist` difiere de `map (f, expr_1, ..., expr_n)`, la cual devuelve una expresión con el mismo operador principal que tenga expr_i, excepto en simplificaciones y en el caso en el que `map` hace un `apply`.

Variable opcional: prederror

  Valor por defecto: `false`

  Cuando `prederror` toma el valor `true`, se emite un mensaje de error siempre que el predicado de una sentencia `if` o de una función `is` no se pueda evaluar ni a verdadero (`true`) ni a falso (`false`).

  Si toma el valor `false`, se devuelve bajo las mismas circunstancias anteriores el valor `unknown`. El modo `prederror: false` no está soportado en el código traducido; sin embargo, `maybe` está soportado en código traducido.

  Véanse también `is` y `maybe`.

Función: return (valor)

  Puede utilizarse para salir de un bloque, devolviendo su argumento. Véase `block` para más información.

Función: scanmap (f, expr)
Función: scanmap (f, expr, bottomup)

  Aplica recursivamente f sobre expr, de arriba hacia abajo. Esto es más útil cuando se busca una factorización completa, por ejemplo:

      (%i1) exp:(a^2+2*a+1)*y + x^2$
      (%i2) scanmap(factor,exp);
                                          2      2
      (%o2)                         (a + 1)  y + x

  Nótese que cómo `scanmap` aplica la función dada `factor` a las subexpresiones que forman a expr; si se presenta otra forma de expr a `scanmap` entonces el resultado puede ser diferente. Así, `%o2` no se restaura cuando `scanmap` se aplica a la forma expandida de exp:

      (%i3) scanmap(factor,expand(exp));
                                 2                  2
      (%o3)                      a  y + 2 a y + y + x

  Aquí hay otro ejemplo de la forma en que `scanmap` aplica recursivamente una función dada a todas las subexpresiones, incluyendo exponentes:

      (%i4) expr : u*v^(a*x+b) + c$
      (%i5) scanmap('f, expr);
                          f(f(f(a) f(x)) + f(b))
      (%o5) f(f(f(u) f(f(v)                      )) + f(c))

  `scanmap (f, expr, bottomup)` aplica f a expr de abajo hacia arriba. Por ejemplo, para `f` no definida,

      scanmap(f,a*x+b) ->
         f(a*x+b) -> f(f(a*x)+f(b)) -> f(f(f(a)*f(x))+f(b))
      scanmap(f,a*x+b,bottomup) -> f(a)*f(x)+f(b)
          -> f(f(a)*f(x))+f(b) ->
           f(f(f(a)*f(x))+f(b))

  En este caso se obtiene la misma respuesta por cualquiera de los dos métodos.

Función: throw (expr)

  Evalúa expr y devuelve el valor del `catch` más reciente. La función `throw` se utiliza junto con `catch` como un mecanismo de retorno no local.

Operador especial: while
Operador especial: unless

  Véase `do`.

Función: outermap (f, a_1, ..., a_n)

  Aplica la función f a cada uno de los elementos del producto vectorial a_1 por a_2 ... por a_n.

  El argumento f debe ser el nombre de una función de n argumentos, o una expresión lambda de n argumentos. Cada uno de los argumentos a_k puede ser una lista, una lista anidada, una matriz o cualquier otro tipo de expresión.

  El valor devuelto por `outermap` es una estructura anidada. Si x es la respuesta dada por `outermap`, entonces tiene la misma estructura que la primera lista, lista anidada o matriz, `x[i_1]...[i_m]` tiene la misma estructura que la segunda lista, lista anidada o matriz, `x[i_1]...[i_m][j_1]...[j_n]` tiene la misma estructura que la tercera lista, lista anidada o matriz, y así sucesivamente, siendo m, n, ... los números índice necesarios para acceder a los elementos de cada argumento: uno para las listas, dos para las matrices y uno o más para las listas anidadas. Aquellos argumentos que no sean listas ni matrices no tienen efecto alguno sobre la estructura del valor retornado.

  Nótese que el efecto producido por `outermap` es diferente del que se obtiene al aplicar f a cada uno de los elementos del producto devuelto por `cartesian_product`. La función `outermap` mantiene la estructura de los argumentos en la respuesta, miemtras que `cartesian_product` no lo hace.

  La función `outermap` evalúa sus argumentos.

  Véanse también `map`, `maplist` y `apply`.

  Ejemplos:

  Ejemplos elementales de uso de `outermap`. Con el fin de mostrar con mayor claridad las combinaciones del argumento, se mantiene sin definir `F`.

      (%i1) outermap (F, [a, b, c], [1, 2, 3]);
      (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)],
                                           [F(c, 1), F(c, 2), F(c, 3)]]
      (%i2) outermap (F, matrix ([a, b], [c, d]), matrix ([1, 2], [3, 4]));
               [ [ F(a, 1)  F(a, 2) ]  [ F(b, 1)  F(b, 2) ] ]
               [ [                  ]  [                  ] ]
               [ [ F(a, 3)  F(a, 4) ]  [ F(b, 3)  F(b, 4) ] ]
      (%o2)    [                                            ]
               [ [ F(c, 1)  F(c, 2) ]  [ F(d, 1)  F(d, 2) ] ]
               [ [                  ]  [                  ] ]
               [ [ F(c, 3)  F(c, 4) ]  [ F(d, 3)  F(d, 4) ] ]
      (%i3) outermap (F, [a, b], x, matrix ([1, 2], [3, 4]));
             [ F(a, x, 1)  F(a, x, 2) ]  [ F(b, x, 1)  F(b, x, 2) ]
      (%o3) [[                        ], [                        ]]
             [ F(a, x, 3)  F(a, x, 4) ]  [ F(b, x, 3)  F(b, x, 4) ]
      (%i4) outermap (F, [a, b], matrix ([1, 2]), matrix ([x], [y]));
             [ [ F(a, 1, x) ]  [ F(a, 2, x) ] ]
      (%o4) [[ [            ]  [            ] ],
             [ [ F(a, 1, y) ]  [ F(a, 2, y) ] ]
                                    [ [ F(b, 1, x) ]  [ F(b, 2, x) ] ]
                                    [ [            ]  [            ] ]]
                                    [ [ F(b, 1, y) ]  [ F(b, 2, y) ] ]
      (%i5) outermap ("+", [a, b, c], [1, 2, 3]);
      (%o5) [[a + 1, a + 2, a + 3], [b + 1, b + 2, b + 3],
                                                 [c + 1, c + 2, c + 3]]

  El siguiente ejemplo permite hacer un análisis más profundo del valor retornado por `outermap`. Los tres primeros argumentos son una matriz, una lista y otra matriz, en este orden. El valor devuelto es una matriz, cuyos elementos son listas y cada elemento de cada una de estas listas es a su vez una matriz.

      (%i1) arg_1 :  matrix ([a, b], [c, d]);
                                  [ a  b ]
      (%o1)                       [      ]
                                  [ c  d ]
      (%i2) arg_2 : [11, 22];
      (%o2)                       [11, 22]
      (%i3) arg_3 : matrix ([xx, yy]);
      (%o3)                      [ xx  yy ]
      (%i4) xx_0 : outermap(lambda([x, y, z], x / y + z), arg_1,
                                                         arg_2, arg_3);
                     [  [      a        a  ]  [      a        a  ]  ]
                     [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                     [  [      11       11 ]  [      22       22 ]  ]
      (%o4)  Col 1 = [                                              ]
                     [  [      c        c  ]  [      c        c  ]  ]
                     [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                     [  [      11       11 ]  [      22       22 ]  ]
                       [  [      b        b  ]  [      b        b  ]  ]
                       [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                       [  [      11       11 ]  [      22       22 ]  ]
               Col 2 = [                                              ]
                       [  [      d        d  ]  [      d        d  ]  ]
                       [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                       [  [      11       11 ]  [      22       22 ]  ]
      (%i5) xx_1 : xx_0 [1][1];
                 [      a        a  ]  [      a        a  ]
      (%o5)     [[ xx + --  yy + -- ], [ xx + --  yy + -- ]]
                 [      11       11 ]  [      22       22 ]
      (%i6) xx_2 : xx_0 [1][1] [1];
                            [      a        a  ]
      (%o6)                 [ xx + --  yy + -- ]
                            [      11       11 ]
      (%i7) xx_3 : xx_0 [1][1] [1] [1][1];
                                        a
      (%o7)                        xx + --
                                        11
      (%i8) [op (arg_1), op (arg_2), op (arg_3)];
      (%o8)                  [matrix, [, matrix]
      (%i9) [op (xx_0), op (xx_1), op (xx_2)];
      (%o9)                  [matrix, [, matrix]

  La función `outermap` mantiene la estructura de los argumentos en su respuesta, mientras que `cartesian_product` no lo hace.

      (%i1) outermap (F, [a, b, c], [1, 2, 3]);
      (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)],
                                           [F(c, 1), F(c, 2), F(c, 3)]]
      (%i2) setify (flatten (%));
      (%o2) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3),
                                             F(c, 1), F(c, 2), F(c, 3)}
      (%i3) map (lambda ([L], apply (F, L)), cartesian_product ({a, b, c}, {1, 2, 3}));
      (%o3) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3),
                                             F(c, 1), F(c, 2), F(c, 3)}
      (%i4) is (equal (%, %th (2)));
      (%o4)                         true

[ << ] | [ >> ] |  |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

This document was generated by Viktor T. Toth on septiembre, 27 2018 using texi2html 1.76.