File: vars.chapt.txt

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

			Variables

*CMD := --- assign a variable or a list; define a function
*STD
*CALL
	var := expr
	{var1, var2, ...} := {expr1, expr2, ...}
	var[i] := expr
	fn(arg1, arg2, ...) := expr
Precedence:
*EVAL OpPrecedence(":=")

*PARMS

{var} -- atom, variable which should be assigned

{expr} -- expression to assign to the variable or body of function

{i} -- index (can be integer or string)

{fn} -- atom, name of a new function to define

{arg1}, {arg2} -- atoms, names of arguments of the new function {fn}

*DESC

The {:=} operator can be used
in a number of ways. In all cases, some sort of assignment or definition takes
place.

The first form is the most basic one. It evaluates the expression on
the right-hand side and assigns it to the variable named on the
left-hand side. The left-hand side is not evaluated. The evaluated
expression is also returned.

The second form is a small extension, which allows one to do multiple
assignments. The first entry in the list on the right-hand side is
assigned to the first variable mentioned in the left-hand side, the
second entry on the right-hand side to the second variable on the
left-hand side, etc. The list on the right-hand side must have at
least as many entries as the list on the left-hand side. Any excess
entries are silently ignored. The result of the expression is the list
of values that have been assigned.

The third form allows one to change an entry in the list. If the index
"i" is an integer, the "i"-th entry in the list is changed to the
expression on the right-hand side. It is assumed that the length of
the list is at least "i". If the index "i" is a string, then
"var" is considered to be an associative list (sometimes called hash
table), and the key "i" is paired with the value "exp". In both
cases, the right-hand side is evaluated before the assignment and the
result of the assignment is {True}.

The last form defines a function. For example, the assignment {fn(x) := x^2} removes any rules previously associated with {fn(x)} and defines the rule {fn(_x) <-- x^2}. Note that the left-hand side may take a different form if
{fn} is defined to be a prefix, infix or bodied function. This case
is special since the right-hand side is not evaluated
immediately, but only when the function {fn} is used. If this takes
time, it may be better to force an immediate evaluation with {Eval} (see the last example). If the expression on the right hand side begins with {Eval()}, then it <i>will</i> be evaluated before defining the new function.

A variant of the function definition can be used to make a function accepting a variable number of arguments. The last argument

*E.G.

A simple assignment:

	In> a := Sin(x) + 3;
	Out> Sin(x)+3;
	In> a;
	Out> Sin(x)+3;

Multiple assignments:

	In> {a,b,c} := {1,2,3};
	Out> {1,2,3};
	In> a;
	Out> 1;
	In> b+c;
	Out> 5;

Assignment to a list:

	In> xs := { 1,2,3,4,5 };
	Out> {1,2,3,4,5};
	In> xs[3] := 15;
	Out> True;
	In> xs;
	Out> {1,2,15,4,5};

Building an associative list:

	In> alist := {};
	Out> {};
	In> alist["cherry"] := "red";
	Out> True;
	In> alist["banana"] := "yellow";
	Out> True;
	In> alist["cherry"];
	Out> "red";
	In> alist;
	Out> {{"banana","yellow"},{"cherry","red"}};

Defining a function:

	In> f(x) := x^2;
	Out> True;
	In> f(3);
	Out> 9;
	In> f(Sin(a));
	Out> Sin(a)^2;

Defining a function with variable number of arguments:

	In> f(x, ...) := If(IsList(x),Sum(x),x);
	Out> True;
	In> f(2);
	Out> 2;
	In> f(1,2,3);
	Out> 6;

Defining a new infix operator:

	In> Infix("*&*",10);
	Out> True;
	In> x1 *&* x2 := x1/x2 + x2/x1;
	Out> True;
	In> Sin(a) *&* Cos(a);
	Out> Tan(1)+Cos(1)/Sin(1);
	In> Clear(a);
	Out> True;
	In> Sin(a) *&* Exp(a);
	Out> Sin(a)/Exp(a)+Exp(a)/Sin(a);

