Previous: Макросы, Up: Определение функций   [Contents][Index]

37.4 Функции и переменные для определения функций

Функция: apply (F, [x_1, ..., x_n])

Составляет и вычисляет выражение F(arg_1, ..., arg_n).

Функция apply не пытается различить функцию-массив и обычную функцию, и если F есть имя функции-массива, то apply вычисляет F(...) (т.е. обычный вызов функции с круглыми а не с квадратными скобками). Функция arrayapply вычисляет вызов функции с квадратными скобками.

Примеры:

Функция apply вычисляет свои аргументы. В этом примере, min применяется к значению L.

(%i1) L : [1, 5, -10.2, 4, 3];
(%o1)                 [1, 5, - 10.2, 4, 3]
(%i2) apply (min, L);
(%o2)                        - 10.2

Функция apply вычисляет свои аргументы даже если функция F не вычисляет их.

(%i1) F (x) := x / 1729;
                                   x
(%o1)                     F(x) := ----
                                  1729
(%i2) fname : F;
(%o2)                           F
(%i3) dispfun (F);
                                   x
(%t3)                     F(x) := ----
                                  1729

(%o3)                         [%t3]
(%i4) dispfun (fname);
fname is not the name of a user function.
 -- an error.  Quitting.  To debug this try debugmode(true);
(%i5) apply (dispfun, [fname]);
                                   x
(%t5)                     F(x) := ----
                                  1729

(%o5)                         [%t5]

Функция apply вычисляет имя функции F. Одиночная кавычка ' блокирует это вычисление. demoivre является именем глобальной переменной и, одновременно, именем функции.

(%i1) demoivre;
(%o1)                         false
(%i2) demoivre (exp (%i * x));
(%o2)                  %i sin(x) + cos(x)
(%i3) apply (demoivre, [exp (%i * x)]);
demoivre evaluates to false
Improper name or value in functional position.
 -- an error.  Quitting.  To debug this try debugmode(true);
