@c /Program.texi/1.23/Mon Feb 19 14:23:10 2007/-ko/
@menu
* Introdução a Fluxo de Programa::  
* Definições para Fluxo de Programa::  
@end menu

@node Introdução a Fluxo de Programa, Definições para Fluxo de Programa, Fluxo de Programa, Fluxo de Programa
@section Introdução a Fluxo de Programa

Maxima fornece um @code{do} para ciclos iterativos, também contruções mais
primitivas tais como @code{go}.

@c end concepts Fluxo de Programa
@node Definições para Fluxo de Programa,  , Introdução a Fluxo de Programa, Fluxo de Programa
@section Definições para Fluxo de Programa

@deffn {Função} backtrace ()
@deffnx {Função} backtrace (@var{n})
Imprime a pilha de chamadas, que é, a lista de funções que
foram chamadas pela função correntemente activa.

@code{backtrace()} imprime toda a pilha de chamadas.

@code{backtrace (@var{n})} imprime as @var{n} mais recentes chamadas a
funções, incluindo a função correntemente activa.

@c IS THIS STATMENT REALLY NEEDED ?? 
@c (WHY WOULD ANYONE BELIEVE backtrace CANNOT BE CALLED OUTSIDE A DEBUGGING CONTEXT??)
@code{backtrace} pode ser chamada por um script, uma função, ou a partir da linha de comando interativa
(não somente em um contexto de depuração).

Exemplos:

@itemize @bullet
@item
@code{backtrace()} imprime toda a pilha de chamadas.