In the following example, it may take some time to compute the Taylor
expansion. This has to be done every time the function {f} is called.

	In> f(a) := Taylor(x,0,25) Sin(x);
	Out> True;
	In> f(1);
	Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-
	x^11/39916800+x^13/6227020800-x^15/
	1307674368000+x^17/355687428096000-x^19/
	121645100408832000+x^21/51090942171709440000
	-x^23/25852016738884976640000+x^25
	/15511210043330985984000000;
	In> f(2);
	Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-
	x^11/39916800+x^13/6227020800-x^15
	/1307674368000+x^17/355687428096000-x^19/
	121645100408832000+x^21/51090942171709440000
	-x^23/25852016738884976640000+x^25/
	15511210043330985984000000;

The remedy is to evaluate the Taylor expansion immediately. Now the
expansion is computed only once.

	In> f(a) := Eval(Taylor(x,0,25) Sin(x));
	Out> True;
	In> f(1);
	Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-
	x^11/39916800+x^13/6227020800-x^15/
	1307674368000+x^17/355687428096000-x^19/
	121645100408832000+x^21/51090942171709440000
	-x^23/25852016738884976640000+x^25
	/15511210043330985984000000;
	In> f(2);
	Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-
	x^11/39916800+x^13/6227020800-x^15
	/1307674368000+x^17/355687428096000-x^19/
	121645100408832000+x^21/51090942171709440000
	-x^23/25852016738884976640000+x^25/
	15511210043330985984000000;

*SEE Set, Clear, [], Rule, Infix, Eval, Function

*CMD Set --- assignment
*CORE
*CALL
	Set(var, exp)

*PARMS

{var} -- variable which should be assigned

{exp} -- expression to assign to the variable

*DESC

The expression "exp" is evaluated and assigned it to the variable
named "var". The first argument is not evaluated. The value True
is returned.

The statement {Set(var, exp)} is equivalent to {var := exp}, but the {:=} operator
has more uses, e.g. changing individual entries in a list.

*E.G.

	In> Set(a, Sin(x)+3);
	Out> True;
	In> a;
	Out> Sin(x)+3;

*SEE Clear, :=

*CMD Clear --- undo an assignment
*CORE
*CALL
	Clear(var, ...)

*PARMS

{var} -- name of variable to be cleared

*DESC

All assignments made to the variables listed as arguments are
undone. From now on, all these variables remain unevaluated (until a
subsequent assignment is made). The result of the expression is
True.

*E.G.

	In> a := 5;
	Out> 5;
	In> a^2;
	Out> 25;
	
	In> Clear(a);
	Out> True;
	In> a^2;
	Out> a^2;

*SEE Set, :=



*CMD Local --- declare new local variables
*CORE
*CALL
	Local(var, ...)

*PARMS

{var} -- name of variable to be declared as local

*DESC

All variables in the argument list are declared as local
variables. The arguments are not evaluated. The value True is
returned.

By default, all variables in Yacas are global. This means that the
variable has the same value everywhere. But sometimes it is useful to
have a private copy of some variable, either to prevent the outside
world from changing it or to prevent accidental changes to the outside
world. This can be achieved by declaring the variable local. Now only
expressions within the {Prog} block (or its
syntactic equivalent, the {[  ]} block) can access
and change it. Functions called within this block cannot access the
local copy unless this is specifically allowed with {UnFence}.

*E.G.

	In> a := 3;
	Out> 3;
	
	In> [ a := 4; a; ];
	Out> 4;
	In> a;
	Out> 4;
	
	In> [ Local(a); a := 5; a; ];
	Out> 5;
	In> a;
	Out> 4;

In the first block, {a} is not declared local and
hence defaults to be a global variable. Indeed, changing the variable
inside the block also changes the value of {a}
outside the block. However, in the second block {a}
is defined to be local and now the value outside the block stays the
same, even though {a} is assigned the value 5 inside
the block.

*SEE LocalSymbols, Prog, [], UnFence

*CMD ++ --- increment variable
*STD
*CALL
	var++

*PARMS

{var} -- variable to increment

*DESC

The variable with name "var" is incremented, i.e. the number 1 is
added to it. The expression {x++} is equivalent to
the assignment {x := x + 1}, except that the
assignment returns the new value of {x} while {x++} always returns true. In this respect, Yacas' {++} differs from the corresponding operator in the
programming language C.

