Siguiente: , Anterior:   [Índice general][Índice]

6 Operadores


6.1 Introducción a los operadores

Maxima reconoce los operadores aritméticos, relacionales y lógicos usuales de la matemática. Además, Maxima dispone de operadores para la asignación de valores a variables y la definición de funciones. La siguiente tabla muestra los operadores que se describen en este capítulo, en la que se incluye el nombre del operador, el rango de enlace por la izquierda lbp, el rango de enlace por la derecha rbp, el tipo de operador y un ejemplo, para finalizar, en cada caso, con su formato interno tal como es leída por el analizador sintáctico.

Operador  lbp rbp  Tipo     Ejemplo  Formato interno
                       
   +      100 134  nary     a+b      ((mplus) $A $B)
   -      100 134  prefix   -a       ((mminus) $A)
   *      120      nary     a*b      ((mtimes) $A $B)
   /      120 120  infix    a/b      ((mquotient) $A $B)
   ^      140 139  infix    a^b      ((mexpt) $A $B)
   **     140 139  infix    a**b     ((mexpt) $A $B)
   ^^     140 139  infix    a^^b     ((mncexpt) $A $B)
   .      130 129  infix    a.b      ((mnctimes) $A $B)
                                     
   <       80  80  infix    a<b      ((mlessp) $A $B)
   <=      80  80  infix    a<=b     ((mleqp) $A $B)
   >       80  80  infix    a>b      ((mqreaterp) $A $B)
   >=      80  80  infix    a>=b     ((mgeqp) $A $B)
                                     
   not         70  prefix   not a    ((mnot) $A)
   and     65      nary     a and b  ((mand) $A $B)
   or      60      nary     a or b   ((mor) $A $B)
                                     
   #       80  80  infix    a#b      ((mnotequal) $A $B)
   =       80  80  infix    a=b      ((mequal) $A $B)
                                     
   :      180  20  infix    a:b      ((msetq) $A $B)
   ::     180  20  infix    a::b     ((mset) $A $B)
   :=     180  20  infix    a:=b     ((mdefine) $A $B)
   ::=    180  20  infix    a::=b    ((mdefmacro) $A $B)

Con los rangos de enlace de los operadores se definen las reglas de prioridad de cálculo de los mismos. Así, por ejemplo, el analizador sintáctico interpreta la expresión a + b * c como a + (b * c) , pues el rango de enlace por la izquierda de la multiplicación es mayor que rango de enlace por la izquierda de la suma.

Maxima clasifica los operadores de la siguiente manera:

Prefijo (prefix)

Los operadores prefijos son unarios con un único operando que se escribe a continuación del operando. Ejemplos son - y not.

Sufijo (postfix)

Los operadores sufijos son unarios con un único operando que se escribe precediendo al operando. Un ejemplo es el factorial !.

Infijo (infix)

Los operadores infijos son operadores binarios que necesitan dos operandos, los cuales se colocan uno a cada lado del operador. Ejemplos son el operador para la exponenciación, ^, y el operador de asignación, :.

N-ario (n-ary)

Los operadores n-arios admiten un número arbitrario de operandos. Son ejemplos la multiplicación, *, y la suma, +.

Acotador (matchfix)

Los acotadores son operadores que se utilizan para establecer el comienzo y final de una lista de operandos. Los operadores [ y ] son ejemplos de acotadores, que se utilizan para definir una lista tal como [a, b, ...].

No-fijo (nofix)

Un operador no-fijo carece de operandos. Maxima no tiene operadores internos no-fijos, pero se pueden crear como cuando se escribe nofix(quit), lo que permite obviar el uso de paréntesis, y utilizar simplemente quit en lugar de quit(), para cerrar una sesión de Maxima.

En la sección dedicada a los operadores definidos por el usuario se describe cómo redefinir los operadores internos de Maxima y cómo crear otros nuevos.

El mecanismo para definir un nuevo operador es sencillo. Tan solo es necesario declarar una función como operador; la función operador puede estar definida o no.

Un ejemplo de operador definido por el usuario es el siguiente. Nótese que la llamada a función "dd" (a) equivale a dd a, de igual manera que "<-" (a, b) también equivale a a <- b. Nótese también que las funciones "dd" y "<-" no están definidas en este ejemplo.

(%i1) prefix ("dd");
(%o1)                          dd
(%i2) dd a;
(%o2)                         dd a
(%i3) "dd" (a);
(%o3)                         dd a
(%i4) infix ("<-");
(%o4)                          <-
(%i5) a <- dd b;
(%o5)                      a <- dd b
(%i6) "<-" (a, "dd" (b));
(%o6)                      a <- dd b

La tabla anterior no incluye todos los operadores definidos en Maxima, ya que también lo son ! para el factorial, for, do y while para programar bucles, o if, then y else para definir condicionales.

Las funciones remove y kill eliminan propiedades de operadores de un átomo. La llamada remove ("a", op) sólo elimina las propiedades de operador de a. La llamada kill ("a") elimina todas las propiedades de a, incluidas las propiedades de operador. Nótese que el nombre del operador debe ir entre comillas.

