Anterior | Superior | Siguiente

Guía de referencia básica de Ada 95

Expresiones y operadores

Expresiones.

Una expresión es una combinación de operadores y operandos de cuya evaluación se obtiene un valor. Los operandos pueden ser nombres que denoten objetos variables o constantes, funciones, literales de cualquier tipo adecuado de acuerdo con los operadores u otras expresiones más simples. La evaluación de una expresión da lugar a un valor de algún tipo, una expresión se dice que es del tipo de su resultado. Ejemplos de expresiones:

a + 5*b
(a >= 0) and ((b+5) > 10)
a
-a * 2 + b
-b + sqrt(b**2 - 4*a*c)
length(s) > 0

Las expresiones se evalúan de acuerdo con la precedencia de los operadores. Ante una secuencia de operadores de igual precedencia, la evaluación se realiza según el orden de escritura, de izquierda a derecha. El orden de evaluación puede modificarse usando paréntesis.

Operadores.

Ada agrupa los operadores en 6 categorías, de menor a mayor precedencia. Los operadores binarios se usan en formato infijo (<operando_izquierdo> <operador> <operando_derecho>), como en "a + b". Los operadores unarios se usan en formato prefijo (<operador> <operando> ), como en "-5".

Operadores lógicos.

Están predefinidos para cualquier tipo, T, que designe un booleano, modular o un array monodimensional de componentes booleanos:

function "and"(Left, Right : T) return T
function "or" (Left, Right : T) return T
function "xor"(Left, Right : T) return T

Ejemplo de uso  en expresiones (sean A, B y C de tipo T):

if A and B then ...
C := A or B;
return (A xor B);

Su significado es el convencional (para los tipos modulares son operaciones bit a bit):

A B (A and B) (A or B) (A xor B)
True
True
False
False
True
False
True
False
True
False
False
False
True
True
True
False
False
True
True
False

Para los tipos booleanos, existen versiones de los operadores "and" y "or", llamadas "and then" y "or else" que tienen el mismo significado, pero realizan una "evaluación en cortocircuito" consistente en que evalúan siempre primero el operando izquierdo y, si el valor de éste es suficiente para determinar el resultado, no evalúan el operando derecho.

La evaluación en cortocircuito resulta muy útil si la correcta evaluación del operando derecho depende del valor del operando izquierdo, como en el siguiente ejemplo:
    if   i <= Vec'last and then Vec(i) > 0   then ...
(Evaluar Vec(i) produciría un error si i tiene un valor superior al límite máximo del vector).

Operadores relacionales.

Los operadores de igualdad están predefinidos para todos los tipos no limitados. Sea T un tipo con estas características:

function "=" (Left, Right : T) return Boolean
function "/="(Left, Right : T) return Boolean

Los operadores de ordenación están predefinidos para todos los tipos escalares y los arrays de elementos discretos. Sea T un tipo con estas características:

function "<" (Left, Right : T) return Boolean
function "<="(Left, Right : T) return Boolean
function ">" (Left, Right : T) return Boolean
function ">="(Left, Right : T) return Boolean

Existe también un operador de pertenencia ("in", "not in") que determina si un valor pertenece a un rango o a un subtipo: if i in 1..10 then ...

Todos los operadores relacionales devuelven un resultado de tipo Boolean.

Ejemplo de uso  en expresiones (sean A, B de tipo T y C de tipo Boolean):

if A = B then ...
C := (A <= B);
return (A >= B);

Operadores binarios de adición.

Los operadores de adición predefinidos para cualquier tipo numérico, T, son:

function "+"(Left, Right : T) return T
function "–"(Left, Right : T) return T

Ejemplo de uso  en expresiones (sean A, B y C de tipo T):

C := A + B;
return (A - B);

También pertenecen a esta categoría los operadores de concatenación, predefinidos para cualquier tipo de array monodimensional no limitado, T, de elementos de tipo C:

function "&"(Left : T; Right : T) return T
function "&"(Left : T; Right : C) return T
function "&"(Left : C; Right : T) return T
function "&"(Left : C; Right : C) return T

Operadores unarios de adición.

Los operadores unarios de adición predefinidos para cualquier tipo númerico, T, son la identidad y la negación:

function "+"(Right : T) return T
function "–"(Right : T) return T

