File: Program.es.texi

package info (click to toggle)
maxima 5.10.0-6
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 44,268 kB
  • ctags: 17,987
  • sloc: lisp: 152,894; fortran: 14,667; perl: 14,204; tcl: 10,103; sh: 3,376; makefile: 2,202; ansic: 471; awk: 7
file content (540 lines) | stat: -rw-r--r-- 26,501 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
@c version 1.21
@menu
* Introducci@'on a la Programaci@'on::  
* Definiciones para la Programaci@'on::  
@end menu

@node Introducci@'on a la Programaci@'on, Definiciones para la Programaci@'on, Programaci@'on, Programaci@'on
@section Introducci@'on a la Programaci@'on

Maxima dispone de los bucles @code{do} para hacer iteraciones, as@'{@dotless{i}} como estructuras m@'as primitivas del estilo de @code{go}.


@node Definiciones para la Programaci@'on,  , Introducci@'on a la Programaci@'on, Programaci@'on
@section Definiciones para la Programaci@'on

@deffn {Funci@'on} backtrace ()
@deffnx {Funci@'on} backtrace (@var{n})
Devuelve la pila de llamadas, esto es, la lista de funciones que han llamado a la funci@'on actualmente activa.

La llamada a @code{backtrace()} devuelve la pila completa de llamadas.

Ejemplos:

@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

La llamada @code{backtrace (@var{n})} devuelve las @var{n} funciones m@'as recientes, incluyendo a la funci@'on actualmente activa.

Ejemplos:

@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 deffn

@deffn {Operador especial} do
La sentencia @code{do} se utiliza para realizar iteraciones.  Debido a su generalidad la sentencia @code{do} se describir@'a en dos partes. En primer lugar se mostrar@'a su forma m@'as usual, an@'aloga a la de otros lenguajes de programaci@'on (Fortran, Algol, PL/I, etc.); despu@'es se mencionar@'an otras formas de uso.

Hay tres variantes de esta sentencia que se diferencian entre s@'{@dotless{i}} @'unicamente por las condiciones de fin de bucle. Son las siguientes:

@itemize @bullet
@item
@code{for @var{variable}: @var{valor_inicial} step @var{incremento}
      thru @var{l@'{@dotless{i}}mite} do @var{cuerpo}}
@item
@code{for @var{variable}: @var{valor_inicial} step @var{incremento}
      while @var{condici@'on} do @var{cuerpo}}
@item
@code{for @var{variable}: @var{valor_inicial} step @var{incremento}
      unless @var{condici@'on} do @var{cuerpo}}
@end itemize

El @var{valor_inicial}, el @var{incremento}, el @var{l@'{@dotless{i}}mite} y el @var{cuerpo} pueden ser cualquier tipo de expresi@'on v@'alida de Maxima. Si el incremento es igual a la unidad (1) entonces "@code{step 1}" puede omitirse.

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

En general la condici@'on @code{thru} se satisfar@'a cuando la variable-control sea mayor que el l@'{@dotless{i}}mite si el incremento es no negativo, o cuando la variable-control sea menor que el l@'{@dotless{i}}mite cuando el incremento es negativo. El incremento y el l@'{@dotless{i}}mite pueden ser expresiones no num@'ericas, tanto en cuanto esta desigualdad pueda quedar determinada. Sin embargo, a menos que el incremento sea un n@'umero negativo en el momento de comenzar el c@'omputo de @code{do}, Maxima supondr@'a que se evaluar@'a a una cantidad positiva. En caso de no ser efectivamente positivo, la sentencia @code{do} puede dar un resultado inesperado.

N@'otese que el l@'{@dotless{i}}mite, el incremento y la condici@'on de terminaci@'on se eval@'uan en cada iteraci@'on del bucle. As@'{@dotless{i}}, si alguna de expresiones necesitan de muchos c@'alculos y devuelven un resultado que no va a cambiar durante toda la ejecuci@'on del cuerpo, ser@'a m@'as eficiente dar este valor a una variable antes de comenzar la sentencia @code{do} y utilizarla luego durante su ejecuci@'on.

El valor que habitualmente devuelva la sentencia @code{do} ser@'a el @'atomo @code{done}. Sin embargo, la funci@'on @code{return} puede usarse dentro del cuerpo para salir de @code{do} de forma prematura retornando un valor determinado.
N@'otese no obstante que un @code{return} dentro de un @code{do} que est@'a dentro de un bloque (@code{block}) provocar@'a una salida de @code{do} pero no de @code{block}. Rep@'arese tambi@'en en que la funci@'on @code{go} no puede usarse para salir de @code{do} e ir a alg@'un lugar de @code{block}.

La variable-control es siempre local respecto de @code{do}, por lo que se puede utilizar cualquier nombre de variable sin afectar el valor de cualquier otra variable externa a @code{do} y que tenga el mismo nombre. La variable-control no tendr@'a asignado ning@'un valor una vez se haya concluido el @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


N@'otese que la condici@'on @code{while i <= 10} es equivalente a @code{unless i > 10} y a @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

lo que da ocho t@'erminos del desarrollo de Taylor de la funci@'on @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

Este ejemplo calcula la ra@'{@dotless{i}}z cuadrada negativa de 10 haciendo 10 iteraciones del m@'etodo de Newton-Raphson. De no haberse alcanzado el criterio de convergencia el valor devuelto hubiese sido @code{done}.

En lugar de a@~nadir siempre una cantidad a la variable-control a veces se puede querer que cambie en cada iteraci@'on siguiendo alg@'un otro criterio. En tal caso se puede hacer uso de @code{next @var{expresi@'on}} en lugar de @code{step @var{incremento}}. Esto har@'a que a la variable-control se le asigne el resultado de evaluar la expresi@'on en cada iteraci@'on del bucle.

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

                            count = 6

                           count = 18
@end example

En ocasiones puede interesar realizar una iteraci@'on en la que la variable-control no se utilice nunca. Se podr@'a entonces dar @'unicamente las condiciones de terminaci@'on del bucle omitiendo la inicializaci@'on y actualizando la informaci@'on, tal como se hace en el siguiente ejemplo para calcular la ra@'{@dotless{i}}z cuadrada de 5 utilizando un valor inicial alejado de la soluci@'on.

@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

Si as@'{@dotless{i}} se quiere, incluso es posible omitir las condiciones de terminaci@'on completamente y escribir @'unicamente @code{do @var{body}}, lo que provocar@'a entrar en un bucle infinito. En tal caso, deber@'{@dotless{i}}a usarse la funci@'on @code{return} a fin de terminar con la ejecuci@'on de @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

(En este ejemplo, cuando se ejecuta @code{return} obliga a que sea @code{x} el valor devuelto por @code{do}. Al salirse del bloque, @code{x} es tambi@'en el valor que devuelve @code{block} por ser @code{do} la @'ultima sentencia del bloque.)

Hay todav@'{@dotless{i}}a otra forma de @code{do} en Maxima. Su sintaxis es:

@example
for @var{variable} in @var{lista} @var{test_de_parada} do @var{cuerpo}
@end example

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

@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 {Funci@'on} errcatch (@var{expr_1}, ..., @var{expr_n})
Eval@'ua las expresiones @var{expr_1}, ..., @var{expr_n} una a una y devuelve @code{[@var{expr_n}]} (una lista) en caso de que no ocurra ning@'un error. En caso de aparecer alg@'un error durante el c@'alculo de alguno de los argumentos, @code{errcatch} evita que el error se propague y devuelve la lista vac@'{@dotless{i}}a @code{[]} sin evaluar m@'as argumentos.

La funci@'on @code{errcatch} es @'util en ficheros @code{batch} donde se sospeche que pueda aparecer alg@'un error, el cual provocar@'{@dotless{i}}a la terminaci@'on de la ejecuci@'on del @code{batch} de no ser previamente detectado.

@end deffn

@deffn {Funci@'on} error (@var{expr_1}, ..., @var{expr_n})
@deffnx {Variable del sistema} error
Calcula y devuelve @var{expr_1}, ..., @var{expr_n}, enviando posteriormente una se@~al de error a Maxima o al @code{errcatch} m@'as cercano. 

A la variable @code{error} se le asigna una lista con la descripci@'on del error. El primer elemento de @code{error} es una cadena de formato, la cual une todas las cadenas de los argumentos @var{expr_1}, ..., @var{expr_n}, siendo los dem@'as elementos de la lista los valores de los argumentos que no son cadenas.

La llamada a @code{errormsg()} formatea e imprime @code{error}. Se reimprime as@'{@dotless{i}} el mensaje de error m@'as reciente.

@end deffn

@deffn {Funci@'on} errormsg ()

Reimprime el mensaje de error m@'as reciente. La variable @code{error} guarda el mensaje y @code{errormsg} lo formatea e imprime.

@end deffn

@deffn {Operador especial} for
Utilizado en las iteraciones. V@'ease @code{do} para una descripci@'on de las t@'ecnicas de iteraci@'on en Maxima.

@end deffn

@deffn {Funci@'on} go (@var{etiqueta})
Se utiliza dentro de un bloque (@code{block}) para transferir el control a la sentencia del bloque que est@'e etiquetada con el argumento de @code{go}. Una sentencia queda etiquetada cuando est@'a precedida por un argumento de tipo @'atomo como cualquier otra sentencia de @code{block}.  Por ejemplo:

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

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

@end deffn

@deffn {Operador especial} if
La sentencia @code{if} se utiliza para la ejecuci@'on condicionada.  Su sintaxis es:

@example
if <condici@'on> then <expr_1> else <expr_2>
@end example

El resultado de una sentencia @code{if} es @var{expr_1} si la condici@'on es verdadera (@code{true}) y @var{expr_2} si es falsa. Tanto @var{expr_1} como @var{expr_2} son expresiones correctas en Maxima (incluyendo sentencias @code{if} anidadas) y  @var{condition} es una expresi@'on que puede ser verdadera (@code{true}) o falsa (@code{false}), formada con los operadores relacionales y l@'ogicos siguientes:

@example
Operaci@'on               S@'{@dotless{i}}mbolo     Tipo
 
menor que               <           operador relacional infijo
menor o igual que       <=          operador relacional infijo
igualdad (sint@'actica)   =           operador relacional infijo
negaci@'on de =           #           operador relacional infijo
igualdad (por valor)    equal       operador relacional infijo
negaci@'on de equal       notequal    operador relacional infijo
mayor o igual que       >=          operador relacional infijo
mayor que               >           operador relacional infijo
y                       and         operador l@'ogico infijo
o                       or          operador l@'ogico infijo
no                      not         operador l@'ogico prefijo
@end example

@end deffn

@deffn {Funci@'on} map (@var{f}, @var{expr_1}, ..., @var{expr_n})
Devuelve una expresi@'on cuyo operador principal es el mismo que aparece en las expresiones @var{expr_1}, ..., @var{expr_n} pero cuyas subpartes son los resultados de aplicar @var{f} a cada una de las subpartes de las expresiones;  @var{f} puede ser tanto el nombre de una funci@'on de @math{n} argumentos o una forma @code{lambda} de @math{n} argumentos.

Uno de los usos que tiene @code{map} es la de aplicar (o mapear) una funci@'on (por ejemplo, @code{partfrac}) sobre cada t@'ermino de una expresi@'on extensa en la que normalmente no se podr@'{@dotless{i}}a utilizar la funci@'on debido a insuficiencias en el espacio de almacenamiento durante el curso de un c@'alculo.

@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 {Funci@'on} mapatom (@var{expr})
Devuelve @code{true} si y s@'olo @var{expr} es tratado por las rutinas de mapeo como un @'atomo.

@end deffn

@defvr {Variable opcional} maperror
Valor por defecto: @code{true}

Cuando @code{maperror} toma el valor @code{false}, hace que todas las funciones de mapeo, como por ejemplo

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

(1) paren cuando hayan terminado de procesar la expi m@'as corta, a menos que todas ellas sean del mismo tama@~no y (2) apliquen  @code{f} a @code{[expr_1, expr_2, ...]} si es el caso que las @code{expr_i} no son todas del mismo tipo de objeto.

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

@end defvr

@deffn {Funci@'on} maplist (@var{f}, @var{expr_1}, ..., @var{expr_n})
Devuelve una lista con las aplicaciones de @var{f} a las partes de las expresiones @var{expr_1}, ..., @var{expr_n}; @var{f} es el nombre de una funci@'on ou una expresi@'on lambda.

La funci@'on @code{maplist} difiere de @code{map (@var{f}, @var{expr_1}, ..., @var{expr_n})}, la cual devuelve una expresi@'on con el mismo operador principal que tenga @var{expr_i}, excepto en simplificaciones y en el caso en el que @code{map} hace un @code{apply}.

@end deffn

@defvr {Variable opcional} prederror
Valor por defecto: @code{true}

Cuando @code{prederror} toma el valor @code{true}, se emite un mensaje de error siempre que el predicado de una sentencia  @code{if} o de una funci@'on @code{is} no se pueda evaluar ni a verdadero (@code{true}) ni  a falso (@code{false}).

Si toma el valor @code{false}, se devuelve bajo las mismas circunstancias anteriores el valor @code{unknown}. El modo @code{prederror: false} no est@'a soportado en el c@'odigo traducido; sin embargo, @code{maybe} est@'a soportado en c@'odigo traducido.

V@'eanse tambi@'en @code{is} y @code{maybe}.

@end defvr

@deffn {Funci@'on} return (valor)
Puede utilizarse para salir de un bloque, devolviendo su.  V@'ease @code{block} para m@'as informaci@'on.

@end deffn

@deffn {Funci@'on} scanmap (@var{f}, @var{expr})
@deffnx {Funci@'on} scanmap (@var{f}, @var{expr}, bottomup)
Aplica recursivamente @var{f} sobre @var{expr}, de arriba hacia abajo. Esto es m@'as @'util cuando se busca una factorizaci@'on completa, por ejemplo:

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

N@'otese que c@'omo @code{scanmap} aplica la funci@'on dada @code{factor} a las subexpresiones que forman a @var{expr}; si se presenta otra forma de @var{expr} a @code{scanmap} entonces el resultado puede ser diferente. As@'{@dotless{i}}, @code{%o2} no se restaura cuando @code{scanmap} se aplica a la forma expandida de exp:

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

Aqu@'{@dotless{i}} hay otro ejemplo de la forma en que @code{scanmap} aplica recursivamente una funci@'on dada a todas las subexpresiones, incluyendo exponentes:

@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 abajo hacia arriba. Por ejemplo, para @code{f} no definida,

@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

En este caso se obtiene la misma respuesta por cualquiera de los dos m@'etodos.

@end deffn

@deffn {Funci@'on} throw (@var{expr})
Eval@'ua @var{expr} y devuelve el valor del @code{catch} m@'as reciente. La funci@'on @code{throw} se utiliza junto con @code{catch} como un mecanismo de retorno no local.

@end deffn

@deffn {Funci@'on} outermap (@var{f}, @var{a_1}, ..., @var{a_n})
Aplica la funci@'on @var{f} a cada uno de los elementos del producto vectorial @var{a_1} por @var{a_2} ... por @var{a_n}.

El argumento @var{f} debe ser el nombre de una funci@'on de @math{n} argumentos,
o una expresi@'on lambda de @math{n} argumentos.
Cada uno de los argumentos @var{a_k} puede ser una lista, una lista anidada, 
una matriz o cualquier otro tipo de expresi@'on.

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

N@'otese que el efecto producido por @code{outermap} es diferente del que
se obtiene al aplicar @var{f} a cada uno de los elementos del producto
devuelto por @code{cartesian_product}. La funci@'on @code{outermap}
mantiene la estructura de los argumentos en la respuesta, miemtras que
@code{cartesian_product} no lo hace.

La funci@'on @code{outermap} eval@'ua sus argumentos.

V@'eanse tambi@'en @code{map}, @code{maplist} y @code{apply}.

Ejemplos:

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


@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

El siguiente ejemplo permite hacer un an@'alisis m@'as profundo del valor
retornado por @code{outermap}.
Los tres primeros argumentos son una matriz, una lista y otra matriz, en este
orden. El valor devuelto es una matriz, cuyos elementos son listas y
cada elemento de cada una de estas listas es a su vez una matriz.

@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

La funci@'on @code{outermap} mantiene la estructura de los argumentos en su respuesta,
mientras que @code{cartesian_product} no lo hace.

@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