(%i1) infix ("##");
(%o1)                          ##
(%i2) "##" (a, b) := a^b;
                                     b
(%o2)                     a ## b := a
(%i3) 5 ## 3;
(%o3)                          125
(%i4) remove ("##", op);
(%o4)                         done
(%i5) 5 ## 3;
Incorrect syntax: # is not a prefix operator
5 ##
  ^
(%i5) "##" (5, 3);
(%o5)                          125
(%i6) infix ("##");
(%o6)                          ##
(%i7) 5 ## 3;
(%o7)                          125
(%i8) kill ("##");
(%o8)                         done
(%i9) 5 ## 3;
Incorrect syntax: # is not a prefix operator
5 ##
  ^
(%i9) "##" (5, 3);
(%o9)                       ##(5, 3)

6.2 Operadores aritméticos

Operador: +
Operador: -
Operador: *
Operador: /
Operador: ^

Los símbolos + * / y ^ representan la suma, resta, multiplicación, división y exponenciación, respectivamente. Los nombres de estos operadores son "+" "*" "/" y "^", que pueden aparecer allá donde se requiera el nombre de una función u operador.

Los símbolos + y - representan el positivo y negativo unario, siendo los nombres de estos operadores "+" y "-", respectivamente.

En Maxima, la resta a - b se representa como la suma a + (- b). Expresiones tales como a + (- b) se muestran como restas. Maxima reconoce "-" tan solo como el operador de negación unaria, no como el nombre del operador de resta binaria.

La división a / b se representa en maxima como la multiplicación a * b^(- 1). Expresiones tales como a * b^(- 1) se muestran como divisiones. Maxima reconoce "/" como el nombre del operador de división.

La suma y la multiplicación son operadores conmutativos n-arios. La división y la exponenciación son operadores no conmutativos binarios.

Maxima ordena los operandos de los operadores conmutativos para formar lo que se conoce como representación canónica. A efectos de almacenamiento interno, la ordenación viene determinada por orderlessp. A efectos de presentación de las expresiones, la ordenación de la suma la determina ordergreatp, y en el caso de la multiplicación, la ordenación coincide con la del almacenamiento interno.

Los cálculos aritméticos se realizan con números literales (enteros, racionales, decimales ordinarios y decimales grandes). Excepto en el caso de la exponenciación, todas las operaciones aritméticas con números dan lugar a resultados en forma de números. La exponenciación da como resultado un número si alguno de los operandos es decimal ordinario o grande (bigfloat), o si el resultado es un entero o racional; en caso contrario, la exponenciación puede expresarse como una raíz cuadrada (sqrt), como otra potencia, o simplemente no sufre cambios.

Se produce contagio de los decimales en coma flotante en los cálculos aritméticos: si algún operando es un número decimal grande (bigfloat), el resultado será también un número decimal grande; no habiendo decimales grandes, pero sí ordinarios, el resultado srá también un decimal ordinario; de no haber operandos decimales, el resultado será un número racional o entero.

Los cálculos aritméticos son simplificaciones, no evaluaciones, por lo que se realizan en expresiones comentadas.

Las operaciones aritméticas se aplican elemento a elemento en el caso de las listas cuando la variable global listarith vale true; pero en el caso de las matrices, siempre se aplican elemento a elemento. Cuando un operando es una lista o matriz y otro operando lo es de otro tipo cualquiera, éste se combina con cada uno de los elementos de la lista o matriz.

Ejemplos:

La suma y la multiplicación son operadores conmutativos n-arios. Maxima ordena los operandos para formar lo que se conoce como representación canónica. Los nombres de estos operadores son "+" y "-".

(%i1) c + g + d + a + b + e + f;
(%o1)               g + f + e + d + c + b + a
(%i2) [op (%), args (%)];
(%o2)              [+, [g, f, e, d, c, b, a]]
(%i3) c * g * d * a * b * e * f;
(%o3)                     a b c d e f g
(%i4) [op (%), args (%)];
(%o4)              [*, [a, b, c, d, e, f, g]]
(%i5) apply ("+", [a, 8, x, 2, 9, x, x, a]);
(%o5)                    3 x + 2 a + 19
(%i6) apply ("*", [a, 8, x, 2, 9, x, x, a]);
                                 2  3
(%o6)                       144 a  x

La división y la exponenciación son operadores no conmutativos binarios. Los nombres de estos operadores son "/" y "^".

(%i1) [a / b, a ^ b];
                              a   b
(%o1)                        [-, a ]
                              b
(%i2) [map (op, %), map (args, %)];
(%o2)              [[/, ^], [[a, b], [a, b]]]
(%i3) [apply ("/", [a, b]), apply ("^", [a, b])];
                              a   b
(%o3)                        [-, a ]
                              b

La resta y la división se representan internamente en términos de la suma y multiplicación, respectivamente.

(%i1) [inpart (a - b, 0), inpart (a - b, 1), inpart (a - b, 2)];
(%o1)                      [+, a, - b]
(%i2) [inpart (a / b, 0), inpart (a / b, 1), inpart (a / b, 2)];
                                   1