Ejemplo de uso  en expresiones (sean A y B de tipo T):

B := -A;

Cuando se aplica a un tipo modular, el operador de negación ("-") tiene el efecto de restar el valor del operando, si es distinto de cero, al módulo. Si el valor del operando es cero, el resultado es cero.

Operadores multiplicativos.

Los operadores de multiplicación y división están predefinidos entre diversas combinaciones de enteros y reales:

function "*" (Left, Right : T) return T
function "/" (Left, Right : T) return T
function "*"(Left : T; Right : Integer) return T
function "*"(Left : Integer; Right : T) return T
function "/"(Left : T; Right : Integer) return T
function "*"(Left, Right : root_real) return root_real
function "/"(Left, Right : root_real) return root_real
function "*"(Left : root_real; Right : root_integer) return root_real
function "*"(Left : root_integer; Right : root_real) return root_real
function "/"(Left : root_real; Right : root_integer) return root_real
function "*"(Left, Right : universal_fixed) return universal_fixed
function "/"(Left, Right : universal_fixed) return universal_fixed

Ejemplo de uso  en expresiones (sean A, B y C del mismo tipo entero o real):

C := A * B;
return (A / B);

Los operadores módulo y resto están definidos para cualquier tipo entero, T:

function "mod"(Left, Right : T) return T
function "rem"(Left, Right : T) return T

La relación entre el resto y la división entera viene dada por la expresión: A = (A/B)*B + (A rem B), donde (A rem B) tiene el mismo signo que A, y es menor que B en valor absoluto.

El operador módulo se define de manera que (A mod B) tiene el mismo signo que B, un valor absoluto menor, y existe un número entero, N, tal que: A = B*N + (A mod B).

Ejemplo de uso  en expresiones (sean A, B y C de tipo T):

C := A rem B;
return (A mod B);

Operadores de máxima prioridad.

Los operadores de máxima prioridad son: el operador de cálculo del valor absoluto, definido para cualquier tipo numérico, T1, el operador de negación lógica, definido para cualquier tipo booleano, modular o array monodimensional de componentes booleanos, T 2, y el operador de exponenciación, definido para cualquier tipo entero, T3, o para cualquier tipo real en coma flotante, T4. Cada uno, de acuerdo con las siguientes especificaciones:

function "abs"(Right : T) return T
function "not"(Right : T) return T
function "**"(Left : T; Right : Natural) return T
function "**"(Left : T; Right : Integer'Base) return T

Ejemplo de uso  en expresiones (sean A, B de tipo T1; C, D de tipo T2 y E de tipo T3):

A := abs(B);
C := not D;
return (E ** 3); -- E elevado al cubo

Sobrecarga de operadores.

Ada permite que el programador sobrecargue los operadores del lenguaje, esto es, que pueda redefinirlos dándoles nuevos significados. Para sobrecargar un operador, simplemente hay que definir una función cuyo nombre sea el operador entre comillas y que tenga los parámetros adecuados. Por ejemplo, dado el siguiente tipo:

type Complejo is record
    PReal, PImag: float;
end record;

podemos sobrecargar el operador de suma ("+") para utilizarlo con el fin de sumar números complejos:

function "+"(A, B : in Complejo) return Complejo is
    Suma: Complejo;
begin
    Suma.PReal := A.PReal + B.PReal;
    Suma.PImag := A.PImag + B.PImag;
    return Suma;
end "+";

Una vez definida esta función, se puede aplicar el operador entre variables del tipo definido en los parámetros, devolviendo un valor del tipo definido como resultado.

...
S, X, Y: Complejo;
...
S := X + Y;

Sólo se pueden redefinir los operadores del lenguaje (no se pueden inventar operadores) y manteniendo siempre su cardinalidad (los binarios se redefinirán con funciones de dos parámetros y los unarios con funciones de un parámetro).

El operador de desigualdad ("/=") devuelve siempre el complementario de la igualdad ("="), por lo que, en caso necesario, sólo hay que sobrecargar este último. De hecho, el operador de desigualdad sólo se puede sobrecargar si se le atribuye un resultado que no sea de tipo Boolean.

© Grupo de Estructuras de Datos y Lingüística Computacional - ULPGC.

Anterior | Superior | Siguiente