@example
(%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
@end example
@end itemize

@itemize @bullet
@item
@code{backtrace (@var{n})} imprime as @var{n} mais recentes chamadas a
funções, incluindo a função correntemente activa.

@example
(%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
@end example
@end itemize

@end deffn

@deffn {Operador especial} do
A declaração @code{do} é usada para executar iteração.  Devido à sua
grande generalidade a declaração @code{do} será  descrita em duas partes.
Primeiro a forma usual será dada que é análoga à forma que é usada em
muitas outras linguagens de programação (Fortran, Algol, PL/I, etc.); em segundo lugar
os outros recursos serão mencionados.

Existem três variantes do operador especial @code{do} que diferem somente por suas
condições de encerramento.  São elas:

@itemize @bullet
@item
@code{for @var{Variável}: @var{valor_inicial} step @var{incremento}
      thru @var{limite} do @var{corpo}}
@item
@code{for @var{Variável}: @var{valor_inicial} step @var{incremento}
      while @var{condition} do @var{corpo}}
@item
@code{for @var{Variável}: @var{valor_inicial} step @var{incremento}
      unless @var{condition} do @var{corpo}}
@end itemize

@c UGH.  DO WE REALLY NEED TO MENTION THIS??
(Alternativamente, o @code{step} pode ser dado após a condição de encerramento
ou limite.)

@var{valor_inicial}, @var{incremento}, @var{limite}, e @var{corpo} podem ser quaisquer
expressões.  Se o incremento for 1 então "@code{step 1}" pode ser omitido.

A execução da declaração @code{do} processa-se primeiro atribuindo o
valor_inicial para a variável (daqui em diante chamada a
variável de controle).  Então: (1) Se a variável de controle excede
o limite de uma especificação @code{thru}, ou se a condição de @code{unless} for
@code{true}, ou se a condição de @code{while} for @code{false} então o @code{do}
será encerrado.  (2) O corpo é avaliado.  (3) O incremento é adicionado à
variável de controle.  O processo de (1) a (3) é executado
repetidamente até que a condição de encerramento seja satisfeita.  Pode-se também
dar muitas condições de encerramento e nesse caso o @code{do} termina
quando qualquer delas for satisfeita.

Em geral o teste @code{thru} é satisfeito quando a variável de controle for
maior que o limite se o incremento for não negativo, ou quando a
variável de controle for menor que o limite se o incremento for negativo.
O incremento e o limite podem ser expressões não numéricas enquanto essa
desigualdade puder ser determinada.  Todavia, a menos que o incremento seja
sintaticamente negativo (e.g. for um número negativo) na hora em que a declaração @code{do}
for iniciada, Maxima assume que o incremento e o limite serão positivos quando o @code{do} for
executado.  Se o limite e o incremento não forem positivos, então o @code{do} pode não terminar
propriamente.

Note que o limite, incremento, e condição de encerramento são
avaliados cada vez que ocorre um ciclo.  Dessa forma se qualquer desses for responsável por
muitos cálculos, e retornar um resultado que não muda durante todas
as execuções do corpo, então é mais eficiente escolher uma
variável para seu valor anterior para o @code{do} e usar essa variável na
forma @code{do}.

O valor normalmente retornado por uma declaração @code{do} é o átomo @code{done}.
Todavia, a função
@code{return} pode ser usada dentro do corpo para sair da delcaração @code{do} prematuramente e dar
a isso qualquer valor desejado.
Note todavia que um @code{return} dentro de um @code{do} que
ocorre em um @code{block} encerrará somente o @code{do} e não o @code{block}.  Note também
que a função @code{go} não pode ser usada para sair de dentro de um @code{do} dentro de um
@code{block} que o envolve.

A variável de controle é sempre local para o @code{do} e dessa forma qualquer
variável pode ser usada sem afectar o valor de uma variável com
o mesmo nome fora da declaração @code{do}.  A variável de controle é liberada
após o encerramento da declaração @code{do}.

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

                              a = 4

                             a = 11

                             a = 18

                             a = 25
@end example

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

Note que a condição @code{while i <= 10}
é equivalente a @code{unless i > 10} e também @code{thru 10}.

@example
(%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
@end example

que fornece 8 termos da série de Taylor para @code{e^sin(x)}.

@example
(%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
@end example

Esse exemplo calcula a raíz quadrada negativa de 10 usando a
iteração de Newton- Raphson um maximum de 10 vezes.  Caso o critério de
convergêcia não tenha sido encontrado o valor retornado pode ser @code{done}.
Em lugar de sempre adicionar uma quantidade à variável de controle pode-se
algumas vezes desejar alterar isso de alguma outra forma para cada iteração.
Nesse caso pode-se usar @code{next @var{expressão}} em lugar de @code{step @var{incremento}}.
Isso fará com que a variável de controle seja escolhida para o
resultado da expressão de avaliação cada vez que o ciclo de repetição for executado.

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

                            count = 6

                           count = 18
@end example

@c UGH.  DO WE REALLY NEED TO MENTION THIS??
Como uma alternativa para @code{for @var{Variável}: @var{valor} ...do...} a sintaxe
@code{for @var{Variável} from @var{valor} ...do...}  pode ser usada.  Isso permite o
@code{from @var{valor}} ser colocado após o @code{step} ou proximo valor ou após a
condição de encerramento.  Se @code{from @var{valor}} for omitido então 1 é usado como
o valor inicial.

Algumas vezes se pode estar interessado em executar uma iteração onde
a variável de controle nunca seja usada.  Isso é permissível
para dar somente as condições de encerramento omitindo a inicialização
e a informação de actualização como no exemplo seguinte para para calcular a
raíz quadrada de 5 usando uma fraca suposição inicial.

@example
(%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
@end example

Se isso for desejado pode-se sempre omitir as condições de encerramento
inteiramente e apenas dar o corpo @code{do @var{corpo}} que continuará a ser 
avaliado indefinidamente.  Nesse caso a função @code{return} será usada para
encerrar a execução da declaração @code{do}.

@example
(%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
@end example

@c DUNNO IF WE NEED THIS LEVEL OF DETAIL; THIS ARTICLE IS GETTING PRETTY LONG
(Note que @code{return}, quando executado, faz com que o valor corrente de
@code{x} seja retornado como o valor da declaração @code{do}.  O @code{block} é encerrado e
esse valor da declaração @code{do} é retornado como o valor do @code{block} porque o
@code{do} é a última declaração do @code{block}.)

Uma outra forma de @code{do} é disponível no Maxima.  A sintaxe é:

@example
for @var{Variável} in @var{list} @var{end_tests} do @var{corpo}
@end example

Os elementos de @var{list} são quaisquer expressões que irão
sucessivamente ser atribuídas para a variável a cada iteração do
corpo.  O teste opcional @var{end_tests} pode ser usado para encerrar a execução da
declaração @code{do}; de outra forma o @code{do} terminará quando a lista for exaurida ou quando
um @code{return} for executado no corpo.  (De facto, a lista pode ser qualquer
expressão não at@^omica, e partes sucessivas são usadas.)

@example
(%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
@end example

@end deffn

@deffn {Função} errcatch (@var{expr_1}, ..., @var{expr_n})
Avalia @var{expr_1}, ..., @var{expr_n} uma por uma e
retorna @code{[@var{expr_n}]} (uma lista) se nenhum erro ocorrer.  Se um
erro ocorrer na avaliação de qualquer argumento, @code{errcatch}
evita que o erro se propague e
retorna a lista vazia @code{[]} sem avaliar quaisquer mais argumentos.

@code{errcatch}
é útil em ficheiros @code{batch} onde se suspeita que um erro possa estar ocorrendo o @code{errcatch}
terminará o @code{batch} se o erro não for detectado.

@end deffn

@deffn {Função} error (@var{expr_1}, ..., @var{expr_n})
@deffnx {Variável de sistema} error
Avalia e imprime @var{expr_1}, ..., @var{expr_n},
e então causa um retorno de erro para o nível mais alto do Maxima
ou para o mais próximo contendo @code{errcatch}.

A variável @code{error} é escolhida para uma lista descrevendo o erro.
O primeiro elemento de @code{error} é uma sequência de caracteres de formato,
que junta todas as sequências de caracteres entre os argumentos @var{expr_1}, ..., @var{expr_n},
e os elementos restantes são os valores de quaisquer argumentos que não são sequências de caracteres.

@code{errormsg()} formata e imprime @code{error}.
Isso efectivamente reimprime a mais recente mensagem de erro.

@end deffn

@deffn {Função} errormsg ()
Reimprime a mais recente mensagem de erro.
A variável @code{error} recebe a mensagem,
e @code{errormsg} formata e imprime essa mensagem.

@end deffn

@c REPHRASE
@c AT LEAST SHOULD LIST VARIANTS HERE
@deffn {Operador especial} for
Usado em iterações.  Veja @code{do} para uma descrição das
facilidades de iteração do Maxima.

@end deffn

@deffn {Função} go (@var{tag})
é usada dentro de um @code{block} para transferir o controle para a declaração
do bloco que for identificada com o argumento para @code{go}.  Para identificar uma
declaração, coloque antes dessa declaração um argumento at@^omico como outra declaração no
@code{block}.  Por exemplo:

@example
block ([x], x:1, loop, x+1, ..., go(loop), ...)
@end example

O argumento para @code{go} deve ser o nome de um identificardor aparecendo no mesmo
@code{block}.  Não se pode usar @code{go} para transferir para um identificador em um outro @code{block} que não seja
o próprio contendo o @code{go}.

@end deffn

@c NEEDS CLARIFICATION, EXPANSION, EXAMPLES
@c THIS ITEM IS IMPORTANT
@deffn {Operador especial} if
Representa avaliação condicional. Várias formas de expressões @code{if} são reconhecidas.
@code{if @var{cond_1} then @var{expr_1} else @var{expr_0}}
avalia para @var{expr_1} se @var{cond_1} avaliar para @code{true},
de outra forma a expressão avalia para @code{expr_0}.

@code{if @var{cond_1} then @var{expr_1} elseif @var{cond_2} then @var{expr_2} elseif ... else @var{expr_0}}
avalia para @var{expr_k} se @var{cond_k} for @code{true} e todas as condições precedentes forem @code{false}.
Se nenhuma das condições forem @code{true}, a expressão avalia para @code{expr_0}.

O comportamento @code{else false} é assumido se @code{else} for omitido.
Isso é, @code{if @var{cond_1} then @var{expr_1}} é equivalente a
@code{if @var{cond_1} then @var{expr_1} else false},
e @code{if @var{cond_1} then @var{expr_1} elseif ... elseif @var{cond_n} then @var{expr_n}}
é equivalente a
@code{if @var{cond_1} then @var{expr_1} elseif ... elseif @var{cond_n} then @var{expr_n} else false}.

As alternativas @var{expr_0}, ..., @var{expr_n} podem ser quaisquer expressões do Maxima,
incluíndo expressões @code{if} aninhadas ( if dentro de if).
As alternativas não são nem simplificadas nem avaliadas a menos que a correspondente condição seja @code{true}.

As condições @var{cond_1}, ..., @var{cond_n} são expressões tais que @code{is(@var{cond_k})} avaliem
para @code{true} ou para @code{false};
de outra forma é um erro.
Entre outros elementos, condições podem compreender operadores lógicos e relacionais como segue.

@c - SEEMS LIKE THIS TABLE WANTS TO BE IN A DISCUSSION OF PREDICATE FUNCTIONS; PRESENT LOCATION IS OK I GUESS
@c - REFORMAT THIS TABLE USING TEXINFO MARKUP (MAYBE)
@example
Operação             Símbolo      Tipo
 
menor que            <           infixo relacional
menor que            <=
  ou igual a                     infixo relacional
igualdade            =
  (sintática)                    infixo relacional
negação de =         #           infixo relacional
igualdade (valor)    equal       função relacional
negação de           notequal
  igualdade                      função relacional
maior que            >=
  ou igual a                     infixo relacional
maior que            >           infixo relacional
e                    and         infixo lógico
ou                   or          infixo lógico
não                  not         prefixo lógico
@end example

@end deffn

@c NEEDS CLARIFICATION
@c THIS ITEM IS IMPORTANT
@deffn {Função} map (@var{f}, @var{expr_1}, ..., @var{expr_n})
Retorna uma expressão cujo operador principal
é o mesmo que o das expressões
@var{expr_1}, ..., @var{expr_n} mas cujas subpartes são os resultados da
aplicação de @var{f} nas correspondentes subpartes das expressões.  @var{f} é ainda
o nome de uma função de @math{n} argumentos
ou é uma forma @code{lambda} de @math{n} argumentos.

@code{maperror} - se @code{false} fará com que todas as funções mapeadas
(1) parem quando elas terminarem retornando a menor expi se não forem todas as
expi do mesmo comprimento e (2) aplique fn a [exp1, exp2,...]
se expi não forem todas do mesmo tipo de objecto.  Se @code{maperror} for @code{true}
então uma mensagem de erro será dada nas duas instâncias acima.

Um dos usos dessa função é para mapear (@code{map}) uma função (e.g. @code{partfrac})
sobre cada termo de uma expressão muito larga onde isso comumente não poderia
ser possível usar a função sobre a expressão inteira devido a uma
exaustão de espaço da lista de armazenamento no decorrer da computação.

@c IN THESE EXAMPLES, SPELL OUT WHAT IS THE MAIN OPERATOR 
@c AND SHOW HOW THE RESULT FOLLOWS FROM THE DESCRIPTION STATED IN THE FIRST PARAGRAPH
@example
(%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]


@end example
@end deffn

@deffn {Função} mapatom (@var{expr})
Retorna @code{true} se e somente se @var{expr} for tratada pelas rotinas de
mapeamento como um átomo.  "Mapatoms" são átomos, números
(incluíndo números racioanais), e variáveis subscritas.
@c WHAT ARE "THE MAPPING ROUTINES", AND WHY DO THEY HAVE A SPECIALIZED NOTION OF ATOMS ??

@end deffn

@c NEEDS CLARIFICATION
@defvr {Variável de opção} maperror
Valor por omissão: @code{true}

Quando @code{maperror} é @code{false}, faz com que todas as funções mapeadas, por exemplo

@example
map (f, expr_1, expr_2, ...))
@end example

(1) parem quando elas terminarem
retornando a menor expi se não forem todas as expi do mesmo
comprimento e (2) aplique @code{f} a @code{[expr_1, expr_2, ...]} se @code{expr_i} não forem todas
do mesmo tipo de objecto.

Se @code{maperror} for @code{true} então uma ,mensagem de erro
é mostrada nas duas instâncias acima.

@end defvr

@c NEEDS CLARIFICATION
@deffn {Função} maplist (@var{f}, @var{expr_1}, ..., @var{expr_n})
Retorna uma lista de aplicações de @var{f}
em todas as partes das expressões @var{expr_1}, ..., @var{expr_n}.
@var{f} é o nome de uma função, ou uma expressão lambda.

@code{maplist} difere de @code{map (@var{f}, @var{expr_1}, ..., @var{expr_n})}
que retorna uma expressão com o mesmo operador principal que @var{expr_i} tem
(excepto para simplificações  e o caso onde @code{map} faz um @code{apply}).

@end deffn

@c NEEDS CLARIFICATION
@defvr {Variável de opção} prederror
Valor por omissão: @code{true}

Quando @code{prederror} for @code{true}, uma mensagem de erro é mostrada
sempre que o predicado de uma declaração @code{if} ou uma função @code{is} falha em
avaliar ou para @code{true} ou para  @code{false}.

Se @code{false}, @code{unknown} é retornado
no lugar nesse caso.  O modo @code{prederror: false} não é suportado no
código traduzido;
todavia, @code{maybe} é suportado no código traduzido.

Veja também @code{is} e @code{maybe}.

@end defvr

@deffn {Função} return (valor)
Pode ser usada para sair explicitamente de um bloco, levando
seu argumento.  Veja @code{block} para mais informação.

@end deffn

@c NEEDS CLARIFICATION
@deffn {Função} scanmap (@var{f}, @var{expr})
@deffnx {Função} scanmap (@var{f}, @var{expr}, bottomup)
Recursivamente aplica @var{f} a @var{expr}, de cima
para baixo.  Isso é muito útil quando uma factoração completa é
desejada, por exemplo:

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

Note o caminho através do qual @code{scanmap} aplica a dada função @code{factor} para as
subexpressões constituintes de @var{expr}; se outra forma de @var{expr} é apresentada
para @code{scanmap} então o resultado pode ser diferente.  Dessa forma, @code{%o2} não é
recuperada quando @code{scanmap} é aplicada para a forma expandida de exp:

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

Aqui está um outro exemplo do caminho no qual @code{scanmap} aplica
recursivamente uma função dada para todas as subexpressões, incluindo expoentes:

@example
(%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))
@end example

@code{scanmap (@var{f}, @var{expr}, bottomup)} aplica @var{f} a @var{expr} de
baixo para cima.  E.g., para @code{f} indefinida,

@example
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))
@end example

Neste caso, obtém-se a mesma resposta pelos dois métodos.

@end deffn

@deffn {Função} throw (@var{expr})
Avalia @var{expr} e descarta o valor retornado para o mais recente
@code{catch}.  @code{throw} é usada com @code{catch} como um mecanismo
de retorno não local.

@end deffn

@c NEED MORE HERE !!
@c AT LEAST SHOULD LIST ACCEPTABLE VARIANTS
@deffn {Operador especial} while
Veja @code{do}.

@end deffn

@deffn {Função} outermap (@var{f}, @var{a_1}, ..., @var{a_n})
Aplica a função @var{f} para cada um dos elementos do produto externo
@var{a_1} vezes @var{a_2} ... vezes @var{a_n}.

@var{f} é o nome de uma função de @math{n} argumentos
ou uma expressão lambda de @math{n} argumentos.
Cada argumento @var{a_k} pode ser uma lista simples ou lista aninhada ( lista contendo listas como elementos ), ou uma matrz, ou qualquer outro tip de expressão.

O valor de retorno de @code{outermap} é uma estrutura aninhada.
Tomemos @var{x} como sendo o valor de retorno.
Então @var{x} tem a mesma estrutura da primeira lista, lista aninhada, ou argumento matriz,
@code{@var{x}[i_1]...[i_m]} tem a mesma estrutura que a segunda lista, lista aninhada, ou argumento matriz,
@code{@var{x}[i_1]...[i_m][j_1]...[j_n]} tem a mesma estrutura que a terceira lista, lista aninhada, ou argumento matriz,
e assim por diante,
onde @var{m}, @var{n}, ... são os números dos índices requeridos para acessar os
elementos de cada argumento (um para uma lista, dois para uma matriz, um ou mais para uma lista aninhada).
Argumentos que não forem listas ou matrizes não afectam a estrutura do valor de retorno.

Note que o efeito de @code{outermap} é diferente daquele de aplicar @var{f}
a cada um dos elementos do produto externo retornado por @code{cartesian_product}.
@code{outermap} preserva a estrutura dos argumentos no valor de retorno,
enquanto @code{cartesian_product} não reserva essa mesma estrutura.

@code{outermap} avalia seus argumentos.

Veja também @code{map}, @code{maplist}, e @code{apply}.
@c CROSS REF OTHER FUNCTIONS HERE ??

Exemplos:
Exemplos elementares de @code{outermap}.
Para mostrar a a combinação de argumentos mais claramente, @code{F} está indefinida à esquerda.

@c ===beg===
@c outermap (F, [a, b, c], [1, 2, 3]);
@c outermap (F, matrix ([a, b], [c, d]), matrix ([1, 2], [3, 4]));
@c outermap (F, [a, b], x, matrix ([1, 2], [3, 4]));
@c outermap (F, [a, b], matrix ([1, 2]), matrix ([x], [y]));
@c outermap ("+", [a, b, c], [1, 2, 3]);
@c ===end===
@example
(%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]]
@end example

Uma explanação final do valor de retorno de @code{outermap}.
Os argumentos primeiro, segundo, e terceiro são matriz, lista, e matriz, respectivamente.
O valor de retorno é uma matriz.
Cada elementos daquela matriz é uma lista,
e cada elemento de cada lista é uma matriz.

@c ===beg===
@c arg_1 :  matrix ([a, b], [c, d]);
@c arg_2 : [11, 22];
@c arg_3 : matrix ([xx, yy]);
@c xx_0 : outermap (lambda ([x, y, z], x / y + z), arg_1, arg_2, arg_3);
@c xx_1 : xx_0 [1][1];
@c xx_2 : xx_0 [1][1] [1];
@c xx_3 : xx_0 [1][1] [1] [1][1];
@c [op (arg_1), op (arg_2), op (arg_3)];
@c [op (xx_0), op (xx_1), op (xx_2)];
@c ===end===
@example
(%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]
@end example

@code{outermap} preserves the structure of the arguments in the return value,
while @code{cartesian_product} does not.

@c ===beg===
@c outermap (F, [a, b, c], [1, 2, 3]);
@c setify (flatten (%));
@c map (lambda ([L], apply (F, L)), cartesian_product ({a, b, c}, {1, 2, 3}));
@c is (equal (%, %th (2)));
@c ===end===
@example
(%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
@end example

@end deffn