(%o2)                       [*, a, -]
                                   b

Los cálculos se realizan con números literales. Se produce el contagio de los números decimales.

(%i1) 17 + b - (1/2)*29 + 11^(2/4);
                                       5
(%o1)                   b + sqrt(11) + -
                                       2
(%i2) [17 + 29, 17 + 29.0, 17 + 29b0];
(%o2)                   [46, 46.0, 4.6b1]

Los cálculos aritméticos son una simplificación, no una evaluación.

(%i1) simp : false;
(%o1)                         false
(%i2) '(17 + 29*11/7 - 5^3);
                              29 11    3
(%o2)                    17 + ----- - 5
                                7
(%i3) simp : true;
(%o3)                         true
(%i4) '(17 + 29*11/7 - 5^3);
                                437
(%o4)                         - ---
                                 7

Los cálculos aritméticos se realizan elemento a elemento en las listas (según sea el valor de listarith) y matrices.

(%i1) matrix ([a, x], [h, u]) - matrix ([1, 2], [3, 4]);
                        [ a - 1  x - 2 ]
(%o1)                   [              ]
                        [ h - 3  u - 4 ]
(%i2) 5 * matrix ([a, x], [h, u]);
                          [ 5 a  5 x ]
(%o2)                     [          ]
                          [ 5 h  5 u ]
(%i3) listarith : false;
(%o3)                         false
(%i4) [a, c, m, t] / [1, 7, 2, 9];
                          [a, c, m, t]
(%o4)                     ------------
                          [1, 7, 2, 9]
(%i5) [a, c, m, t] ^ x;
                                      x
(%o5)                     [a, c, m, t]
(%i6) listarith : true;
(%o6)                         true
(%i7) [a, c, m, t] / [1, 7, 2, 9];
                              c  m  t
(%o7)                     [a, -, -, -]
                              7  2  9
(%i8) [a, c, m, t] ^ x;
                          x   x   x   x
(%o8)                   [a , c , m , t ]
Operador: **

Operador de exponenciación. Maxima identifica ** con el operador ^ en la entrada de expresiones, pero se representa como ^ en las salidas no formateadas (display2d=false), o colocando un superíndice en la salida formateada (display2d=true).

La función fortran representa el operador de exponenciación con **, tanto si se ha introducido como ** o como ^.

Ejemplos:

(%i1) is (a**b = a^b);
(%o1)                         true
(%i2) x**y + x^z;
                              z    y
(%o2)                        x  + x
(%i3) string (x**y + x^z);
(%o3)                        x^z+x^y
(%i4) fortran (x**y + x^z);
      x**z+x**y
(%o4)                         done
Operator: ^^

Operador de exponenciación no conmutativa. Se trata del operador de exponenciación correspondiente a la multiplicación no conmutativa ., del mismo modo que el operador de exponenciación ordinario ^ se corresponde con la multiplicación conmutativa *.

La exponenciación no conmutativa se representa como ^^ en las salidas no formateadas (display2d=false), o colocando un superíndice entre ángulos (< >) en la salida formateada (display2d=true).

Ejemplos:

(%i1) a . a . b . b . b + a * a * a * b * b;
                        3  2    <2>    <3>
(%o1)                  a  b  + a    . b
(%i2) string (a . a . b . b . b + a * a * a * b * b);
(%o2)                  a^3*b^2+a^^2 . b^^3
Operador: .

El operador punto, para multiplicación de matrices (no-conmutativo). Cuando "." se usa de esta forma, se dejarán espacios a ambos lados de éste, como en A . B. Así se evita que se confunda con el punto decimal de los números.

Véanse: dot, dot0nscsimp, dot0simp, dot1simp, dotassoc, dotconstrules, dotdistrib, dotexptsimp, dotident y dotscrules.


6.3 Operadores relacionales

Operator: <
Operator: <=
Operator: >=
Operator: >

Los símbolos <, <=, >= y > representan menor que, menor o igual que, mayor o igual que y mayor que, respectivamente. Los nombres de estos operadores son "<" "<=" ">=" y ">", que pueden aparecer allá donde se requiera el nombre de una función u operador.

Estos operadores relacionales son todos operadores binarios. Maxima no reconoce expresiones del estilo a < b < c.

Las expresiones relacionales devuelven valores booleanos haciendo uso de las funciones is o maybe, así como de las sentencias condicionales if, while y unless. Las expresiones relacionales no se evalúan de otra manera, aunque sus argumentos sí sean evaluados.

Cuando una expresión relacional no pueda ser evaluada a true o false, el comportamiento de is y de if estará controlado por la variable global prederror. Si prederror toma el valor true, is y if emiten un mensaje de error. Si prederror toma el valor false, is devuelve unknown y if devuelve una expresión condicional parcialmente evaluada.

maybe se comporta siempre como si prederror fuese false, al tiempo que while y unless se comportan siempre como si prederror fuese true.

Los operadores relacionales no se distribuyen sobre listas ni sobre cualesquiera otros tipos de estructuras de datos.

Véanse también =, #, equal y notequal.

Ejemplos:

