Calqit Summary

4. Summary for experienced programmers

This is an introduction to the main points. For a quick language specification, see here.

Calqit mostly deals with vectors of double-precision numbers. A scalar is a vector of length 1, the empty set is a vector of length 0. Familiar programming syntax such as "x = 2*exp(y)+1" is legal. However, you can also use implied multiplication, and in certain contexts implied brackets and implied commas. e.g. you can write E = m c^2 and x = r sin(theta) and x = r sin theta.

N.B. You can try the following examples by cutting and pasting the text into calqit.

help funcGet information on func
?funcditto
??funcmore information
??xdisplay x in full
Basic syntax
# a commentEverything after # till newline is a comment.
## descriptionUse double-# to start a user function help description
x ySame as x*y, element-wise multiplication.
5x, x(5), x 5, x*5, x . 5all mean x*5
m.5, m\5, m\\55'th element, 5'th row, 5'th column
x[5], x.5both mean 5'th element of x
m[5,:],  m[:,5]5'th row, 5'th column of a matrix m
x[3:end]same as x[3:x.size]
x = (2, 5, 3)x = vector with elements 2,5,3
x = (2 5 3)x = 30 (implied multiplication)
x = [2 5 3]square brackets => implied commas: same as x=[2,5,3]
x += 6x = x+6, also allowed are -= *= /= ,= ;=
++x, --xincrement, decrement
9//1+2// means everything to right is denominator, so this evaluates to 3
a @ b, m @+ v,  m @- v tensor product, displacement (add v to all rows/cols)
|3-5| absolute value, same as abs(3-5)
a & b, a | b, a && b, a || belementwise and/or, short-circuit and/or
M . x, M .x, matrix multiplication (inner product): note the space
x .y'' means transpose, so this is a scalar product (if x and y are row vectors)
sin(x), sin{x}, sin[x], sin xuse any brackets you like, or none!
x.sinalternative function syntax
x.size, x.shape, x.nrow, x.mean, x.sumsome further examples
\sin{x} same as sin(x)
sin^2(x) convenient syntax for (sin(x))^2
disp('hello'," there");use either '...' or "..." for strings
disp("pi=",pi,', cos(pi)=', cos(pi));display strings or numbers
[x,y] = load('mydata.txt')multiple output from function
ans refers to the last displayed answer the two before it
semicolon syntax for functionals
plot(x,y)plot, using two vectors of equal length
plot(sin, xmin,xmax)plot a function
plot(sin(x^2)-x; x,xmin,xmax)plot an expression as a function: note the semicolon
see also: qinteg, fzero, min, cheby
sum((1/n)sin(n x); n,1:2:11)sum a series (x can be a vector)
see also: table
Passing a function
fzero(poly, [0 1 1 -1], [1 2])find a zero lying between x=1 and x=2
lsfit(gauss, [1 2], x,y,dy)least-squares fit to function gauss
user definitions
r := 1//x^2 + 1Define a shorthand using globals
sinc(x) := sin(x)/x;Define a function
myfun(n,x) := { blah; blah blah; etc }Define a function
#eg myfun([0 1],x)put a comment near the definition
?myfunhelp feature gives the call syntax and comment from file
myfunc(z,v) := { v /=c; z sqrt((1-v)//1+v); } return value is the outcome of last evaluated statement
rt(y) := { t=y; x=(y+1)/2; while x~=t: {t=x; x=(x+y/x)/2;} x; } sqrt(y) by Newton-Raphson
myfunc(z,v) := { v /=c; d=z sqrt((1-v)//1+v); } this will return d
function [v,d] = myfunc(z,v)
   v /= c;
   d = z sqrt((1-v)//1+v);
end
syntax allowing return of more than one variable
function myfunc(z, v:1, n:0) ...
default values
function cube(^m) ... use ^ for pass-by-reference
keywords, block statements
for, while, break, if, else, function, return
unless, persistent, global
help, ?, ?consts, ?funcs, func
use, set, clear, \tex, quit, exit
for j=0:10; bnc(j,0:j)Pascal's triangle!
if n>1: { x *= n; n -= 1; }braces {} around a block of statements
gcd(a, b):= {while b: {t=b; b=a mod b; a=t;} t;} Euclid's algorithm!
\tex \frac{\sqrt{9}}{2}evaluate a TeX expression
Types
a=[1 3 4];; b='hello';; c=(1==1) number, string, boolean
a = 2;; b = complex(1,2);; c = list(0)see ?complex, ?list
str = ['' 73 68]; num = 0+'hi';the left-most term decides the type of result
files
use myprogcompile and run a script
dircurrent directory (folder) contents
cddisplay current directory
cd pathnamechange directory
cd ?change directory (folder) via a dialogue
cd('mypath')is also valid
x=load('mydata.txt')load the first column of numbers from a text file
x=load mydata.txtcan also be used
[x,y]=load('mydata.txt')load the first two columns into x and y
x=load('mydata.txt',1)load all numbers in the file as a single vector
fopen, fread, fwrite, fclosegeneral file io

Compiling and running scripts
You can write a calqit script using any text editor, then run it from calqit by the instruction:

use filename

This will compile all user-defined functions in the script, and also compile and run the script itself. The user-defined functions now reside in memory. This approach is similar to Python and Perl, different from Matlab. Beware: if you edit your code, calqit will not notice until you compile it again (checking of file modification times is planned but not yet implemented). It makes sense to put well-established functions (i.e. whose code is not going to change) in a script different to the one you are currently working on, then you only need to compile the stable functions once.

The default extension expected by the "use" command is ".clq".

If you use the "open with" feature of windows explorer using calqit, then calqit will launch, run the script, and then exit. You can also do this by associating the extension ".clq" with calqit, and then double-click your script file in Explorer. Owing to the fast launch time of calqit, this amounts to converting your script into an executable program!

Mouse
Copy and paste in the calqit window by mouse select then ctrl-c, crtl-v. Double-clicking an old command means re-execute it.

Your programs can get access to the mouse via built-in functions click and getmouse. You can also write user functions called onLdown, onLup, onMove, onDrag to respond to mouse messages.

Multi-line statements
The syntax for calqit statements does not require a finishing semi-colon. Rather, any line which does not finish with something like an opening bracket or an operator is interpreted as a finished line. Multi-line statements can be used in scripts but not at the interpreter prompt. In a script you can indicate that a line is not finished by adding a trailing "...". e.g.

x = thing + another_thing / lengthy_formula ...
      + carry_on / finished;        
Alternatively, lines that finish with one of the characters
=.+-/,*^`<>&|~?,
are interpreted as unfinished, and continued on the next line. The same goes for the case of an unfinished square bracket. However, when working with the interpreter you can only offer single-line statements. This still leaves quite a lot of flexibility because calqit's syntax is concise, allowing one to fit a lot on one line. e.g.
tic; for n=1:100 { y\n=qinteg(sin n/x; x,pi,2pi); z/=y\n; } toc; y%

A block of statements may be enclosed between braces ({}) or, in a script, you can reply on the use of indentation e.g.

while j<10:
    do_this
    do_that
    j += 1
and_do_this_after_the_loop  
is the same as
while j<10:
{   do_this
    do_that
    j += 1
}     
and_do_this_after_the_loop  

Brackets
Following a policy of flexible syntax, brackets are mostly interchangeable. i.e. you can use any of () or [] or {} as brackets in expressions, including for function argument lists. Array indexing is by square brackets, or in the case of a single index consisting of a single number or symbol, you can use a dot, as in x.4 for the element at index number 4. Similarly, x\4 means the 4th row and x\\4 means the 4th column. Together these cover the most common cases so in practice Calqit scripts do not need to use bracket-style indexing very much.

To resolve ambiguity between indexing and implied multiplication, a bracket representing an index must be square and you are encouraged to place it immediately after the symbol, without a space. So x(n+3) means x multiplied by (n+3), but x[n+3] means the n+3 element of x, and so does x [n+3]. If you are worried that your code might be unclear, just put in an explicit * sign where appropriate. You can also use a dot or \ or \\ to make it clear that an index is intended.

Square brackets also have a further special use: in this case a space between symbol names or numbers is interpreted as an implied comma (sequencing operator) instead of multiplication. Thus [2 3 5] means the three-element vector (2,3,5), whereas (2 3 5) means 30.

Array indexing is based on 1 not zero. i.e. x[1] is the 1st element of x, and x[0] is illegal. This is like Matlab, and unlike C and C++. (It is under consideration whether to allow the user to adjust this index offset but that is not available at the moment).

Groups of statements (a block) are bracketed by braces {} as in C. e.g.
if n>1: { x *= n; n -= 1; }
(the colon after the if clause can be replaced by a semi-colon if you prefer). Or, as explained above, you can use indentation to indicate a block. So: be warned, if you indent your code in some odd way, it will be interpreted accordingly....

Displayed output
Finish statements with ; or ;; or newline or a comment. A single ; means don't display the result, a double ;; means do display the result. A newline without any semicolon means do display if it is entered at the interpreter prompt, and don't display if it is a line in a script file. Note that by using ;; you can take a look at items for debugging purposes, and then easily find the places where you have done this, using a search for ';;' in a text editor. You can also terminate a statement with ;? to display further info about the result of the statement, and ;! will insert a breakpoint.

To display a vector v in full, use disp v or ??v.

To save results to file (ascii text format), use save. (For more general file io, use fopen, fread, fwrite, fclose).

4.1 Operator precedence

++ --increment, decrement
! ' ~ <name>factorial, transpose, logical not
^ ^^power, matrix power
:sequence (slice)
* / . @ vecmultiply, divide, matrix product, tensor product, vector product
- + mod @+ @-minus, plus, modulo (remainder), displace
< <= == ~= === >= >comparison
& | @& @| @! ?and/or (vector), bitwise and/or/xor, query
,comma (sequencing)
;semicolon (vertical sequencing)
&& ||scalar logical and/or, ('lazy' evaluation)

The precedence of the unary minus sign is such as to preserve standard mathematical notation, so -x^2 means -(x^2) but x^-2 means x^(-2).

4.2 Implied brackets and commas

As well as implied multiplication, calqit offers some further syntax features designed to make the language feel natural.

1. implied brackets Whenever a function expects at least one argument, and the user only wishes to provide a single argument, the brackets can be omitted, as in, for example,
sin x
Be careful, however. At the time of writing sin 2x will evaluate as x*sin(2) (it is planned to change this). Therefore you should use a bracket if there is any possibility of ambiguity.

2. implied commas Inside square brackets, [...], implied multiplication is replaced by implied commas. This is useful, for example, as a quick way to enter a set of numbers, as in x = [12 3 65 1 18].

3. assumed strings When a function usually expects a string or strings as its arguments (for example, dir, cd, load, save) then an alternative syntax is simply to enter the function name then a string without brackets or inverted commas. For example,
dir *.txt
is an alternative form for dir('*.txt')

4.3 Index verses multiplication

Implicit multiplication is so convenient that we don't want to lose it, but it leads to the need to distinguish between array indexing and implied multiplication, as we have mentioned above. The rule is: a variable name followed by a square bracket means an index. So
5x, x (5), x 5, x(5)
all mean 'x times 5', (and so does x*5) whereas
x[5], x.5
mean 'the element of x at index number 5'. The form x. 5 (with a space) is allowed but discouraged.

For a single element of a matrix you would normally write something like
m[2,3]
However if you are looking at individual elements a lot, it may be that you are missing a neater and quicker method using whole rows or columns.

The backslash \ is used as a shorthand for row and column indexing. Thus
x\5
means the 5th row of matrix x (which is the 5th element of x if x is a column vector). You can also write x[5,:] for the 5th row. Use a double-backslash to indicate a column, for example
x\\5
or you can use x[:,5].

When an index is a real number, it is rounded to the nearest integer.

In an array index expression the symbol 'end' evaluates to the size of the vector being indexed, or to the number of rows or columns, as appropriate:e:

v[4:end], m[3:end, 2], m[4, 5:end]
is the same as
v[4:v.size], m[3:m.nrow, 2], m[4, 5:m.ncol]
(calqit will not prevent you from defining your own symbol called 'end' but this is not recommended).

4.4 The use of dot and backslash

The single dot '.' and the backslash '\' appear quite often in calqit expressions. They both have several uses, as follows.

A dot means either an array element (x.3), or a function evaluation (x.size), or a matrix multiplication (x . y) (also called inner product), or a decimal point. If you want matrix multiplication then put a space before the dot.

The backslash character '\' has three purposes. First, it is used for row and column indexing (x\3, x\\3), as outlined above under Index verses multiplication.

Next, a backslash can be placed at the front of function names, in which case it gives another way of accessing functions. For example "sqrt(3)" and "\sqrt(3)" and "\sqrt{3}" all evaluate to the same thing. This can be useful if you want to evaluate simple TeX or LaTeX expressions. There is also a built-in command \tex to do that.

The third use is to allow the user to define symbols with the same name as built-in (or user-defined) functions, but still have access to those functions. For example, you might want to define a variable called "type", as in "type = 10". You can do this, but then in an instruction such as
type(x)
calqit assumes you mean the variable not the function. However you can still get access to the calqit function by writing
\type(x)
The backslash here tells calqit you mean the function not the variable.

Overriding function names such as "sum" is not advisable in general, because then the form "sum[x]" would still be valid (meaning the x'th element of the variable called "sum") but its appearance is now misleading.

4.5 Functionals

In mathematics a "function" such as sin, exp, log, etc. is a 'number machine' that takes a single number as input and returns a single number as output. A "functional" is a 'number machine' that takes a whole function (and possibly one or more numbers) as input and returns a single number as output. The most well-known example is integration: if you provide some function f(x), then I[f(x)] refers to the integral of the function between given limits.

The following built-in calqit functions act as functionals, i.e. they require or can be used with a function as input:

plot, qinteg, fzero, min, qmin, fmin, fminbrac, sum, differ, cheby

The syntax for these functionals has one of the following forms:
i) ff(func, x1, x2)
ii) ff(func, xlimits)
iii) ff(func, xlimits, [], tol)
iv) ff(func, a, xlimits)
v) ff(func, a, xlimits, tol)
vi) ff(func, x, style)
vii) ff(func, x1, x2, style)
viii) ff(expr; x, x1, x2)
In the case of cheby another argument (n) is provided after xlimits.

Cases (i)-(iii) are used when func expects a single argument. Cases (iv),(v) are used for functions such as poly(a,x) which take two arguments. Cases (vi),(vii) are used for the plot function. Case (viii) shows an important general syntax which can handle any type of function. You simply type the expression you want, finishing with a semicolon, then after the semicolon indicate the variable, then give the range. Some examples should make this clear. The following list gives one example of each case (i) to (vii), then three examples of case (viii):

fzero(sin, 2,5)
fzero(sin, [2 5])
fzero(sin, [2 5], '', 1e-10)
fzero(poly, [1 1 -1], [1 4])        
fzero(poly, [1 1 -1], [1 4], 1e-10)
plot(sin, [1:10], 'r.')
plot(sin, 1,10, 'g,')
# case (viii):
fzero(x-cos x; x,0,2)
plot(sin(x^2); x,-3,3)
plot(lor([1 0.5 2],x) + 0.01 x^2; x,0,4)

4.6 More on user functions

User functions are defined either by using the ":=" symbol or by the keywords "function", ... "end". See the demonstration programs for examples.

In order to allow two or more functions to refer to one another, functions can be declared before they are defined. That is, a statement such as

funcdec myfunc(y, n:0)
declares that myfunc is a user function expecting either 1 or 2 arguments. The full definition can then be placed somewhere else.

Default values

You can provide default values for parameters using a colon, as in

f(t, tau:1) := exp(-t/tau);
In this example f(t) would be equivalent to f(t,1). For multiple default arguments, the rules are as in C++: once any given argument has a default value, all subsequent ones must also have default values. Only scalar default values are permitted.

Local vs. global.

Variables are declared by the first statement in which they are assigned a value. This is usually a straightforward assignment such as "x=2" but it could also be a for loop. Variables have to be declared before they can appear on the right hand side of expressions, or be indexed.

User functions have read-only access to global variables. For example

g = 2;

funnyfunc(y) := 
{  y *= g   # multiply y by the global variable g
   g = 4;   # define a local variable called g, give it the value 4
   y /= g;  # divide y by the local g
}
This is not good programming style! It is merely to illustrate the logic: the first statement in funnyfunc is valid because calqit can identify g on the right hand side as an already-defined global variable. At the second statement calqit knows that globals cannot be modified, but the statement is valid because it is a legitimate declaration of a new local variable. At the third statement both variables called g exist. The name clash is resolved by giving preference to the local variable.

If you want to modify global variables within user functions, you can: just declare them "global" at the first statement in the function:

g = 2;

funnyfunc(y) := 
{  global g; 
   y *= g   # multiply y by the global variable g
   g = 4;   # change the value of the global variable g to 4
   y /= g;  # divide y by g
}
You would normally have a single "global" declaration with a list of symbol names, but you can have more such statements as long as they come right at the start of the function definition.

Pass by reference.

By default parameters to user functions are passed by value. That is, a copy of the passed parameter is made, and this copy is manipulated by the function. Sometimes it can be useful to pass a parameter by reference. That is, the function acts directly on the passed variable, leaving it modified on exit. This offers an alternative way to allow the function to provide output. If poorly used this can reduce program readability, but when used with care it can enhance a program.

One usage is when you are passing large matrices around but don't need to do much with the matrix once it is passed: then you can save running time by passing a reference rather than forcing the code to prepare a copy of the matrix. For example:

traceabs_v(a) := sum( |diag a| );
traceabs_r(^a) := sum( |diag a| );

m=-5+irand(10, [1000,1000]);  # a large matrix
tic; traceabs_v(m); t1=toc; tic; traceabs_r(m); t2=toc;
t1,t2

You should find that both t1 and t2 are small here, but t2 is a lot less than t1. (Built in functions use pass by reference so the call to diag is fast in both cases).

[top] . [home]