[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Índice] [ ? ]

42. Fluxo de Programa


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Índice] [ ? ]

42.1 Introdução a Fluxo de Programa

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


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Índice] [ ? ]

42.2 Definições para Fluxo de Programa

Função: backtrace ()
Função: backtrace (n)

Imprime a pilha de chamadas, que é, a lista de funções que foram chamadas pela função correntemente ativa.

backtrace() imprime toda a pilha de chamadas.

backtrace (n) imprime as n mais recentes chamadas a funções, incluindo a função correntemente ativa.

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:

Operador especial: do

A declaração do é usada para executar iteração. Devido à sua grande generalidade a declaração 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 do que diferem somente por suas condições de encerramento. São elas:

(Alternativamente, o step pode ser dado após a condição de encerramento ou limite.)

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

A execução da declaração 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 thru, ou se a condição de unless for true, ou se a condição de while for false então o 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 do termina quando qualquer delas for satisfeita.

Em geral o teste 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 do for iniciada, Maxima assume que o incremento e o limite serão positivos quando o do for executado. Se o limite e o incremento não forem positivos, então o 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 do e usar essa variável na forma do.

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

A variável de controle é sempre local para o do e dessa forma qualquer variável pode ser usada sem afetar o valor de uma variável com o mesmo nome fora da declaração do. A variável de controle é liberada após o encerramento da declaração 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

Note que a condição while i <= 10 é equivalente a unless i > 10 e também 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

que fornece 8 termos da série de Taylor para 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

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 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 next expressão em lugar de step 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.

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

                            count = 6

                           count = 18