Las expresiones relacionales se reducen a valores booleanos a través de ciertas funciones y sentencias condicionales.

(%i1) [x, y, z] : [123, 456, 789];
(%o1)                    [123, 456, 789]
(%i2) is (x < y);
(%o2)                         true
(%i3) maybe (y > z);
(%o3)                         false
(%i4) if x >= z then 1 else 0;
(%o4)                           0
(%i5) block ([S], S : 0, 
             for i:1 while i <= 100 do S : S + i, return (S));
(%o5)                         5050

Las expresiones relacionales no se evalúan de otra manera, aunque sus argumentos sí sean evaluados.

(%o1)                    [123, 456, 789]
(%i2) [x < y, y <= z, z >= y, y > z];
(%o2)    [123 < 456, 456 <= 789, 789 >= 456, 456 > 789]
(%i3) map (is, %);
(%o3)               [true, true, true, false]

6.4 Operadores lógicos

Operador: and

Operador de conjunción lógica. El operador and es un operador infijo n-ario; sus operandos son expresiones booleanas y su resultado es un valor lógico.

El operador and impone la evaluación (igual que is) de uno o más operandos, y puede forzar la evaluación de todos los operandos.

Los operandos se evalúan en el orden en el que aparecen; sólo evalúa tantos operandos como sean necesarios para determinar el resultado. Si algún operando vale false, el resultado es false y ya no se evalúan más operandos.

La variable global prederror controla el comportamiento de and cuando la evaluación de un operando no da como resultado true o false; and imprime un mensaje de error cuando prederror vale true. Cuando los operandos devuelven un valor diferente a true o false al ser evaluados, el resultado es una expresión booleana.

El operador and no es conmutativo: a and b puede no ser igual a b and a debido al tratamiento de operandos indeterminados.

Operador: not

Operador de negación lógica. El operador not es un operador prefijo; su operando es una expresión booleana y su resultado es un valor lógico.

El operador not impone la evaluación (igual que is) de su operando.

La variable global prederror controla el comportamiento de not cuando la evaluación de su operando no da como resultado true o false; not imprime un mensaje de error cuando prederror vale true. Cuando los operandos devuelven un valor diferente a true o false al ser evaluados, el resultado es una expresión booleana.

Operador: or

Operador de disyunción lógica. El operador or es un operador infijo n-ario; sus operandos son expresiones booleanas y su resultado es un valor lógico.

El operador or impone la evaluación (igual que is) de uno o más operandos, y puede forzar la evaluación de todos los operandos.

Los operandos se evalúan en el orden en el que aparecen; or sólo evalúa tantos operandos como sean necesarios para determinar el resultado. Si un operando vale true, el resultado es true y ya no se evalúan más operandos.

La variable global prederror controla el comportamiento de or cuando la evaluación de un operando no da como resultado true o false; or imprime un mensaje de error cuando prederror vale true. Cuando los operandos devuelven un valor diferente a true o false al ser evaluados, el resultado es una expresión booleana.

El operador or no es conmutativo: a or b puede no ser igual a b or a debido al tratamiento de operandos indeterminados.


6.5 Operadores para ecuaciones

Operador: #

Representa la negación de la igualdad sintáctica =.