*E.G.

	In> x := 5;
	Out> 5;
	In> x++;
	Out> True;
	In> x;
	Out> 6;

*SEE --, :=

*CMD -- --- decrement variable
*STD
*CALL
	var--

*PARMS

{var} -- variable to decrement

*DESC

The variable with name "var" is decremented, i.e. the number 1 is
subtracted from it. The expression {x--} is
equivalent to the assignment {x := x - 1}, except
that the assignment returns the new value of {x}
while {x--} always returns true. In this respect,
Yacas' {--} differs from the corresponding operator
in the programming language C.

*E.G.

	In> x := 5;
	Out> 5;
	In> x--;
	Out> True;
	In> x;
	Out> 4;

*SEE ++, :=

*CMD Object --- create an incomplete type
*STD
*CALL
	Object("pred", exp)

*PARMS

{pred} -- name of the predicate to apply

{exp} -- expression on which "pred" should be applied

*DESC

This function returns "obj" as soon as "pred" returns {True} when applied on "obj". This is used to declare
so-called incomplete types.

*E.G.

	In> a := Object("IsNumber", x);
	Out> Object("IsNumber",x);
	In> Eval(a);
	Out> Object("IsNumber",x);
	In> x := 5;
	Out> 5;
	In> Eval(a);
	Out> 5;

*SEE IsNonObject

*CMD SetGlobalLazyVariable --- global variable is to be evaluated lazily
*CORE
*CALL
	SetGlobalLazyVariable(var,value)

*PARMS

{var} -- variable (held argument)

{value} -- value to be set to (evaluated before it is assigned)

*DESC

{SetGlobalLazyVariable} enforces that a global variable will re-evaluate
when used. This functionality doesn't survive if {Clear(var)}
is called afterwards.

Places where this is used include the global variables {%} and {I}.

The use of lazy in the name stems from the concept of lazy evaluation.
The object the global variable is bound to will only be evaluated when
called. The {SetGlobalLazyVariable} property only holds once: after 
that, the result of evaluation is stored in the global variable, and it won't be reevaluated again:

	In> SetGlobalLazyVariable(a,Hold(Taylor(x,0,30)Sin(x)))
	Out> True

Then the first time you call {a} it evaluates {Taylor(...)} and assigns the result to {a}. The next time
you call {a} it immediately returns the result.
{SetGlobalLazyVariable} is called for {%} each time {%} changes.

The following example demonstrates the sequence of execution:

	In> SetGlobalLazyVariable(test,Hold(Write("hello")))
	Out> True

The text "hello" is not written out to screen yet. However, evaluating
the variable {test} forces the expression to be evaluated:

	In> test
	"hello"Out> True

*E.G.

	In> Set(a,Hold(2+3))
	Out> True
	In> a
	Out> 2+3
	In> SetGlobalLazyVariable(a,Hold(2+3))
	Out> True
	In> a
	Out> 5


*SEE Set, Clear, Local, %, I

*CMD UniqueConstant --- create a unique identifier
*STD
*CALL
	UniqueConstant()

*DESC

This function returns a unique constant atom each time you call
it. The atom starts with a C character, and a unique number is
appended to it.

*E.G.

	In> UniqueConstant()
	Out> C9
	In>  UniqueConstant()
	Out> C10

*SEE LocalSymbols

*CMD LocalSymbols --- create unique local symbols with given prefix
*STD
*CALL
	LocalSymbols(var1, var2, ...) body

*PARMS

{var1}, {var2}, ... -- atoms, symbols to be made local

{body} -- expression to execute

*DESC

Given the symbols passed as the first arguments to LocalSymbols a set of local
symbols will be created, and creates unique ones for them, typically of the
form {$<symbol><number>}, where {symbol} was the symbol entered by the user,
and {number} is a unique number. This scheme was used to ensure that a generated
symbol can not accidentally be entered by a user.

This is useful in cases where a guaranteed free variable is needed,
for example, in the macro-like functions ({For}, {While}, etc.).

*E.G. notest

	In> LocalSymbols(a,b)a+b
	Out> $a6+ $b6;

*SEE UniqueConstant