Como uma alternativa para for Variável: valor ...do... a sintaxe for Variável from valor ...do... pode ser usada. Isso permite o from valor ser colocado após o step ou proximo valor ou após a condição de encerramento. Se from 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 atualização como no exemplo seguinte para para calcular a raíz quadrada de 5 usando uma fraca suposição inicial.

 
(%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

Se isso for desejado pode-se sempre omitir as condições de encerramento inteiramente e apenas dar o corpo do corpo que continuará a ser avaliado indefinidamente. Nesse caso a função return será usada para encerrar a execução da declaração 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

(Note que return, quando executado, faz com que o valor corrente de x seja retornado como o valor da declaração do. O block é encerrado e esse valor da declaração do é retornado como o valor do block porque o do é a última declaração do block.)

Uma outra forma de do é disponível no Maxima. A sintaxe é:

 
for Variável in list end_tests do corpo

Os elementos de 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 end_tests pode ser usado para encerrar a execução da declaração do; de outra forma o do terminará quando a lista for exaurida ou quando um return for executado no corpo. (De fato, a lista pode ser qualquer expressão não atômica, e partes sucessivas são usadas.)

 
(%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
Função: errcatch (expr_1, ..., expr_n)

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

errcatch é útil em arquivos batch onde se suspeita que um erro possa estar ocorrendo o errcatch terminará o batch se o erro não for detectado.

Função: error (expr_1, ..., expr_n)
Variável de sistema: error

Avalia e imprime expr_1, ..., 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 errcatch.

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

errormsg() formata e imprime error. Isso efetivamente reimprime a mais recente mensagem de erro.

Função: errormsg ()

Reimprime a mais recente mensagem de erro. A variável error recebe a mensagem, e errormsg formata e imprime essa mensagem.

Operador especial: for

Usado em iterações. Veja do para uma descrição das facilidades de iteração do Maxima.

Função: go (tag)

é usada dentro de um block para transferir o controle para a declaração do bloco que for identificada com o argumento para go. Para identificar uma declaração, coloque antes dessa declaração um argumento atômico como outra declaração no block. Por exemplo:

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

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

Operador especial: if

A declaração if é usada para execução condicional. A sintaxe é:

 
if <condição> then <expr_1> else <expr_2>

O resultado de uma declaração if será expr_1 se condição for true e expr_2 de outra forma. expr_1 e expr_2 são quaisquer expressões Maxima (incluindo declarações if aninhadas), e condição é uma expressão que avalia para true ou false e é composto de operadores relacionais e lógicos que são os seguintes:

 
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
Função: map (f, expr_1, ..., expr_n)

Retorna uma expressão cujo operador principal é o mesmo que o das expressões expr_1, ..., expr_n mas cujas subpartes são os resultados da aplicação de f nas correspondentes subpartes das expressões. f é ainda o nome de uma função de n argumentos ou é uma forma lambda de n argumentos.

maperror - se 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 objeto. Se maperror for true então uma mensagem de erro será dada nas duas instâncias acima.

Um dos usos dessa função é para mapear (map) uma função (e.g. 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.

 
(%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]


Função: mapatom (expr)

Retorna true se e somente se 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.

Variável de opção: maperror

Valor padrão: true

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

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

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

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

Função: maplist (f, expr_1, ..., expr_n)

Retorna uma lista de aplicações de f em todas as partes das expressões expr_1, ..., expr_n. f é o nome de uma função, ou uma expressão lambda.

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

Variável de opção: prederror

Valor padrão: true

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

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

Veja também is e maybe.

Função: return (valor)

Pode ser usada para sair explicitamente de um bloco, levando seu argumento. Veja block para mais informação.

Função: scanmap (f, expr)
Função: scanmap (f, expr, bottomup)

Recursivamente aplica f a expr, de cima para baixo. Isso é muito útil quando uma fatoração completa é desejada, por exemplo:

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

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

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

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

 
(%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 baixo para cima. E.g., para f indefinida,

 
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))

Nesse caso, você pega a mesma resposta em ambos os caminhos.

Função: throw (expr)

Avalia expr e descarta o valor retornado para o mais recente catch. throw é usada com catch como um mecanismo de retorno não local.

Função: outermap (f, a_1, ..., a_n)

Aplica a função f para cada um dos elementos do produto externo a_1 vezes a_2 ... vezes a_n.

f é para ser o nome de uma função de n argumentos ou uma expressão lambda de n argumentos. Os argumentos a_1, ..., a_n podem ser listas ou não listas. Argumentos listas podem ter diferentes comprimentos. Argumentos outros que não listas são tratados como listas de comprimento 1 para o propósito de construção do produto externo.

O resultado da aplicação de f para o produto externo é organizado como uma lista aninhada. A intensidade do aninhamento é igual ao número de argumentos listas (argumentos outros que não listas não contribuem com um nível de aninhamento). Uma lista de intensidade de aninhamento k tem o mesmo comprimento que o k'ésimo argumento da lista.

outermap avalia seus argumentos.

Veja também map, maplist, e apply.

Exemplos:

 
(%i1) f (x, y) := x - y$
(%i2) outermap (f, [2, 3, 5], [a, b, c, d]);
(%o2) [[2 - a, 2 - b, 2 - c, 2 - d], 
      [3 - a, 3 - b, 3 - c, 3 - d], [5 - a, 5 - b, 5 - c, 5 - d]]
(%i3) outermap (lambda ([x, y], y/x), [55, 99], [Z, W]);
                        Z   W     Z   W
(%o3)                 [[--, --], [--, --]]
                        55  55    99  99
(%i4) g: lambda ([x, y, z], x + y*z)$
(%i5) outermap (g, [a, b, c], %pi, [11, 17]);
(%o5) [[a + 11 %pi, a + 17 %pi], [b + 11 %pi, b + 17 %pi], 
                                        [c + 11 %pi, c + 17 %pi]]
(%i6) flatten (%);
(%o6) [a + 11 %pi, a + 17 %pi, b + 11 %pi, b + 17 %pi, 
                                          c + 11 %pi, c + 17 %pi]

[ << ] [ >> ]           [Top] [Contents] [Índice] [ ? ]

This document was generated by root on Outubro, 3 2006 using texi2html 1.76.