Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

[1f6f15]: ru / maxima-tarnavsky-5.xml Maximize Restore History

Download this file

maxima-tarnavsky-5.xml    150 lines (82 with data), 37.7 kB

  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
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="../main.xsl"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" id="maxima-tarnavsky-5" xml:lang="ru">
<head>
<title>Тихон Тарнавский. Maxima. Графики и управляющие конструкции</title>
<link rel="schema.DC" href="http://purl.org/dc/elements/1.1/"/>
<link rel="schema.DCTERMS" href="http://purl.org/dc/terms/"/>
<meta name="DC.identifier" scheme="DCTERMS.URI" content="http://maxima.sourceforge.net/ru/maxima-tarnavsky-5.html"/>
</head>
<body>
<p>Впервые было опубликовано в «<a href="http://www.linuxformat.ru/">Linux Format</a>» <a href="http://www.linuxformat.ru/download/85.pdf">№11&#x00a0;(85), ноябрь&#x00a0;2006&#x00a0;г</a>.</p>
<h3>«А рисовать вы тоже умеете?»&#x00a0;— «Рисовать? Кого-нибудь привлечем»</h3>
<p>Как мы уже говорили в прошлый раз, количество различных функций в Maxima разработчики постарались свести к минимуму, а широту размаха каждой конкретной функции, соответственно, к максимуму. Соблюдается эта тенденция и в функциях построения графиков: основных таких функций всего две, с очевидными, как всегда, названиями&#x00a0;<kbd>plot2d</kbd> и <kbd>plot3d</kbd> (одно из значений слова <em>plot</em>&#x00a0;<em>график</em>, а аббревиатуры <em>2d</em> и <em>3d</em> переводятся как <em>двумерный</em> и <em>трехмерный</em>). Если говорить точнее, возможности графической отрисовки не встроены в Maxima, а реализованы посредством внешних программ, в чем и прослеживается пресловутый Unix-way: «одна задача&#x00a0;— одна программа». По умолчанию, построением графиков занимается <kbd>gnuplot</kbd>, но кроме него есть разрабатываемый вместе с Maxima и идущий в ее же пакете <kbd>openmath</kbd>. Gnuplot необходимо установить (вручную либо автоматически&#x00a0;— как зависимость Maxima) из пакета <kbd>gnuplot-nox</kbd>, либо просто <kbd>gnuplot</kbd>, а для работы <kbd>openmath</kbd> нужен командный интерпретатор <kbd>wish</kbd>, входящий обычно в пакет <kbd>tk</kbd>; и, начиная с версии 5.10.0, еще и xMaxima.</p>
<p>Теперь кратко&#x00a0;— о возможностях. Начнем с <kbd>plot2d</kbd>. Кратчайший вариант ее вызова такой: <kbd>plot2d(выражение,&#x00a0;[символ,&#x00a0;начало,&#x00a0;конец])</kbd>, где выражение задает функцию, график которой нужно построить, символ&#x00a0;— неизвестное (он, понятное дело, должен быть единственным неопределенным символом, входящим в выражение), а начало и конец задают отрезок оси <kbd>Х</kbd> для построения графика; участок по оси <kbd>Y</kbd> в таком варианте записи выбирается автоматически, исходя из минимума и максимума функции на заданном промежутке. Обратите внимание, что неизвестное и концы промежутка нужно задавать не тремя отдельными параметрами, как, скажем, в <kbd>integrate</kbd>, а в виде списка. Это связано с тем, что <kbd>plot2d</kbd> может принимать еще и дополнительные аргументы&#x00a0;— в таком случае они перечисляются следом за таким списком, что исключает всякую путаницу.</p>
<p>После вызова функции <kbd>plot2d</kbd> в таком варианте откроется окно <kbd>gnuplot</kbd>, в котором будет отображен затребованный график. Никакой интерактивной работы с полученным изображением <kbd>gnuplot</kbd> не предусматривает, кроме автоматического его масштабирования при изменении размеров окна. Насмотревшись вдоволь, можно закрыть окно с графиком клавишей <kbd>Q</kbd>, либо, в случае работы с Maxima в редакторе TeXmacs или wxMaxima, просто переключиться обратно в интерфейс, оставив окно <kbd>gnuplot</kbd> открытым, и продолжить работу:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-01.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-02-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-03-thumb.png" alt="" /></p>
<p>В некоторых случаях автоматический подбор отображаемого участка вертикальной оси может нас не устроить. Например, он работает не очень хорошо, если функция имеет на заданном промежутке точку разрыва, хотя бы один из односторонних пределов в которой равен бесконечности: тогда промежуток по оси <kbd>Y</kbd> будет выбран слишком большим. Да и в других случаях может понадобиться изменить умолчательное поведение. Для этого предусмотрен такой вариант вызова функции: <kbd>plot2d(выражение,&#x00a0;[символ,&#x00a0;начало,&#x00a0;конец], [y,&#x00a0;начало,&#x00a0;конец])</kbd>. Здесь буква <kbd>y</kbd> используется в качестве обозначения вертикальной оси, а остальные два параметра имеют тот же смысл, что и выше.</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-04-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-05-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-06-thumb.png" alt="" /></p>
<p>Как видите, умолчательный вид графиков в <kbd>gnuplot</kbd> достаточно прост и даже аскетичен, но здесь можно очень и очень многое менять с помощью дополнительных опций. Некоторые из которых будут освещены чуть ниже, а остальные можно изучить по документации к <kbd>gnuplot</kbd>.</p>
<p>Чтобы построить на одной и той же картинке одновременно два графика (или больше), просто передайте функции <kbd>plot2d</kbd> вместо отдельного выражения их список:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-07-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-08-thumb.png" alt="" /></p>
<p>Здесь <kbd>[x,&#x00a0;0.01,&#x00a0;5]</kbd> вместо <kbd>[x,&#x00a0;0,&#x00a0;5]</kbd> я написал «по привычке»&#x00a0;— Maxima 5.9.x выдавала ошибку, если заданная функция была не определена на одном из концов интервала. В 5.10.0 мне эту ошибку воспроизвести не удалось; так что есть основания полагать, что поведение в таких случаях поправили.</p>
<p>Может <kbd>plot2d</kbd> строить и графики параметрически заданных функций. Для этого используется список с ключевым словом <kbd>parametric</kbd>: <kbd>plot2d([parametric,&#x00a0;x-выражение,&#x00a0;y-выражение, [переменная,&#x00a0;начало,&#x00a0;конец], [nticks,&#x00a0;количество]])</kbd>. Здесь <kbd>x-выражение</kbd> и <kbd>y-выражение</kbd> задают зависимость координат от параметра, то есть, по сути, это две функции вида <var>x</var>(<var>t</var>), <var>y</var>(<var>t</var>), где t&#x00a0;— переменная параметризации. Эта же переменная должна фигурировать в следующем аргументе-списке, а параметры <kbd>начало</kbd>, <kbd>конец</kbd>, как и в двух других рассмотренных случаях, задают отрезок, в пределах которого этот параметр будет изменяться. Последний аргумент-список, с ключевым словом <kbd>nticks</kbd>, задает количество кусочков, на которые будет разбит интервал изменения параметра при построении графика. Этот аргумент опционален, но на практике он нужен почти всегда: умолчательное значение <kbd>nticks</kbd> равно <kbd>10</kbd>; согласитесь, редко бывает нужно в качестве графика получить ломаную из 10 отрезков. Вот пример построения графика параметрической функции:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-09-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-10-thumb.png" alt="" /></p>
<p>Кроме <kbd>parametric</kbd>, функция <kbd>plot2d</kbd> понимает еще одно ключевое слово: <kbd>discrete</kbd>. Предназначено оно, как нетрудно догадаться, для отображения на плоскости дискретных множеств; точнее говоря, конечных наборов точек. По записи аргументов такой вариант распадается еще на два: <kbd>plot2d([discrete,&#x00a0;x-список,&#x00a0;y-список])</kbd> и <kbd>plot2d([discrete,&#x00a0;[x,&#x00a0;y]-список])</kbd>. В первом варианте координаты задаются как два отдельных списка <kbd>[x1,&#x00a0;x2,&#x00a0;…,&#x00a0;xn], [y1,&#x00a0;y2,&#x00a0;,…,&#x00a0;yn]</kbd>, а во втором&#x00a0;— как список пар координат отдельных точек <kbd>[[x1,&#x00a0;y1],&#x00a0;[x2,&#x00a0;y2],&#x00a0;…,&#x00a0;[xn,&#x00a0;yn]]</kbd>.</p>
<p>Если мы, к примеру, имеем набор статистических значений, зависящих от номера, мы можем отобразить его, задав в качестве x-координат сами эти номера, то есть натуральные числа:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-11-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-12-thumb.png" alt="" /></p>
<p>По умолчанию множество отображается в виде ломаной с вершинами в заданных точках; такое поведение можно изменить и получить вывод, к примеру, в виде отдельных точек. Это достигается использованием специальных опций, применимых как к <kbd>plot2d</kbd>, так и к <kbd>plot3d</kbd>, поэтому давайте перейдем к рассмотрению последней.</p>
<h3>Придаем объем</h3>
<p>Функция <kbd>plot3d</kbd> имеет два варианта вызова: один для явного задания функции и один для параметрического. В обоих случаях функция принимает три аргумента. Для явно заданной функции: <kbd>plot3d(выражение, [переменная1,&#x00a0;начало,&#x00a0;конец], [переменная2,&#x00a0;начало,&#x00a0;конец])</kbd>; аргументы аналогичны <kbd>plot2d</kbd>, с той разницей, что здесь независимых переменных две.</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-13-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-14-thumb.png" alt="" /></p>
<p>Построение нескольких поверхностей на одном графике не поддерживается&#x00a0;— потому, вероятно, что на таком рисунке проблематично было бы что-либо разглядеть. Посему для параметрически заданной функции ключевое слово parametric не требуется: вызов с первым аргументом-списком уже не с чем перепутать. График параметрически заданной функции строится так: <kbd>plot3d([выражение1,&#x00a0;выражение2,&#x00a0;выражение3], [переменная1,&#x00a0;начало,&#x00a0;конец], [переменная2,&#x00a0;начало,&#x00a0;конец])</kbd>, где <kbd>выражения</kbd> отвечают, по порядку, <var>x</var>(<var>u</var>,&#x00a0;<var>v</var>), <var>y</var>(<var>u</var>,&#x00a0;<var>v</var>), <var>z</var>(<var>u</var>,&#x00a0;<var>v</var>).</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-15-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-16-thumb.png" alt="" /></p>
<p>С помощью параметрической формы можно строить и пространственные кривые. Для этого просто нужно задать второй, фиктивный, параметр, чтобы Maxima не ругалась на неправильный синтаксис вызова функции:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-17-thumb.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-18-thumb.png" alt="" /></p>
<p>И отсюда мы плавно переходим к опциям функций построения графиков, посредством использованной выше опции <kbd>grid</kbd>. Каждая опция имеет некоторое умолчательное значение, а изменить его можно, добавив к аргументам список вида <kbd>[имя-опции,&#x00a0;значение]</kbd>. Строго говоря, рассмотренные выше <kbd>y</kbd> и <kbd>nticks</kbd> также являются опциями; в предпоследнем примере мы задали опции <kbd>nticks</kbd> значение <kbd>120</kbd>, а в примере перед ним в качестве значения опции <kbd>y</kbd> использовалась пара чисел <kbd>0,&#x00a0;5</kbd>. В документации к Maxima символ <kbd>x</kbd>, выступавший в примерах выше в качестве обязательного параметра, также приводится как опция; на самом деле опцией он является только в случае <kbd>parametric</kbd> и действует тогда так же, как и опция <kbd>y</kbd>, только по другой оси. Опция <kbd>grid</kbd>, использованная выше, применима к трехмерным графикам вместо опции <kbd>nticks</kbd>, используемой для двумерных. Она, также как и <kbd>y</kbd>, задается в виде двух целых значений, которые для поверхностей задают размер ячеек сетки, в виде которой отображается поверхность; первое число&#x00a0;— вдоль оси <var>X</var>, второе&#x00a0;— вдоль оси <var>Y</var>; либо, в случае параметрического задания, по первому и по второму параметру соответственно. Для кривых из этих параметров действует только один, но писать нужно опять же оба, дабы не нарушать синтаксис; и здесь этот параметр имеет в точности тот же смысл, что <kbd>nticks</kbd> для кривых на плоскости. Но перейдем к другим опциям.</p>
<h3>С претензией на красоту</h3>
<p>Первая опция, которую мы рассмотрим, задает формат вывода результата; так она и называется: <kbd>plot_format</kbd>. Формат может принимать одно из четырех значений, первое из которых действует по умолчанию: <kbd>gnuplot</kbd>, <kbd>mgnuplot</kbd>, <kbd>openmath</kbd> и <kbd>ps</kbd>. В умолчательном варианте (значение <kbd>gnuplot</kbd>) данные для отображения передаются напрямую программе <kbd>gnuplot</kbd>, которая сама по себе имеет достаточно гибкое управление, и параметры ей можно передавать прямо из Maxima с помощью дополнительных опций функций <kbd>plot2d</kbd>/<kbd>3d</kbd>. Параметров этих настолько много, что <kbd>gnuplot</kbd> могла бы стать темой отдельной статьи; так что обращайтесь за ними к документации по <kbd>gnuplot</kbd>. В противовес своим богатым возможностям, <kbd>gnuplot</kbd> имеет перед следующими двумя интерфейсами (если откровенно&#x00a0;— скорее, лишь перед одним из них) только один недостаток: она генерирует статичное изображение, тогда как <kbd>mgnuplot</kbd> и openmath позволяют в реальном времени масштабировать и передвигать картинку, а <kbd>plot3d</kbd>&#x00a0;— еще и вращать линию или поверхность в разные стороны в пространстве.</p>
<p>Следующий вариант&#x00a0;<kbd>mgnuplot</kbd>&#x00a0;— является дополнительным интерфейсом к <kbd>gnuplot</kbd>, написанным на Tcl/Tk, но динамика у него настолько «задумчивая», а остальные возможности настолько бедны, что я не вижу смысла останавливаться на нем подробнее.</p>
<p>И перехожу сразу к <kbd>openmath</kbd>. Он тоже не очень-то поддается управлению, зато предоставляет хорошую интерактивность, особенно ценную в трехмерном варианте: после того, как объект сгенерирован, его можно масштабировать и очень динамично вращать, разглядывая со всех сторон. Особенно это помогает для сложных поверхностей, когда, глядя на статичную «сетку» <kbd>gnuplot</kbd>, непросто понять форму поверхности. Справедливости ради нужно отметить, что <kbd>gnuplot</kbd> позволяет задавать точку обзора трехмерного объекта в качестве одного из многочисленных параметров, то есть хотя картинка и статична, но с какой стороны на нее смотреть, мы можем указать произвольно.</p>
<p>Ну и последнее значение опции <kbd>plot_format</kbd> подталкивает Maxima к непосредственной генерации PostScript-документа с изображением. Но и здесь надо сказать: генерировать PostScript-вывод умеет и все тот же <kbd>gnuplot</kbd>.</p>
<p>Большинство остальных опций относятся только к формату вывода <kbd>gnuplot</kbd>. А мы рассмотрим еще одну универсальную, пригодную для всех форматов и преобразующую не результирующее изображение, а сам процесс построения графика; точнее, систему координат. Называется эта опция <kbd>transform_xy</kbd>, по умолчанию она равна <kbd>false</kbd>. Передавать ей нужно выражение, сгенерированное функцией <kbd>make_transform([x,&#x00a0;y,&#x00a0;z], f1(x,&#x00a0;y,&#x00a0;z), f2(x,&#x00a0;y,&#x00a0;z), f3(x,&#x00a0;y,&#x00a0;z))</kbd>. Кроме того, существует одно встроенное преобразование, известное как <kbd>polar_xy</kbd> и соответствующее <kbd>make_transform([r,&#x00a0;th,&#x00a0;z], r*cos(th), r*sin(th), z)</kbd>, то есть переходу к полярной цилиндрической системе координат. В качестве примера использования <kbd>transform_xy</kbd> приведу преобразование к полярным сферическим координатам, раз уж во встроенном виде его нет:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-19.png" alt="" /></p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-20-thumb.png" alt="" /></p>
<p>Обратите внимание: в первом аргументе-списке к make_transform последним должен идти зависимый символ, то есть тот, который будет выступать функцией от двух других.</p>
<p>Если вам нужно постоянно работать со сферическими координатами, можете задать, скажем, <kbd>spherical_xy:make_transform([t,&#x00a0;f,&#x00a0;r], r*sin(f)*sin(t), r*cos(f)*sin(t), r*cos(t))</kbd>, и затем при построении графиков писать [transform_xy, spherical_xy]. Ветвитесь и повторяйтесь До сих пор мы двигались только по прямой, а теперь поговорим о средствах «изменения траектории»: условном операторе и циклах.</p>
<p>Начнем с условия. В Maxima, в отличие от большинства «традиционных» процедурных и объектных языков программирования, где существует так называемый условный оператор, привычная связка <kbd>if</kbd>-<kbd>then</kbd>-<kbd>else</kbd> является не синтаксической конструкцией, а самым настоящим оператором. По своему действию он больше всего похож на тернарный оператор языка C, только с более «человеческим» синтаксисом: <kbd>if&#x00a0;условие&#x00a0;then&#x00a0;выражение1&#x00a0;else&#x00a0;выражение2</kbd>. При выполнении «условия» из двух «выражений» вычисляется только первое и возвращается как результат оператора; в противном случае выполняется только второе и оно же является значением всего выражения <kbd>if</kbd>-<kbd>then</kbd>-<kbd>else</kbd>. Часть конструкции <kbd>else&#x00a0;выражение2</kbd>, как и в большинстве языков программирования, опциональна. Если ее нет, а условие все-таки не выполнилось, результат оператора <kbd>if</kbd> будет равен <kbd>false</kbd>.</p>
<p>При этом, конечно же, никто вам не мешает использовать этот оператор как обычную условную конструкцию, а возвращаемое значение просто игнорировать. С другой стороны, оператор <kbd>if</kbd> можно применять, например, для задания рекурсивных последовательностей:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-21-thumb.png" alt="" /></p>
<p>Немного о самих условиях, которые могут проверяться оператором <kbd>if</kbd>. Условия <kbd>&gt;</kbd>, <kbd>&lt;</kbd>, <kbd>&gt;=</kbd>, <kbd>&lt;=</kbd> записываются и расшифровываются традиционно, так же как и логические операторы <kbd>and</kbd>, <kbd>or</kbd>, <kbd>not</kbd>. А вот о равенствах-неравенствах нужно сказать пару слов. Равенство в Maxima есть двух видов: синтаксическое и логическое. Знаком <kbd>=</kbd> обозначается как раз первое, а второе вычисляется с помощью функции <kbd>equal()</kbd>. Чтобы не быть многословными, отличие синтаксического равенства от логического продемонстрируем на примере; здесь дополнительно используется предикат по имени <kbd>is</kbd>, которые проверяет на истинность свой аргумент.</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-22.png" alt="" /></p>
<p>Ну и неравенств, соответственно, тоже существует два, с тем же смыслом. Синтаксическое неравенство обозначается достаточно непривычно&#x00a0;— через <kbd>#</kbd>; видимо, этот символ разработчики сочли наиболее визуально схожим со знаком ≠. Ну а логическое неравенство обозначено через <kbd>notequal()</kbd>.</p>
<p>Конечно, кроме упомянутых сравнений в условном операторе можно использовать любые предикаты, то есть функции, возвращающие логические значения <kbd>true</kbd>/<kbd>false</kbd>. Функций таких достаточно много, но все они достаточно просты, поэтому не буду тратить время на их описание: его можно почерпнуть в том же объеме из документации.</p>
<p>Напоследок перейдем к циклам. Цикл в Maxima будто бы тоже один. Но он имеет столько различных вариантов, что назвать это все одним оператором цикла язык не поворачивается. Вот как выглядят основные разновидности:</p>
<ul class="dashedlist">
<li><kbd>for переменная:начало step шаг thru конец do выражение</kbd></li>
<li><kbd>for переменная:начало step шаг while условие do выражение</kbd></li>
<li><kbd>for переменная:начало step шаг unless условие do выражение</kbd></li>
</ul>
<p>Первый прокручивает цикл, изменяя <kbd>переменную</kbd> с заданным <kbd>шагом</kbd> от <kbd>начала</kbd> до <kbd>конца</kbd>; второй&#x00a0;— от <kbd>начала</kbd> и пока выполняется <kbd>условие</kbd>; третий&#x00a0;— наоборот, пока <kbd>условие</kbd> не выполняется. К примеру, мы можем получить список из первых десяти членов последовательности из позапрошлого примера:</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-23-thumb.png" alt="" /></p>
<p>Как видите, в качестве оператора цикл в простейшем его виде, в отличие от условия, использовать смысла нет, так как его возвращаемое значение всегда равно <kbd>done</kbd>. В этом примере один из элементов циклического оператора не указан; шаг, как видите, может быть опущен и по умолчанию равен единице. Самое интересное в этом операторе то, что опустить позволяется любую его часть, кроме <kbd>do</kbd>; и в том числе в любых комбинациях. К примеру, опустив кроме <kbd>step</kbd> еще и <kbd>for</kbd>, мы получаем из этого же оператора традиционные циклы <kbd>while</kbd> и <kbd>unless</kbd> (второй и третий варианты). А проделав то же самое с первым вариантом записи, получим цикл без счетчика вида <kbd>thru</kbd> число <kbd>do</kbd> выражение, который просто повторится заданное число раз. Можно, наоборот, опустить условие окончания и получить цикл с индексной переменной, но бесконечный. А оставив только <kbd>do</kbd>, получим самый простой вариант бесконечного цикла. Из таких бесконечных циклов можно выйти с помощью оператора <kbd>return(выражение)</kbd> (точнее, конечно, конструкции из двух операторов вида <kbd>if&#x00a0;условие&#x00a0;then&#x00a0;return(выражение)</kbd>), который прервет выполнение цикла и вместо done вернет заданное выражение. Естественно, оператор <kbd>return()</kbd> можно применять во всех видах циклов, а не только в бесконечных.</p>
<p>Но и это еще не все. Кроме всех уже рассмотренных вариаций, цикл может принимать еще две ипостаси. Во-первых, вместо <kbd>step</kbd> может использоваться конструкция <kbd>next&#x00a0;выражение</kbd>, смысл которой лучше тоже продемонстрировать на примере</p>
<p class="labeled-image"><img src="i/tarnavsky/5/maxima5-24-thumb.png" alt="" /></p>
<p>После <kbd>next</kbd> может стоять любое вычислимое выражение относительно индекса цикла, и применяться эта конструкция может во всех трех вариантах цикла (<kbd>thru</kbd>/<kbd>while</kbd>/<kbd>unless</kbd>).</p>
<p>А «во-вторых»&#x00a0;— это еще один отдельный вариант цикла: <kbd>for&#x00a0;переменная&#x00a0;in&#x00a0;список&#x00a0;do&#x00a0;выражение</kbd>; либо расширенная форма: <kbd>for&#x00a0;переменная&#x00a0;in&#x00a0;список&#x00a0;условие&#x00a0;do&#x00a0;выражение</kbd>. Здесь цикл будет прокручен с <kbd>переменной</kbd>, изменяющейся по всем элементам <kbd>списка</kbd>; плюс можно задать еще и дополнительное <kbd>условие</kbd> на прерывание цикла. Вот теперь мы с циклами действительно закончили. Как видите, все достаточно разнообразно. Я, признаться, ничего, что здесь не реализовано, и придумать не смог.</p>
<p>Но рассказ о циклах и условном операторе остается неполным, пока я не рассказал о группировке выражений&#x00a0;— ведь в обычном варианте после <kbd>then</kbd> или <kbd>do</kbd> можно написать всего одно из них. А группировка, или, как ее принято называть, составной оператор, в Maxima&#x00a0;— это опять-таки самый настоящий оператор, который тоже, как и положено оператору, возвращает некоторое значение. Обозначается он скобками, самыми что ни на есть круглыми и обыкновенными; а разделяются сгруппированные операторы/выражения внутри этих скобок не менее обыкновенными запятыми. Возвращаемым значением составного оператора является последнее вычисленное выражение.</p>
<p>С условным оператором, столь разнообразными циклами и составным оператором мы уже можем, комбинируя их между собой и с любыми другими функциями и выражениями Maxima, писать полноценные программы с использованием богатого символьного математического аппарата. Естественно, теперь нам захочется сохранять эти программы в виде внешних файлов, чтобы не набирать их каждый раз вручную, а подгружать одной короткой командой. Об этом, а также о математических аналогах объявления переменных&#x00a0;— в завершающей статье цикла.</p>
<p>Мы также поговорим о математических аналогах объявления переменных и рассмотрим практические примеры с применением уже достаточно богатого известного нам инструментария.</p>
</body>
</html>