Previous: Макросы, Up: Определение функций [Contents][Index]
Составляет и вычисляет выражение 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
последовательно вычисляет 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
.
Блоки обычно применяются в правых частях определения функций, но могут быть использованы и в других местах.
Вычисляет и печатает выражения expr_1, ..., expr_n и затем
вызывает прерывание Maxima с тем, чтобы пользователь мог исследовать и изменить
окружение. Ввод exit;
возобновляет вычисление.
Вычисляет 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
и "бросает" его вверх.
Транслирует функции 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
.
Транслирует определения Maxima функций f_1, ..., f_n в Lisp, вычисляет Lisp код и
вызывает Lisp функцию COMPILE
на каждую транслированную функцию.
Функция compile
возвращает список скомпилированных функций.
Вызов compile (all)
или compile (functions)
компилирует все определенные
пользователем функции.
Функция compile
не вычисляет свои аргументы.
Оператор кавычка-кавычка ''
может быть использован
для их вычисления.
Определяет функцию с именем 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
полезна в пользовательских пакетах, которые часто
транслируются или компилируются.
Функция define_variable
выполняет следующие шаги:
mode_declare (name, mode)
декларирует тип переменной name для транслятора.
См. mode_declare
для списка возможных типов.
declare (name, special)
объявляет переменную специальной.
Свойство 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
Выводит определения пользовательских функций 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
есть список всех обычных функций 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]
Возвращает определение функции f.
Аргумент должен быть именем: макроса (определенного при помощи ::=
),
обычной функции (определенной :=
или define
),
функции-массива (определенной :=
или define
,
но с аргументами в квадратных скобках [ ]
),
функцией с индексом (определенной :=
или define
,
но с частью аргументов в квадратных скобках а с другими в круглых ( )
),
одним из элементов функции с индексом с определенным значением индекса,
или функцией с постоянным индексом.
Функция fundef
не вычисляет свои аргументы.
Оператор кавычка-кавычка ''
может быть использован для их вычисления.
Вызов fundef (f)
возвращает определение функции f.
В отличии от этого, dispfun (f)
присваивает определения функций
меткам промежуточных выражений.
Возвращает выражение 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
Определяет и возвращает лямбда-выражение (т.е. функцию без имени). Функция может иметь обязательные параметры 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
lambda
не вычисляет аргументы, нижеприведенное лямбда-выражение i
не определяет функцию "умножить на a
".
Такая функция может быть определена с помощью buildq
, как сделано в лямбда-выражении i2
.
(%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
[L]
в качестве единственного или последнего параметра.
Фактические параметры представлены внутри функции в виде списка.
(%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
Объявляет переменные v_1, ..., v_n локальными по отношению ко всем
свойствам в выражении, где используется local
.
Функция local
не вычисляет свои аргументы.
Функция local
возвращает done
.
Функция local
может использоваться только внутри блока block
, в теле функции или
лямбда-выражении lambda
, в функции ev
, и только один раз в каждом случае.
local
независима от context
.
Значение по умолчанию: 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
Значение по умолчанию: true
Если mode_checkp
равна true
, то mode_declare
проверяет
типы переменных, имеющих значение до вызова mode_declare
.
Значение по умолчанию: false
Если mode_check_errorp
равна true
, то mode_declare
вызывает ошибку.
Значение по умолчанию: true
Если mode_check_warnp
равна true
, то выводятся
предупреждения о ошибках типизации.
Функция 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_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
всякий раз при обращении
к первому элементу списка чисел.
Значение по умолчанию: true
Если transcompile
равно true
, то translate
и translate_file
создают декларации, которые делают транслируемый код более удобным для компиляции.
Функция compfile
устанавливает transcompile: true
на время своей работы.
Транслирует определенные пользователем функции 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
возвращает список транслированных функций.
Транслирует файл кода 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
.
Значение по умолчанию: true
Если transrun
равна false
, то для всех функций интерпретируемые
варианты будут выполняться (если они еще доступны) вместо транслированных.
Значение по умолчанию: 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
.
Значение по умолчанию: true
Если tr_bound_function_applyp
равна true
, то Maxima выдает предупреждение,
если имеющая значение переменная (такая, как аргумент функции) используется как
имя функции.
Например, выражение g (f, x) := f (x+1)
вызовет предупреждение.
Значение по умолчанию: false
Если tr_file_tty_messagesp
равна true
, то сообщения,
генерируемые translate_file
в процессе трансляции, отображаются на консоли
и выводятся в UNLISP файл.
Если false
, то сообщения выводятся только в UNLISP файл.
Значение по умолчанию: 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
.
Значение по умолчанию: general
Если равна false
, то следует вызывать meval
;
если expr
, то предполагать Lisp функцию с фиксированными аргументами; если general
,
то генерируется код, подходящий для mexprs
и mlexprs
но не macros
.
general
обеспечивает правильное связывание переменных в компилируемом коде.
В режиме general
, при трансляции F(X), если F является связанной переменной, то
предполагается apply (f, [x])
, и в таком виде транслируется с печатью соответствующего
предупреждения. Нет необходимости выключать этот механизм. С установками по умолчанию,
отсутствие предупреждений не означает полную совместимость транслированного и
интерпретируемого кода.
Значение по умолчанию: false
Если tr_numer
равна true
, то для атомов, имеющих свойство numer
,
например, %pi
, это свойство принимается во внимание транслятором.
Значение по умолчанию: 100
tr_optimize_max_loop
есть максимальное число раз, которое
цикл макро-расширения и оптимизации транслятора будет повторен
при трансляции формы. Данный предел установлен для обнаружения
ошибок макро-расширения и зацикливания оптимизатора.
Значение по умолчанию: false
Если tr_semicompile
равна true
, то translate_file
и compfile
генерируют формы, которые будут макро-расширены но не скомпилированы в машинный код
Lisp компилятором.
Значение по умолчанию:
[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]
Список переключателей, которые влияют на форму транслированного кода. Эта информация полезна для отладки транслятора. Сравнивая результат трансляции с ожидаемым для данного состояния результатом, можно обнаружить ошибки транслятора.
Печатает список предупреждений, сгенерированных транслятором в процессе текущей трансляции.
Значение по умолчанию: true
– выдает предупреждение в случае вызова функции, который может быть неверным из-за неправильных деклараций, сделанных во время трансляции.
Значение по умолчанию: compfile
– выдает предупреждение если встречается FEXPR. Обычно, FEXPR не должны присутствовать в транслированном коде.
Значение по умолчанию: compfile
– выдает предупреждение при вызове функции meval
. Вызов meval
означает проблему
в транслированном коде.
Значение по умолчанию: all
– выдает предупреждение, когда переменной присваивается значение, несовместимое с ее типом.
Значение по умолчанию: compile
– управляет тем, когда печатать сообщения о необъявленных переменных.
Значение по умолчанию: all
– печатает предупреждение, когда встречается необъявленная переменная.
Значение по умолчанию: true
– вызывает печать полезных комментариев и советов по программированию.
Транслирует файл 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
вычисляет свои аргументы.
При трансляции кода Maxima в код Lisp, транслятору важно знать, какие функции
следует вызывать как транслированные или компилированные, а какие как обычные Maxima
функции или неопределенные. Данная декларация, помещенная в начале транслируемого
файла, дает транслятору информацию, что хотя f_n и не имеет свойство Lisp функции
во время трансляции, но будет иметь таковое в момент вызова.
Если транслятор не знает, что fn
будет Lisp функцией, то
генерируется код (MFUNCTION-CALL fn arg1 arg2 ...)
.
Previous: Макросы, Up: Определение функций [Contents][Index]