Nótese que debido a las reglas de evaluación de expresiones de tipo predicado (en concreto debido a que not expr obliga a la evaluación previa de expr), not a = b equivale a is(a # b), pero no a a # b.

Ejemplos:

(%i1) a = b;
(%o1)                         a = b
(%i2) is (a = b);
(%o2)                         false
(%i3) a # b;
(%o3)                         a # b
(%i4) not a = b;
(%o4)                         true
(%i5) is (a # b);
(%o5)                         true
(%i6) is (not a = b);
(%o6)                         true
Operador: =

Operador de ecuación.

La expresión a = b representa una ecuación sin evaluar, la cual puede verificarse o no. Las ecuaciones sin evaluar pueden aparecer como argumentos de solve, algsys y de algunas otras funciones.

La función is evalúa el operador = a un resultado booleano; is(a = b) asigna un valor de verdad a a = b, siendo true si a y b son idénticos, lo cual acontece si ambos a y b son átomos idénticos, o si no siendo átomos, sus operadores y argumentos respectivos son idénticos; en caso contrario, is(a = b) devuelve el valor false. Nunca se devuelve el valor unknown. Cuando is(a = b) toma el valor true, se dice que a y b son sintácticamente iguales, no expresiones equivalentes, para las cuales is(equal(a, b)) devuelve true. Las expresiones pueden ser equivalentes, pero no sintácticamente iguales.

La negación de = se representa por #. Como en el caso de =, la expresión a # b no está evaluada; sin embargo, is(a # b) evalúa a # b a true o false.

Además de is, hay otros operadores que evalúan = y # a true o false; a saber, if, and, or y not.

Nótese que debido a las reglas de evaluación de expresiones de tipo predicado (en concreto debido a que not expr obliga a la evaluación previa de expr), not a = b equivale a is(a # b), pero no a a # b.

Las funciones rhs y lhs devuelven los miembros derecho e izquierdo, respectivamente, de una ecuación o inecuación.

Véanse también equal y notequal.

Ejemplos:

La expresión a = b representa una ecuación sin evaluar, la cual puede verificarse o no.

(%i1) eq_1 : a * x - 5 * y = 17;
(%o1)                    a x - 5 y = 17
(%i2) eq_2 : b * x + 3 * y = 29;
(%o2)                    3 y + b x = 29
(%i3) solve ([eq_1, eq_2], [x, y]);
                        196         29 a - 17 b
(%o3)          [[x = ---------, y = -----------]]
                     5 b + 3 a       5 b + 3 a
(%i4) subst (%, [eq_1, eq_2]);
         196 a     5 (29 a - 17 b)
(%o4) [--------- - --------------- = 17, 
       5 b + 3 a      5 b + 3 a
                                  196 b     3 (29 a - 17 b)
                                --------- + --------------- = 29]
                                5 b + 3 a      5 b + 3 a
(%i5) ratsimp (%);
(%o5)                  [17 = 17, 29 = 29]

is(a = b) evalúa a = b a true si a y b son sintácticamente iguales (es decir, idénticas). Las expresiones pueden ser equivalentes, pero no sintácticamente iguales.

(%i1) a : (x + 1) * (x - 1);
(%o1)                    (x - 1) (x + 1)
(%i2) b : x^2 - 1;
                              2
(%o2)                        x  - 1
(%i3) [is (a = b), is (a # b)];
(%o3)                     [false, true]
(%i4) [is (equal (a, b)), is (notequal (a, b))];
(%o4)                     [true, false]

Algunos operadores evalúan = y # a true o false.

(%i1) if expand ((x + y)^2) = x^2 + 2 * x * y + y^2
        then FOO else BAR;
(%o1)                          FOO
(%i2) eq_3 : 2 * x = 3 * x;
(%o2)                       2 x = 3 x
(%i3) eq_4 : exp (2) = %e^2;
                              2     2
(%o3)                       %e  = %e
(%i4) [eq_3 and eq_4, eq_3 or eq_4, not eq_3];
(%o4)                  [false, true, true]

Debido a que not expr obliga a la evaluación previa de expr, not a = b equivale a is(a # b).

(%i1) [2 * x # 3 * x, not (2 * x = 3 * x)];
(%o1)                   [2 x # 3 x, true]
(%i2) is (2 * x # 3 * x);
(%o2)                         true

6.6 Operadores de asignación

Operador: :

Operador de asignación.

Cuando el miembro de la izquierda es una variable simple (no subindicada), : evalúa la expresión de la derecha y asigna ese valor a la variable del lado izquierdo.

Cuando en el lado izquierdo hay un elemento subindicado correspondiente a una lista, matriz, array declarado de Maxima o array de Lisp, la expresión de la derecha se asigna a ese elemento. El subíndice debe hacer referencia a un elemento ya existente, ya que los objetos anteriores no pueden ampliarse nombrando elementos no existentes.

Cuando en el lado izquierdo hay un elemento subindicado correspondiente a un array no declarado de Maxima, la expresión de la derecha se asigna a ese elemento en caso de que ya exista, o a un nuevo elemento, si éste todavía no existe.

Cuando el miembro de la izquierda es una lista de átomos y/o variables subindicadas, el miembro derecho debe evaluar también a una lista, cuyos elementos serán asignados en paralelo a las variables de la lista de la izquierda.

Véanse también kill y remvalue, que deshacen las asociaciones hechas por el operador :.

Ejemplos:

Asignación a una variable simple.

(%i1) a;
(%o1)                           a
(%i2) a : 123;
(%o2)                          123
(%i3) a;
(%o3)                          123

Asignación a un elemento de una lista.

(%i1) b : [1, 2, 3];
(%o1)                       [1, 2, 3]
(%i2) b[3] : 456;
(%o2)                          456
(%i3) b;
(%o3)                      [1, 2, 456]

La asignación crea un array no declarado.

(%i1) c[99] : 789;
(%o1)                          789
(%i2) c[99];
(%o2)                          789
(%i3) c;
(%o3)                           c
(%i4) arrayinfo (c);
(%o4)                   [hashed, 1, [99]]
(%i5) listarray (c);
(%o5)                         [789]

Asignación múltiple.

(%i1) [a, b, c] : [45, 67, 89];
(%o1)                     [45, 67, 89]
(%i2) a;
(%o2)                          45
(%i3) b;
(%o3)                          67
(%i4) c;
(%o4)                          89

La asignación múltiple se hace en paralelo. Los valores de a y b se intercambian en este ejemplo.

(%i1) [a, b] : [33, 55];
(%o1)                       [33, 55]
(%i2) [a, b] : [b, a];
(%o2)                       [55, 33]
(%i3) a;
(%o3)                          55
(%i4) b;
(%o4)                          33
Operador: ::

Operador de asignación.

El operador :: es similar a :, excepto que :: evalúa ambos miembros, tanto el derecho como el izquierdo.

Ejemplos:

(%i1) x : 'foo;
(%o1)                          foo
(%i2) x :: 123;
(%o2)                          123
(%i3) foo;
(%o3)                          123
(%i4) x : '[a, b, c];
(%o4)                       [a, b, c]
(%i5) x :: [11, 22, 33];
(%o5)                     [11, 22, 33]
(%i6) a;
(%o6)                          11
(%i7) b;
(%o7)                          22
(%i8) c;
(%o8)                          33
Operador: ::=

El operador de definición de macros ::= define una función (llamada macro por razones históricas) que no evalúa sus argumentos, siendo la expresión que retorna (llamada "macroexpansión") evaluada dentro del contexto desde el cual se ha invocado la macro. En cualquier otro sentido, una función macro es igual que una función ordinaria.

macroexpand devuelve la expresión que a su vez fue devuelta por una macro (sin evaluar la expresión); macroexpand (foo (x)) seguida de ''% es equivalente a foo (x) si foo es una función macro.

::= coloca el nombre de la nueva función macro en la lista global macros. Por otro lado, las funciones kill, remove y remfunction borran las definiciones de las funciones macro y eliminan sus nombres de la lista macros.

Las funciones fundef y dispfun devuelven la definición de una función macro y le asignan una etiqueta, respectivamente.

Las funciones macro normalmente contienen expresiones buildq y splice para construir una expresión, que luego será evaluada.

Ejemplos:

Una función macro no evalúa sus argumentos, por lo que el mensaje (1) muestra y - z, no el valor de y - z. La macroexpansión (es decir, la expresión no evaluada '(print ("(2) x is equal to", x))) se evalúa en el contexto desde el cual se produjo la llamada a la macro, imprimiendo el mensaje (2).

(%i1) x: %pi$

(%i2) y: 1234$

(%i3) z: 1729 * w$

(%i4) printq1 (x) ::= block (print ("(1) x is equal to", x),
'(print ("(2) x is equal to", x)))$

(%i5) printq1 (y - z);
(1) x is equal to y - z
(2) x is equal to %pi
(%o5)                                 %pi

Una función ordinaria evalúa sus argumentos, por lo que el mensaje (1) muestra el valor de y - z. El valor de retorno no se evalúa, por lo que el mensaje (2) no se imprime hasta la evaluación explícita ''%.

(%i1) x: %pi$

(%i2) y: 1234$

(%i3) z: 1729 * w$

(%i4) printe1 (x) := block (print ("(1) x is equal to", x),
'(print ("(2) x is equal to", x)))$

(%i5) printe1 (y - z);
(1) x is equal to 1234 - 1729 w
(%o5)                     print((2) x is equal to, x)
(%i6) ''%;
(2) x is equal to %pi
(%o6)                                 %pi

macroexpand devuelve la macroexpansión; macroexpand (foo (x)) seguida de ''% es equivalente a foo (x) si foo es una función macro.

(%i1) x: %pi$

(%i2) y: 1234$

(%i3) z: 1729 * w$

(%i4) g (x) ::= buildq ([x], print ("x is equal to", x))$

(%i5) macroexpand (g (y - z));
(%o5)                     print(x is equal to, y - z)
(%i6) ''%;
x is equal to 1234 - 1729 w
(%o6)                            1234 - 1729 w
(%i7) g (y - z);
x is equal to 1234 - 1729 w
(%o7)                            1234 - 1729 w
Operador: :=

El operador de definición de funciones. La expresión f(x_1, ..., x_n) := expr define una función de nombre f con argumentos x_1, ..., x_n y cuerpo expr. El operador := no evalúa el cuerpo de la función (a menos que se indique lo contrario mediante el operador comilla-comilla ''). La función así definida puede ser una función ordinaria de Maxima (con argumentos encerrados entre paréntesis) o una función array (con argumentos encerrados entre corchetes).

Cuando el último o único argumento x_n es una lista de un solo elemento, la función definida por := acepta un número variable de argumentos. Los valores de los argumentos se asignan uno a uno a los argumentos formales x_1, ..., x_(n - 1), y cualesquiera otros valores de argumentos, si existen, se asignan a x_n en forma de lista.

Todas las definiciones de funciones aparecen en el mismo espacio de nombres; definiendo una función f dentro de otra función g no limita automáticamente el alcance de f a g. No obstante, local(f) hace que la función f sea efectiva solamente dentro del bloque o empaquetado de expresiones en la que aparece local.

Si un argumento formal x_k es un símbolo afectado por el operador comilla (expresión nominal), la función definida por := no evalúa el correspondiente valor de argumento. En cualquier otro caso, los argumentos que se pasan son evaluados.

Véanse también define y ::=.

Ejemplos:

:= no evalúa el cuerpo de la función (a menos que se indique lo contrario mediante el operador comilla-comilla '').

(%i1) expr : cos(y) - sin(x);
(%o1)                    cos(y) - sin(x)
(%i2) F1 (x, y) := expr;
(%o2)                   F1(x, y) := expr
(%i3) F1 (a, b);
(%o3)                    cos(y) - sin(x)
(%i4) F2 (x, y) := ''expr;
(%o4)              F2(x, y) := cos(y) - sin(x)
(%i5) F2 (a, b);
(%o5)                    cos(b) - sin(a)

La función así definida puede ser una función ordinaria de Maxima o una función array.

(%i1) G1 (x, y) := x.y - y.x;
(%o1)               G1(x, y) := x . y - y . x
(%i2) G2 [x, y] := x.y - y.x;
(%o2)                G2     := x . y - y . x
                       x, y

Cuando el último o único argumento x_n es una lista de un solo elemento, la función definida por := acepta un número variable de argumentos.

(%i1) H ([L]) := apply ("+", L);
(%o1)                H([L]) := apply("+", L)
(%i2) H (a, b, c);
(%o2)                       c + b + a

local define una función como local.

(%i1) foo (x) := 1 - x;
(%o1)                    foo(x) := 1 - x
(%i2) foo (100);
(%o2)                         - 99
(%i3) block (local (foo), foo (x) := 2 * x, foo (100));
(%o3)                          200
(%i4) foo (100);
(%o4)                         - 99

6.7 Operadores definidos por el usuario

Función: infix (op)
Función: infix (op, lbp, rbp)
Función: infix (op, lbp, rbp, lpos, rpos, pos)

Declara op como operador infijo. Un operador infijo es una función de dos argumentos, con el nombre de la función escrito entre sus argumentos. Por ejemplo, el operador de sustracción - es un operador infijo.

infix (op) declara op como operador infijo con fuerzas de ligadura por la izquierda y por la derecha iguales a 180, que es el valor por defecto, y partes izquierda y derecha iguales a any.

infix (op, lbp, rbp) declara op como operador infijo con fuerzas de ligadura por la izquierda y por la derecha declaradas en los argumentos, siendo las partes izquierda y derecha iguales a any.

infix (op, lbp, rbp, lpos, rpos, pos) declara op como operador infijo con fuerzas de ligadura por la izquierda y por la derecha, junto con los tipos de expresiones correspondientes a lpos, rpos y pos, que son el operando de la izquierda, el de la derecha y el operador del resultado; los tipos reconocidos son: expr, clause y any, que indican expresión algebraica, expresión booleana o cualquier otra, respectivamente. Maxima puede detectar algunos errores sintácticos comparando los tipos declarados con los de la expresión actual.

La precedencia de op con respecto a otros operadores deriva de las fuerzas de ligadura de los operadores en cuestión. Si las fuerzas de ligadura a izquierda y derecha de op son ambas mayores que las fuerzas de ligadura a izquierda y derecha de otro operador, entonces op tiene preferencia sobre el otro operador. Si las fuerzas de ligadura no son ambas mayores o menores, se aplican otras relaciones más complejas.

La asociatividad de op depende de las fuerzas de ligadura. Una mayor fuerza de ligadura a la izquierda (lbp) implica que op sea evaluado antes que otros operadores a su izquierda en la expresión, mientras que mayor fuerza de ligadura a la derecha (rbp) implica que op sea evaluado antes que otros operadores a su derecha en la expresión. Así, si lbp es mayor, op es asociativo por la derecha, mientras que si rbp es mayor, op es asociativo por la izquierda.

Véase también Syntax.

Ejemplos:

Si las fuerzas de ligadura a izquierda y derecha de op son ambas mayores que las fuerzas de ligadura a izquierda y derecha de otro operador, entonces op tiene preferencia sobre el otro operador.

(%i1) :lisp (get '$+ 'lbp)
100
(%i1) :lisp (get '$+ 'rbp)
100
(%i1) infix ("##", 101, 101);
(%o1)                          ##
(%i2) "##"(a, b) := sconcat("(", a, ",", b, ")");
(%o2)       (a ## b) := sconcat("(", a, ",", b, ")")
(%i3) 1 + a ## b + 2;
(%o3)                       (a,b) + 3
(%i4) infix ("##", 99, 99);
(%o4)                          ##
(%i5) 1 + a ## b + 2;
(%o5)                       (a+1,b+2)

Mayor lbp hace a op asociativo por la derecha, mientras que mayor rbp hace a op asociativo por la izquierda.

(%i1) infix ("##", 100, 99);
(%o1)                          ##
(%i2) "##"(a, b) := sconcat("(", a, ",", b, ")")$
(%i3) foo ## bar ## baz;
(%o3)                    (foo,(bar,baz))
(%i4) infix ("##", 100, 101);
(%o4)                          ##
(%i5) foo ## bar ## baz;
(%o5)                    ((foo,bar),baz)

Maxima puede detectar algunos errores sintácticos comparando los tipos declarados con los de la expresión actual.

(%i1) infix ("##", 100, 99, expr, expr, expr);
(%o1)                          ##
(%i2) if x ## y then 1 else 0;
Incorrect syntax: Found algebraic expression where logical expression expected
if x ## y then 
             ^
(%i2) infix ("##", 100, 99, expr, expr, clause);
(%o2)                          ##
(%i3) if x ## y then 1 else 0;
(%o3)                if x ## y then 1 else 0
Función: matchfix (ldelimiter, rdelimiter)
Función: matchfix (ldelimiter, rdelimiter, arg_pos, pos)

Declara un operador "matchfix" con delimitadores a la izquierda y derecha, ldelimiter y rdelimiter, respectivamente. Los delimitadores son cadenas alfanuméricas.

Un operador "matchfix" es una función con un número arbitrario de argumentos, de manera que los argumentos se presentan entre los delimitadores de la izquierda y derecha. Los delimitadores pueden ser cualquier tipo de cadena, en tanto que el analizador sintáctico pueda distinguirlos de los operandos y de expresiones con operadores. En la práctica esto excluye delimitadores como %, ,, $ y ;, necesitando aislar los delimitadores con espacios en blanco. El delimitador de la derecha puede ser igual o diferente del de la izquierda.

Un delimitador de la izquierda sólo puede asociarse con un único delimitador de la derecha; dos operadores "matchfix" diferentes no pueden tener el mismo delimitador por la izquierda.

Un operador ya existente puede declararse como operador "matchfix" sin necesidad de que cambie el resto de propiedades. En particular, los operadores de Maxima tales como la suma + pueden ser declarados como "matchfix".

La llamada matchfix (ldelimiter, rdelimiter, arg_pos, pos) declara el argumento arg_pos y el resultado pos, así como los delimitadores ldelimiter y rdelimiter.

Los argumentos arg_pos y pos son tipos de funciones, reconociéndose como tales: expr, clause y any, los cuales hacen referencia a una expresión algebraica, booleana o de cualquier otro tipo, respectivamente. Maxima puede detectar ciertos errores sintácticos comparando el tipo de expresión declarado con el de la expresión actual.

La función que ejecutará una operación "matchfix" será una típica función definida por el usuario. La función de operador se define por el método habitual con := o define. Los argumentos pueden escribirse entre los delimitadores, o con el delimitador izquierdo como una cadena precedida de apóstrofo y seguidamente los argumentos entre paréntesis. La llamada dispfun (ldelimiter) muestra la definición de la función.

El único operador "matchfix" de Maxima es el constructor de listas [ ]. Los paréntesis ( ) y las comillas dobles " " actúan como operadores "matchfix", pero son tratados como operadores "matchfix" por el analizador sintáctico de Maxima.

Ejemplos:

  • Los delimitadores pueden ser practicamente cualquier cadena.
(%i1) matchfix ("@@", "~");
(%o1)                          @@
(%i2) @@ a, b, c ~;
(%o2)                      @@a, b, c~
(%i3) matchfix (">>", "<<");
(%o3)                          >>
(%i4) >> a, b, c <<;
(%o4)                      >>a, b, c<<
(%i5) matchfix ("foo", "oof");
(%o5)                          foo
(%i6) foo a, b, c oof;
(%o6)                     fooa, b, coof
(%i7) >> w + foo x, y oof + z << / @@ p, q ~;
                     >>z + foox, yoof + w<<
(%o7)                ----------------------
                            @@p, q~
  • Los operadores "matchfix" son funciones definidas por el usuario.
(%i1) matchfix ("!-", "-!");
(%o1)                         "!-"
(%i2) !- x, y -! := x/y - y/x;
                                    x   y
(%o2)                   !-x, y-! := - - -
                                    y   x
(%i3) define (!-x, y-!, x/y - y/x);
                                    x   y
(%o3)                   !-x, y-! := - - -
                                    y   x
(%i4) define ("!-" (x, y), x/y - y/x);
                                    x   y
(%o4)                   !-x, y-! := - - -
                                    y   x
(%i5) dispfun ("!-");
                                    x   y
(%t5)                   !-x, y-! := - - -
                                    y   x

(%o5)                         done
(%i6) !-3, 5-!;
                                16
(%o6)                         - --
                                15
(%i7) "!-" (3, 5);
                                16
(%o7)                         - --
                                15
Función: nary (op)
Función: nary (op, bp, arg_pos, pos)

Un operador n-ario denota una función con un número arbitrario de argumentos entre los que se intercal el símbolo del operador, como en A+B+C. La instrucción nary("x") declara x como operador n-ario. Las funciones se pueden declarar como n-arias; de modo que si se ejecuta declare(j,nary), el simplificador transforma j(j(a,b),j(c,d)) en j(a, b, c, d).

Función: nofix (op)
Función: nofix (op, pos)

Los operadores no-fijos se utilizan para definir funciones sin argumentos. La mera presencia de tal operador en una instrucción hará que se evalúe la función correspondiente. Por ejemplo, cuando se teclea exit; para salir de una interrupción de Maxima, exit se comporta como una función no-fija. La instrucción nofix("x") declara x como operador no-fijo.

Función: postfix (op)
Función: postfix (op, lbp, lpos, pos)

Los operadores sufijos son funciones de un único argumento en las que éste precede al operador, como en 3!. La instrucción postfix("x") declara x como operador sufijo.

Función: prefix (op)
Función: prefix (op, rbp, rpos, pos)

Los operadores prefijos son funciones de un único argumento en las que éste se coloca a continuación del operador. La instrucción prefix("x") declara x como operador prefijo.


Siguiente: , Anterior:   [Índice general][Índice]