(%i4) apply ('demoivre, [exp (%i * x)]);
(%o4)                  %i sin(x) + cos(x)
Функция: block ([v_1, ..., v_m], expr_1, ..., expr_n)
Функция: block (expr_1, ..., expr_n)

Функция block последовательно вычисляет expr_1, ..., expr_n и возвращает значение последнего вычисленного выражения. Последовательность вычисления может быть изменена при помощи функций go, throw и return. Последнее выражение expr_n вычисляется если не используется return или вычисляется выражение, содержащие throw. Некоторые переменные v_1, ..., v_m могут быть объявлены локальными в блоке, и они отличаются от глобальных переменных с теми же именами. Если не требуется определять локальные переменные, то список может быть опущен. Внутри блока, все другие переменные, отличные от v_1, ..., v_m, являются глобальными.

block сохраняет текущие значения переменных v_1, ..., v_m (если таковые существуют) при входе в блок, и затем удаляет их значения, так чтобы эти переменные вычислялись сами в себя. Локальные переменные могут принимать любые значения внутри блока, но пр выходе из него сохраненные значения восстанавливаются, а локальные в блоке значения теряются.

Блок может существовать внутри другого блока. Локальные переменные определяются всякий раз как вычисляется новый block. Локальные переменные объемлющего блока выглядят как глобальные для внутреннего блока. Если переменная не локальна в блоке, то ее значение равно последнему, присвоенному в объемлющем блоке, если таковое существует, и значению переменной в глобальном окружении в противном случае. Эта политика совпадает с обычным понятием "динамической области определения".

Если необходимо сохранять и восстанавливать другие локальные свойства, кроме value, такие как array (кроме полных массивов), function, dependencies, atvalue, matchdeclare, atomgrad, constant и nonscalar, то следует использовать функцию local внутри блока с именем функции в качестве параметра.

Значением блока является значение последнего выражения или значение аргумента функции return, которая может быть использована для явного выхода из блока. Функция go используется для передачи управления на команду блока, помеченную аргументом go. Для того, чтобы пометить команду нужно поместить перед ней метку в виде атома. Например: block ([x], x:1, loop, x: x+1, ..., go(loop), ...). Аргументом go должна быть метка, определенная в текущем блоке. Невозможно использовать go для передачи управления в блок отличный от того, в котором находится вызов go.

Блоки обычно применяются в правых частях определения функций, но могут быть использованы и в других местах.

Функция: break (expr_1, ..., expr_n)

Вычисляет и печатает выражения expr_1, ..., expr_n и затем вызывает прерывание Maxima с тем, чтобы пользователь мог исследовать и изменить окружение. Ввод exit; возобновляет вычисление.

Функция: catch (expr_1, ..., expr_n)

Вычисляет expr_1, ..., expr_n одно за другими и, если одно из них приводит к вычислению выражения throw (arg), то значением catch становится значение аргумента throw (arg), и дальнейшее вычисление не производится. Такой "нелокальный возврат" осуществляется из любого уровня вложенности до первого объемлющего catch. Если нет объемлющего catch, то throw вызывает ошибку.

Если вычисление аргументов не приводит к вычислению throw, то значение catch равно значению expr_n.

(%i1) lambda ([x], if x < 0 then throw(x) else f(x))$
(%i2) g(l) := catch (map (''%, l))$
(%i3) g ([1, 2, 3, 7]);
(%o3)               [f(1), f(2), f(3), f(7)]
(%i4) g ([1, 2, -3, 7]);
(%o4)                          - 3

Здесь, если список l содержит только неотрицательные числа, то функция g возвращает список функций f, примененных к элементам l, иначе, g "ловит" первое отрицательное число в l и "бросает" его вверх.

Функция: compfile (filename, f_1, ..., f_n)
Функция: compfile (filename, functions)
Функция: compfile (filename, all)

Транслирует функции Maxima в Lisp и записывает полученный код в файл filename.

Вызов compfile(filename, f_1, ..., f_n) транслирует только заданные функции. Вызов compfile(filename, functions) или вызов compfile(filename, all) транслирует все определенные пользователем функции.

Код Lisp не вычисляется, а результирующий файл не обрабатывается компилятором Lisp. Функция translate создает и вычисляет Lisp код. Функция compile_file транслирует код Maxima в Lisp, и затем выполняет компилятор Lisp.

См. также translate, translate_file и compile_file.

Функция: compile (f_1, ..., f_n)
Функция: compile (functions)
Функция: compile (all)

Транслирует определения Maxima функций f_1, ..., f_n в Lisp, вычисляет Lisp код и вызывает Lisp функцию COMPILE на каждую транслированную функцию. Функция compile возвращает список скомпилированных функций.

Вызов compile (all) или compile (functions) компилирует все определенные пользователем функции.

Функция compile не вычисляет свои аргументы. Оператор кавычка-кавычка '' может быть использован для их вычисления.

Функция: define (f(x_1, ..., x_n), expr)
Функция: define (f[x_1, ..., x_n], expr)
Функция: define (funmake (f, [x_1, ..., x_n]), expr)
Функция: define (arraymake (f, [x_1, ..., x_n]), expr)
Функция: define (ev (expr_1), expr_2)

Определяет функцию с именем f, аргументами x_1, ..., x_n и телом функции expr. Функция define всегда вычисляет свой второй аргумент (если вычисление не экранировано, т.е. блокировано явным образом). Функция, определенная данным образом, может быть обычной функцией Maxima (с аргументами в круглых скобках) или функцией-массивом (с аргументам в квадратных скобках).

Если последний аргумент x_n является одноэлементным списком, то функция, определенная define, принимает произвольное число аргументов. Фактические параметры присваиваются по одному формальным параметрам x_1, ..., x_(n - 1), а все последующие фактические параметры, если таковые есть, присваиваются x_n одним списком.

Если первый параметр define имеет форму f(x_1, ..., x_n) или f[x_1, ..., x_n], то аргументы функции вычисляются, а f нет, даже если уже есть функция или переменная с таким именем.

Если же первый параметр является выражением с оператором funmake, arraymake или ev, то первый аргумент вычисляется. Это позволяет вычислять как имя функции так и ее тело.

Все определяемые функции действуют в одном пространстве имен, т.е. если функция f определена внутри другой функции g, то действие f не ограничено функцией g.

Если некоторый формальный параметр x_k является экранированным символом (после вычисления), то функция, определенная define, не будет вычислять соответствующий фактический параметр. Все остальные фактические параметры вычисляются.

См. также := и ::=.

Примеры:

Функция define всегда вычисляет свой второй аргумент (если вычисление не блокировано явным образом).

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

Функция, определяемая define, может быть обычной функцией Maxima или функцией-массивом.

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

Если последний аргумент x_n является одноэлементным списком, то определенная define функция принимает произвольное число аргументов.

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

Если первый параметр является выражением с оператором funmake, arraymake или ev, то первый аргумент вычисляется.

(%i1) [F : I, u : x];
(%o1)                        [I, x]
(%i2) funmake (F, [u]);
(%o2)                         I(x)
(%i3) define (funmake (F, [u]), cos(u) + 1);
(%o3)                  I(x) := cos(x) + 1
(%i4) define (arraymake (F, [u]), cos(u) + 1);
(%o4)                   I  := cos(x) + 1
                         x
(%i5) define (foo (x, y), bar (y, x));
(%o5)                foo(x, y) := bar(y, x)
(%i6) define (ev (foo (x, y)), sin(x) - cos(y));
(%o6)             bar(y, x) := sin(x) - cos(y)
Функция: define_variable (name, default_value, mode)

Определяет глобальную переменную. define_variable полезна в пользовательских пакетах, которые часто транслируются или компилируются.

Функция define_variable выполняет следующие шаги:

  1. mode_declare (name, mode) декларирует тип переменной name для транслятора. См. mode_declare для списка возможных типов.
  2. Если переменная не имеет значения, то default_value устанавливается равным name.
  3. declare (name, special) объявляет переменную специальной.
  4. Ассоциирует имя name с тестовой функцией, чтобы обеспечить, что name будут присваиваться значения только объявленного типа.

Свойство value_check может быть установлено для любой переменной, определенной при помощи define_variable с типом отличным от any. Значение свойства value_check является лямбда-выражением или именем функции одной переменной. Эта функция вызывается всякий раз, как производится попытка присвоить значение данной переменной. Параметром функции value_check является предполагаемое новое значение переменной.

Функция define_variable вычисляет default_value и не вычисляет name и mode. Функция define_variable возвращает текущее значение name, что есть default_value если name не имела значения до декларации и значение name в противном случае.

Примеры:

foo – логическая переменная с начальным значением true.

(%i1) define_variable (foo, true, boolean);
(%o1)                         true
(%i2) foo;
(%o2)                         true
(%i3) foo: false;
(%o3)                         false
(%i4) foo: %pi;
Error: foo was declared mode boolean, has value: %pi
 -- an error.  Quitting.  To debug this try debugmode(true);
(%i5) foo;
(%o5)                         false

bar – целочисленная переменная, которая должна быть простым числом.

(%i1) define_variable (bar, 2, integer);
(%o1)                           2
(%i2) qput (bar, prime_test, value_check);
(%o2)                      prime_test
(%i3) prime_test (y) := if not primep(y) then
                           error (y, "is not prime.");
(%o3) prime_test(y) := if not primep(y)

                                   then error(y, "is not prime.")
(%i4) bar: 1439;
(%o4)                         1439
(%i5) bar: 1440;
1440 is not prime.
#0: prime_test(y=1440)
 -- an error.  Quitting.  To debug this try debugmode(true);
(%i6) bar;
(%o6)                         1439

baz_quux – переменная, которой нельзя присвоить значение. Тип any_check аналогичен any, но позволяет применять механизм value_check, в то время как тип any этого не позволяет.

(%i1) define_variable (baz_quux, 'baz_quux, any_check);
(%o1)                       baz_quux
(%i2) F: lambda ([y], if y # 'baz_quux then
                 error ("Cannot assign to `baz_quux'."));
(%o2) lambda([y], if y # 'baz_quux

                        then error(Cannot assign to `baz_quux'.))
(%i3) qput (baz_quux, ''F, value_check);
(%o3) lambda([y], if y # 'baz_quux

                        then error(Cannot assign to `baz_quux'.))
(%i4) baz_quux: 'baz_quux;
(%o4)                       baz_quux
(%i5) baz_quux: sqrt(2);
Cannot assign to `baz_quux'.
#0: lambda([y],if y # 'baz_quux then
                 error("Cannot assign to `baz_quux'."))(y=sqrt(2))
 -- an error.  Quitting.  To debug this try debugmode(true);
(%i6) baz_quux;
(%o6)                       baz_quux
Функция: dispfun (f_1, ..., f_n)
Функция: dispfun (all)

Выводит определения пользовательских функций f_1, ..., f_n. Каждый аргумент должен быть именем: макроса (определенного при помощи ::=), обычной функции (определенной := или define), функции-массива (определенной := или define, но с аргументами в квадратных скобках [ ]), функцией с индексом (определенной := или define, но с частью аргументов в квадратных скобках а с другими в круглых ( )), одним из элементов функции с индексом с определенным значением индекса, или функцией с постоянным индексом.

Вызов dispfun (all) выводит все пользовательские функции, которые определяются списками functions, arrays и macros, кроме функций с постоянным индексом.

Функция dispfun создает метки промежуточных выражений (%t1, %t2 и т.д.) для каждой выводимой функции и присваивает определения функций этим меткам. В отличии от этого, fundef возвращает определение функции.

Функция dispfun не вычисляет свои аргументы. Оператор кавычка-кавычка '' может быть использован для их вычисления. Функция dispfun возвращает список меток промежуточных выражений, соответствующих выведенным функциям.

Примеры:

(%i1) m(x, y) ::= x^(-y);
                                     - y
(%o1)                   m(x, y) ::= x
(%i2) f(x, y) :=  x^(-y);
                                     - y
(%o2)                    f(x, y) := x
(%i3) g[x, y] :=  x^(-y);
                                    - y
(%o3)                     g     := x
                           x, y
(%i4) h[x](y) :=  x^(-y);
                                    - y
(%o4)                     h (y) := x
                           x
(%i5) i[8](y) :=  8^(-y);
                                    - y
(%o5)                     i (y) := 8
                           8
(%i6) dispfun (m, f, g, h, h[5], h[10], i[8]);
                                     - y
(%t6)                   m(x, y) ::= x

                                     - y
(%t7)                    f(x, y) := x

                                    - y
(%t8)                     g     := x
                           x, y

                                    - y
(%t9)                     h (y) := x
                           x

                                    1
(%t10)                     h (y) := --
                            5        y
                                    5

                                     1
(%t11)                    h  (y) := ---
                           10         y
                                    10

                                    - y
(%t12)                    i (y) := 8
                           8

(%o12)       [%t6, %t7, %t8, %t9, %t10, %t11, %t12]
(%i12) ''%;
                     - y              - y            - y
(%o12) [m(x, y) ::= x   , f(x, y) := x   , g     := x   , 
                                            x, y
                  - y           1              1             - y
        h (y) := x   , h (y) := --, h  (y) := ---, i (y) := 8   ]
         x              5        y   10         y   8
                                5             10
Системная переменная: functions

Значение по умолчанию: []

Переменная functions есть список всех обычных функций Maxima в текущей сессии. Обычные функции – это функции, определенные при помощи define или :=, и вызываемые с аргументами в круглых скобках (). Функция может быть определена в командной строке Maxima или в файле, загруженном при помощи load или batch.

Функции-массивы (вызываемые с квадратными скобками, т.е. F[x]) и функции с индексом (вызываемые с круглыми и квадратными скобками, т.е. F[x](y)) перечислены в глобальной переменной arrays, а не в functions.

Lisp функции не включаются в список.

Примеры:

(%i1) F_1 (x) := x - 100;
(%o1)                   F_1(x) := x - 100
(%i2) F_2 (x, y) := x / y;
                                      x
(%o2)                    F_2(x, y) := -
                                      y
(%i3) define (F_3 (x), sqrt (x));
(%o3)                   F_3(x) := sqrt(x)
(%i4) G_1 [x] := x - 100;
(%o4)                    G_1  := x - 100
                            x
(%i5) G_2 [x, y] := x / y;
                                     x
(%o5)                     G_2     := -
                             x, y    y
(%i6) define (G_3 [x], sqrt (x));
(%o6)                    G_3  := sqrt(x)
                            x
(%i7) H_1 [x] (y) := x^y;
                                      y
(%o7)                     H_1 (y) := x
                             x
(%i8) functions;
(%o8)              [F_1(x), F_2(x, y), F_3(x)]
(%i9) arrays;
(%o9)                 [G_1, G_2, G_3, H_1]
Функция: fundef (f)

Возвращает определение функции f.

Аргумент должен быть именем: макроса (определенного при помощи ::=), обычной функции (определенной := или define), функции-массива (определенной := или define, но с аргументами в квадратных скобках [ ]), функцией с индексом (определенной := или define, но с частью аргументов в квадратных скобках а с другими в круглых ( )), одним из элементов функции с индексом с определенным значением индекса, или функцией с постоянным индексом.

Функция fundef не вычисляет свои аргументы. Оператор кавычка-кавычка '' может быть использован для их вычисления.

Вызов fundef (f) возвращает определение функции f. В отличии от этого, dispfun (f) присваивает определения функций меткам промежуточных выражений.

Функция: funmake (F, [arg_1, ..., arg_n])

Возвращает выражение F(arg_1, ..., arg_n). Это выражение упрощается но не вычисляется, т.е. функция F не вызывается, даже если она определена.

Функция funmake не различает обычные функции и функции-массивы. Если F есть имя функции-массива, то funmake все равно возвращает F(...) (т.е вызов функции с круглыми а не с квадратными скобками). Для функций-массивом следует использовать arraymake.

Функция funmake вычисляет свои аргументы.

Примеры:

Функция funmake, примененная к обычной Maxima функции.

(%i1) F (x, y) := y^2 - x^2;
                                   2    2
(%o1)                  F(x, y) := y  - x
(%i2) funmake (F, [a + 1, b + 1]);
(%o2)                    F(a + 1, b + 1)
(%i3) ''%;
                              2          2
(%o3)                  (b + 1)  - (a + 1)

Функция funmake, примененная к макросу.

(%i1) G (x) ::= (x - 1)/2;
                                  x - 1
(%o1)                    G(x) ::= -----
                                    2
(%i2) funmake (G, [u]);
(%o2)                         G(u)
(%i3) ''%;
                              u - 1
(%o3)                         -----
                                2

Функция funmake, примененная к функции с индексом.

(%i1) H [a] (x) := (x - 1)^a;
                                        a
(%o1)                   H (x) := (x - 1)
                         a
(%i2) funmake (H [n], [%e]);
                                       n
(%o2)               lambda([x], (x - 1) )(%e)
(%i3) ''%;
                                    n
(%o3)                       (%e - 1)
(%i4) funmake ('(H [n]), [%e]);
(%o4)                        H (%e)
                              n
(%i5) ''%;
                                    n
(%o5)                       (%e - 1)

Функция funmake, примененная к символу, не являющемуся функцией какого-либо типа.

(%i1) funmake (A, [u]);
(%o1)                         A(u)
(%i2) ''%;
(%o2)                         A(u)

Функция funmake вычисляет аргументы, но не результат.

(%i1) det(a,b,c) := b^2 -4*a*c;
                                    2
(%o1)              det(a, b, c) := b  - 4 a c
(%i2) (x : 8, y : 10, z : 12);
(%o2)                          12
(%i3) f : det;
(%o3)                          det
(%i4) funmake (f, [x, y, z]);
(%o4)                    det(8, 10, 12)
(%i5) ''%;
(%o5)                         - 284

Maxima упрощает возвращаемое funmake значение.

(%i1) funmake (sin, [%pi / 2]);
(%o1)                           1
Функция: lambda ([x_1, ..., x_m], expr_1, ..., expr_n)
Функция: lambda ([[L]], expr_1, ..., expr_n)
Функция: lambda ([x_1, ..., x_m, [L]], expr_1, ..., expr_n)

Определяет и возвращает лямбда-выражение (т.е. функцию без имени). Функция может иметь обязательные параметры x_1, ..., x_m и/или необязательные параметры L, представляемые в форме списка. Значение, возвращаемое функцией, равно expr_n. Лямбда-выражение может быть присвоено переменной и вычислено, как обычная функция. Лямбда-выражение может использоваться в тех же контекстах, где ожидается имя функции.

При вычислении функции, создаются неинициализированные локальные переменные x_1, ..., x_m. lambda может использоваться внутри block или другого lambda, и локальные переменные создаются каждый раз, как вычисляется новый блок block или lambda. Локальные переменные выглядят как глобальные для каждого внутреннего блока block или lambda. Если переменная не является локальной, то ее значение равно последнему, присвоенному в объемлющем блоке block или lambda, если таковое существует, и значению переменной в глобальном окружении в противном случае. Эта политика совпадает с обычным понятием "динамической области определения".

После определения локальных переменных, выражения с expr_1 по expr_n последовательно вычисляются. Специальная переменная %% обозначает значение предыдущего выражения. Среди выражение могут применяться throw и catch.

Команда возврата return не может использоваться в лямбда-выражении если только она не заключена в блоке block. В этом случае return определяет значение блока а не лямбда-выражения в целом, за исключением случая, когда блок является последним выражением expr_n. Аналогично, go не может использоваться в лямбда-выражении без объемлющего блока block.

Функция lambda не вычисляет свои параметры. Оператор кавычка-кавычка '' может быть использован для их вычисления.

Примеры:

(%i1) f: lambda ([x], x^2);
                                      2
(%o1)                    lambda([x], x )
(%i2) f(a);
                                2
(%o2)                          a
(%i3) lambda ([x], x^2) (a);
                                2
(%o3)                          a
(%i4) apply (lambda ([x], x^2), [a]);
                                2
(%o4)                          a
(%i5) map (lambda ([x], x^2), [a, b, c, d, e]);
                        2   2   2   2   2
(%o5)                 [a , b , c , d , e ]
(%i6) a: %pi$
(%i7) b: %e$
(%i8) g: lambda ([a], a*b);
(%o8)                   lambda([a], a b)
(%i9) b: %gamma$
(%i10) g(1/2);
                             %gamma
(%o10)                       ------
                               2
(%i11) g2: lambda ([a], a*''b);
(%o11)                lambda([a], a %gamma)
(%i12) b: %e$
(%i13) g2(1/2);
                             %gamma
(%o13)                       ------
                               2
(%i14) h: lambda ([a, b], h2: lambda ([a], a*b), h2(1/2));
                                                   1
(%o14)    lambda([a, b], h2 : lambda([a], a b), h2(-))
                                                   2
(%i15) h(%pi, %gamma);
                             %gamma
(%o15)                       ------
                               2
(%i16) i: lambda ([a], lambda ([x], a*x));
(%o16)            lambda([a], lambda([x], a x))
(%i17) i(1/2);
(%o17)                  lambda([x], a x)
(%i18) i2: lambda([a], buildq([a: a], lambda([x], a*x)));
(%o18)    lambda([a], buildq([a : a], lambda([x], a x)))
(%i19) i2(1/2);
                                     x
(%o19)                   lambda([x], -)
                                     2
(%i20) i2(1/2)(%pi);
                               %pi
(%o20)                         ---
                                2
(%i1) f : lambda ([aa, bb, [cc]], aa * cc + bb);
(%o1)          lambda([aa, bb, [cc]], aa cc + bb)
(%i2) f (foo, %i, 17, 29, 256);
(%o2)       [17 foo + %i, 29 foo + %i, 256 foo + %i]
(%i3) g : lambda ([[aa]], apply ("+", aa));
(%o3)             lambda([[aa]], apply(+, aa))
(%i4) g (17, 29, x, y, z, %e);
(%o4)                  z + y + x + %e + 46
Функция: local (v_1, ..., v_n)

Объявляет переменные v_1, ..., v_n локальными по отношению ко всем свойствам в выражении, где используется local.

Функция local не вычисляет свои аргументы. Функция local возвращает done.

Функция local может использоваться только внутри блока block, в теле функции или лямбда-выражении lambda, в функции ev, и только один раз в каждом случае.

local независима от context.

Управляющая переменная: macroexpansion

Значение по умолчанию: false

Переменная macroexpansion управляет тем, подставляется ли макро-расширение (т.е. возвращаемое значением) вместо вызова макро-функции. Подстановка может ускорить последующие вычисления но за счет увеличения памяти для хранения выражений.

false

Макро-расширение не подставляется вместо вызова макро-функции.

expand

При первом вызове макро-функции, макро-расширение сохраняется. Для последующих вызовов, макро-расширение не перевычисляется. Побочные эффекты (такие как print или присваивание глобальных переменных) осуществляются только при первом вычислении макро-функции. Макро-расширение в выражении не влияет на другие выражения, имеющие такой же вызов макро-функции.

displace

При первом вызове макро-функции, макро-расширение подставляется вместо вызова, изменяя выражение, из которого макро-функция вызывается. Для последующих вызовов, макро-расширение не перевычисляется. Побочные эффекты осуществляются только при первом вычислении макро-функции. Макро-расширение в выражении не влияет на другие выражения, имеющие такой же вызов макро-функции.

Примеры:

Если macroexpansion равна false, то макро-функция вызывается всякий раз, как вычисляется вызывающее выражение, и вызывающее выражение не изменяется.

(%i1) f (x) := h (x) / g (x);
                                  h(x)
(%o1)                     f(x) := ----
                                  g(x)
(%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                       return (x + 99));
(%o2) g(x) ::= block(print("x + 99 is equal to", x), 
                                                  return(x + 99))
(%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                       return (x - 99));
(%o3) h(x) ::= block(print("x - 99 is equal to", x), 
                                                  return(x - 99))
(%i4) macroexpansion: false;
(%o4)                         false
(%i5) f (a * b);
x - 99 is equal to x 
x + 99 is equal to x 
                            a b - 99
(%o5)                       --------
                            a b + 99
(%i6) dispfun (f);
                                  h(x)
(%t6)                     f(x) := ----
                                  g(x)

(%o6)                         done
(%i7) f (a * b);
x - 99 is equal to x 
x + 99 is equal to x 
                            a b - 99
(%o7)                       --------
                            a b + 99

Если macroexpansion равна expand, то макро-функция вызывается один раз, и взывающее выражение не изменяется.

(%i1) f (x) := h (x) / g (x);
                                  h(x)
(%o1)                     f(x) := ----
                                  g(x)
(%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                       return (x + 99));
(%o2) g(x) ::= block(print("x + 99 is equal to", x), 
                                                  return(x + 99))
(%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                       return (x - 99));
(%o3) h(x) ::= block(print("x - 99 is equal to", x), 
                                                  return(x - 99))
(%i4) macroexpansion: expand;
(%o4)                        expand
(%i5) f (a * b);
x - 99 is equal to x 
x + 99 is equal to x 
                            a b - 99
(%o5)                       --------
                            a b + 99
(%i6) dispfun (f);
                                  h(x)
(%t6)                     f(x) := ----
                                  g(x)

(%o6)                         done
(%i7) f (a * b);
                            a b - 99
(%o7)                       --------
                            a b + 99

Если macroexpansion равна expand, то макро-функция вызывается один раз, и взывающее выражение изменяется.

(%i1) f (x) := h (x) / g (x);
                                  h(x)
(%o1)                     f(x) := ----
                                  g(x)
(%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                       return (x + 99));
(%o2) g(x) ::= block(print("x + 99 is equal to", x), 
                                                  return(x + 99))
(%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                       return (x - 99));
(%o3) h(x) ::= block(print("x - 99 is equal to", x), 
                                                  return(x - 99))
(%i4) macroexpansion: displace;
(%o4)                       displace
(%i5) f (a * b);
x - 99 is equal to x 
x + 99 is equal to x 
                            a b - 99
(%o5)                       --------
                            a b + 99
(%i6) dispfun (f);
                                 x - 99
(%t6)                    f(x) := ------
                                 x + 99

(%o6)                         done
(%i7) f (a * b);
                            a b - 99
(%o7)                       --------
                            a b + 99
Управляющая переменная: mode_checkp

Значение по умолчанию: true

Если mode_checkp равна true, то mode_declare проверяет типы переменных, имеющих значение до вызова mode_declare.

Управляющая переменная: mode_check_errorp

Значение по умолчанию: false

Если mode_check_errorp равна true, то mode_declare вызывает ошибку.

Управляющая переменная: mode_check_warnp

Значение по умолчанию: true

Если mode_check_warnp равна true, то выводятся предупреждения о ошибках типизации.

Функция: mode_declare (y_1, mode_1, ..., y_n, mode_n)

Функция mode_declare используется для определения типов переменных или функций для последующей трансляции и компиляции. Вызов mode_declare обычно располагается в начале определения функции, в начале Maxima-программы или выполняется интерактивно в командной строке.

Параметры mode_declare являются парами, состоящими из переменной и ее типа, который может быть boolean, fixnum, number, rational или float. Вместо переменной можно использовать список переменных, которые все будут объявлены однотипными.

Если переменная является массивом, и каждый элемент этого массива, на который будут ссылаться, имеет значение, то для первой декларации границ массива следует использовать array (yi, complete, dim1, dim2, ...) а не

array(yi, dim1, dim2, ...)

Если все элементы массива имеют тип fixnum (float), то следует использовать fixnum (float) вместо complete. Кроме того, если все элементы массива имеют один тип, скажем m, то для эффективной трансляции следует использовать

mode_declare (completearray (yi), m))

Численный код с использованием массивов может работать быстрее при объявлении ожидаемого размера массива, как сделано в

mode_declare (completearray (a [10, 10]), float)

для массива с плавающей точкой размера 10 x 10.

Можно определить тип результата функции при помощи function (f_1, f_2, ...), где f_1, f_2, ... есть имена функций. Например, выражение

mode_declare ([function (f_1, f_2, ...)], fixnum)

объявляет значения, возвращаемые функциями f_1, f_2, ..., целыми числами длиной одно слово.

Функция modedeclare является синонимом mode_declare.

Функция: mode_identity (arg_1, arg_2)

Специальная форма, используемая вместе с mode_declare и macros для объявления, например, списка списков чисел с плавающей точкой или других подобных составных объектов. Первый аргумент mode_identity есть имя типа, как в mode_declare (т.е. одно из float, fixnum, number, list или any), а второй аргумент есть выражение, которое вычисляется и возвращается как значение mode_identity. Если возвращаемое значение недопустимо для декларации типа, указанного в первом аргументе, то случается ошибка или печатается предупреждение. Важно то, что тип выражения для транслятора Maxima в Lisp будет всегда определяться первым аргументом, вне зависимости от того, что происходит со вторым. Например, x: 3.3; mode_identity (fixnum, x); дает ошибку а mode_identity (flonum, x) возвращает 3.3. С этим связан ряд проблем, например, если известно, что first (l) возвращает число, то можно написать mode_identity (number, first (l)). Но более эффективно будет определить новый примитив

firstnumb (x) ::= buildq ([x], mode_identity (number, first(x)));

и использовать firstnumb всякий раз при обращении к первому элементу списка чисел.

Управляющая переменная: transcompile

Значение по умолчанию: true

Если transcompile равно true, то translate и translate_file создают декларации, которые делают транслируемый код более удобным для компиляции.

Функция compfile устанавливает transcompile: true на время своей работы.

Функция: translate (f_1, ..., f_n)
Функция: translate (functions)
Функция: translate (all)

Транслирует определенные пользователем функции f_1, ..., f_n из языка Maxima в Lisp и вычисляет результат трансляции. Обычно, транслированные функции работают быстрее оригиналов.

Вызов translate (all) или translate (functions) транслирует все определенные пользователем функции.

Транслируемые функции должны, где это возможно, содержать в начале кода вызовы mode_declare, для генерации более эффективного кода.

Например:

f (x_1, x_2, ...) := block ([v_1, v_2, ...],
    mode_declare (v_1, mode_1, v_2, mode_2, ...), ...)

где x_1, x_2, ... – параметры функции, а v_1, v_2, ... – локальные переменные.

Имена транслированных функций удаляются из списка functions если значение savedef равно false (см. ниже) и добавляются к списку props.

Не следует транслировать недостаточно отлаженные функции.

При трансляции, выражения предполагаются уже упрощенными. Если это не так, то будет сгенерирован правильный но неоптимальный код. Таким образом, не следует устанавливать переключатель simp равным false, что подавляет упрощение транслируемых выражений.

Если переключатель translate равен true, то все определяемые пользователем функции автоматически транслируются в Lisp.

Отметим, что транслируемые функции могут работать не совсем так, как до трансляции, т.к. существуют некоторые несовместимости между Lisp и Maxima версиями функции. Главным образом, функция rat, имеющая более одного параметра, и функция ratvars не должны использоваться, если некоторые переменные объявлены mode_declare каноническими рациональными выражениями (КРВ). Кроме того, prederror: false не транслируется.

Если savedef равна true, то Maxima версия сохраняется при трансляции. Это позволяет выводить определение функции при помощи dispfun и редактировать его.

Если transrun равна false, то интерпретируемые варианты будут выполняться (если они еще доступны) вместо транслированных для всех вызовов функций.

Функция translate возвращает список транслированных функций.

Функция: translate_file (maxima_filename)
Функция: translate_file (maxima_filename, lisp_filename)

Транслирует файл кода Maxima в файлд кода Lisp. Функция translate_file возвращает список трех имен файлов: имя файла Maxima, имя файла Lisp и имя файла, содержащего дополнительную информацию о трансляции. Функция translate_file вычисляет свои аргументы.

Команды translate_file ("foo.mac"); load("foo.LISP") дают тот же результат, что и batch ("foo.mac") за исключением некоторых ограничений, например, на использование '' и %.

Вызов translate_file (maxima_filename) транслирует файл Maxima maxima_filename в Lisp файл с аналогичным именем. Например, foo.mac транслируется в foo.LISP. Имя файла Maxima может включать имена директорий, и результирующий Lisp файл будет записан в ту же директорию, где располагается исходный файл Maxima.

Вызов translate_file (maxima_filename, lisp_filename) транслирует файл Maxima maxima_filename в Lisp файл lisp_filename. translate_file игнорирует расширение имени файла для lisp_filename, если таковое задано. Расширение Lisp файла всегда будет LISP. Имя Lisp файла может содержать имена директорий, и в этом случае файл будет записан в заданную директорию.

translate_file также записывает файл предупреждений транслятора, разной степени важности. Расширение имени этого файла – UNLISP. Этот файл может содержать ценную информацию, возможно туманную, для обнаружения ошибок в транслированном коде. Файл UNLISP всегда записывается в ту же директорию, где расположен исходный файл Maxima.

translate_file генерирует код, в котором некоторые декларации и определения вступают в силу сразу в процессе компиляции Lisp кода. См. также compile_file по этому поводу.

См. также tr_array_as_ref, tr_bound_function_applyp, tr_exponent, tr_file_tty_messagesp, tr_float_can_branch_complex, tr_function_call_default, tr_numer, tr_optimize_max_loop, tr_semicompile, tr_state_vars, tr_warnings_get, tr_warn_bad_function_calls, tr_warn_fexpr, tr_warn_meval, tr_warn_mode, tr_warn_undeclared, tr_warn_undefined_variable и tr_windy.

Управляющая переменная: transrun

Значение по умолчанию: true

Если transrun равна false, то для всех функций интерпретируемые варианты будут выполняться (если они еще доступны) вместо транслированных.

Управляющая переменная: tr_array_as_ref

Значение по умолчанию: true

Если translate_fast_arrays равна false, то ссылки на массивы в Lisp коде, созданном translate_file, зависят от tr_array_as_ref. Если tr_array_as_ref равна true, то имена массивов вычисляются, иначе они рассматриваются в транслированном коде как буквальные символы.

tr_array_as_ref не действует если translate_fast_arrays равна true.

Управляющая переменная: tr_bound_function_applyp

Значение по умолчанию: true

Если tr_bound_function_applyp равна true, то Maxima выдает предупреждение, если имеющая значение переменная (такая, как аргумент функции) используется как имя функции.

Например, выражение g (f, x) := f (x+1) вызовет предупреждение.

Управляющая переменная: tr_file_tty_messagesp

Значение по умолчанию: false

Если tr_file_tty_messagesp равна true, то сообщения, генерируемые translate_file в процессе трансляции, отображаются на консоли и выводятся в UNLISP файл. Если false, то сообщения выводятся только в UNLISP файл.

Управляющая переменная: tr_float_can_branch_complex

Значение по умолчанию: true

Сообщает Maxima-Lisp транслятору, что функции acos, asin, asec и acsc могут возвращать комплексные значения.

Эффект tr_float_can_branch_complex заключается в следующем. Хотя, явного влияния на результат трансляции нет, но если этот флаг равен true, то acos(x) имеет тип any, даже если x имеет тип float (как определено mode_declare). Если ли же он равен false, то acos(x) имеет тип float тогда и тоько тогда, когда x имеет тип float.

Управляющая переменная: tr_function_call_default

Значение по умолчанию: general

Если равна false, то следует вызывать meval; если expr, то предполагать Lisp функцию с фиксированными аргументами; если general, то генерируется код, подходящий для mexprs и mlexprs но не macros. general обеспечивает правильное связывание переменных в компилируемом коде. В режиме general, при трансляции F(X), если F является связанной переменной, то предполагается apply (f, [x]), и в таком виде транслируется с печатью соответствующего предупреждения. Нет необходимости выключать этот механизм. С установками по умолчанию, отсутствие предупреждений не означает полную совместимость транслированного и интерпретируемого кода.

Управляющая переменная: tr_numer

Значение по умолчанию: false

Если tr_numer равна true, то для атомов, имеющих свойство numer, например, %pi, это свойство принимается во внимание транслятором.

Управляющая переменная: tr_optimize_max_loop

Значение по умолчанию: 100

tr_optimize_max_loop есть максимальное число раз, которое цикл макро-расширения и оптимизации транслятора будет повторен при трансляции формы. Данный предел установлен для обнаружения ошибок макро-расширения и зацикливания оптимизатора.

Управляющая переменная: tr_semicompile

Значение по умолчанию: false

Если tr_semicompile равна true, то translate_file и compfile генерируют формы, которые будут макро-расширены но не скомпилированы в машинный код Lisp компилятором.

Системная переменная: tr_state_vars

Значение по умолчанию:

[transcompile, tr_semicompile, tr_warn_undeclared, tr_warn_meval,
tr_warn_fexpr, tr_warn_mode, tr_warn_undefined_variable,
tr_function_call_default, tr_array_as_ref,tr_numer]

Список переключателей, которые влияют на форму транслированного кода. Эта информация полезна для отладки транслятора. Сравнивая результат трансляции с ожидаемым для данного состояния результатом, можно обнаружить ошибки транслятора.

Функция: tr_warnings_get ()

Печатает список предупреждений, сгенерированных транслятором в процессе текущей трансляции.

Управляющая переменная: tr_warn_bad_function_calls

Значение по умолчанию: true

– выдает предупреждение в случае вызова функции, который может быть неверным из-за неправильных деклараций, сделанных во время трансляции.

Управляющая переменная: tr_warn_fexpr

Значение по умолчанию: compfile

– выдает предупреждение если встречается FEXPR. Обычно, FEXPR не должны присутствовать в транслированном коде.

Управляющая переменная: tr_warn_meval

Значение по умолчанию: compfile

– выдает предупреждение при вызове функции meval. Вызов meval означает проблему в транслированном коде.

Управляющая переменная: tr_warn_mode

Значение по умолчанию: all

– выдает предупреждение, когда переменной присваивается значение, несовместимое с ее типом.

Управляющая переменная: tr_warn_undeclared

Значение по умолчанию: compile

– управляет тем, когда печатать сообщения о необъявленных переменных.

Управляющая переменная: tr_warn_undefined_variable

Значение по умолчанию: all

– печатает предупреждение, когда встречается необъявленная переменная.

Управляющая переменная: tr_windy

Значение по умолчанию: true

– вызывает печать полезных комментариев и советов по программированию.

Функция: compile_file (filename)
Функция: compile_file (filename, compiled_filename)
Функция: compile_file (filename, compiled_filename, lisp_filename)

Транслирует файл Maxima filename в Lisp, выполняет компилятор Lisp и, если трансляция и компиляция успешны, то загружает скомпилированный код в Maxima.

compile_file возвращает список имен четырех файлов: изначального файла кода Maxima, транслированного Lisp файла, файла замечаний по трансляции и файла скомпилированного кода. Если компиляция неуспешна, то последний элемент равен false.

Некоторые декларации и определения активизируются сразу в процессе компиляции Lisp кода (без загрузки скомпилированного кода). Сюда относятся функции, определенные при помощи оператора :=, макросы, определенные при помощи ::=, alias, declare, define_variable, mode_declare и infix, matchfix, nofix, postfix, prefix а также compfile.

Присваивания и вызовы функций не вычисляются до загрузки скомпилированного файла. В частности, присваивания флагам трансляции (tr_numer и т.п.) внутри Maxima файла не оказывают влияния на результат трансляции.

Файл filename не может содержать специальные :lisp команды.

Функция compile_file вычисляет свои аргументы.

Функция: declare_translated (f_1, f_2, ...)

При трансляции кода Maxima в код Lisp, транслятору важно знать, какие функции следует вызывать как транслированные или компилированные, а какие как обычные Maxima функции или неопределенные. Данная декларация, помещенная в начале транслируемого файла, дает транслятору информацию, что хотя f_n и не имеет свойство Lisp функции во время трансляции, но будет иметь таковое в момент вызова. Если транслятор не знает, что fn будет Lisp функцией, то генерируется код (MFUNCTION-CALL fn arg1 arg2 ...).


Previous: Макросы, Up: Определение функций   [Contents][Index]