Go to the previous, next section.
SM maintains a set of variables which are defined with the statement
DEFINE name value
DEFINE name { value_list 2
DEFINE name ( expression )
name
must consist of digits, letters and `_' (but must not start
with a digit), and may be a keyword.
Value
may be a word or a number. Value_list
has no such
restrictions
and may contain many words. Note that due to the presence of the {2,
variables are not expanded in value_list
,
whereas they are in value
. In fact, the list can be delimited by
<>
rather than {2
; see DEFINE
for details.
The expression in DEFINE variable ( expr )
should be
a scalar; if it is not, the first element of the vector will be used and
you will be warned, if VERBOSE
(@xref{VERBOSE}) is one or greater.
Sometimes you just want to evaluate an expression and treat the answer
as a string; in this case use the special vector form $(expr)
which is replaced by the value of the expression -- for example
echo e is $(exp(1))
.
Expressions are further discussed under `Vectors and Arithmetic'.
There are a number of special variables whose value is always the current
value of some internal SM variable such as the current position or the
point type. The variable "date" is also special and expands to give
the current time and date, -- try typing echo $date
. You can freeze
these variables at their current value by saying define name |
(see below).
Each time SM reads $name
it replaces it by its
value, considered as a character string. For example,
@br
DEFINE hi hello WRITE STANDARD $hiwill print
hello
. This expansion is done before even the lowest level
of lex analysis, so if a command is attempting to read a value
it is possible to give it the name of a SM variable. An example
would be the XLABEL
command, which writes a string as the x-axis label
of a graph,
@br
DEFINE name Aelfred
XLABEL My name is $namewill invoke the
XLABEL
command, and write My name is Aelfred
below
the x-axis. (Incidentally, DEFINE Aelfred Aethelstan YLABEL $$name
will write Aethelstan
as the y-axis label, which can be handy in macros.
The use of the double $$ indicates to SM to do a double
translation, as it first expands to $Aelfred
which then expands to
Aethelstan
).
A variable can be deleted by DEFINE name DELETE
so for example the macro
MACRO undef 1 { DEFINE $1 DELETE 2invoked as @br
undef namewill undefine the variable
name
(see the section on macros if you are
confused).
There are also three special values
, :
, |
, and
?
. The command define name :
means `get the
value of name from the environment file'. If this fails, and if the
variable is all uppercase, SM will then try to use the value of an
environment (VMS: logical) variable of the same name.
Using define name ?
means
`read the value of name from the keyboard'. You can specify a prompt to be
used, see DEFINE
for details.
The form with |
has changed a little with version 2.1.1. The variables
that you can use with |
have not changed, but their usage has
slightly. They are all defined for you when SM starts and each is always
correct, tracking the current value of the corresponding internal variable.
For example, try echo $angle angle 45 echo $angle
. If you now
say define angle |
, $angle
will cease to track the internal
value and will remain fixed (the same effect can be achieved with
define angle 45
). When you say define angle delete
it will
once more track the internal value. Your old code will continue to work,
but in many cases it is possible to remove the explicit definition
with |
. This special sort of variable will not be SAVE
d,
and will not show up if you list the currently defined variables.
A list of the |
variables is given in the section on DEFINE
.
So using the example `.sm' environment file listed in the previous
section of the manual, DEFINE name :
will define
name
to be Robert
, DEFINE angle |
will give the last
value set by the ANGLE
command, and DEFINE datafile ?
will ask you
for the value of `datafile', which can be useful in macros. For example,
@br
DEFINE noise ? { Ring bell? 2 IF('$noise' != 'n') { bell 2will execute the macro
bell
if you type anything but n in reply
to the question `Ring bell?'.
When writing macros, it is also sometimes useful to know if a variable
has been defined. The variable $?name
has the value 1 if name
is defined, otherwise it is 0. For instance, there is a line@br
define term : if($?term) { termtype $term 2in the startup file, to set a termtype if present in the environment file.
There are also commands to read the values of variables from data
files defined with the DATA
command.
DEFINE name READ i
DEFINE name READ i j
name
to be the i'th line of the file (or the j'th word
of the i'th line). An example is given in the section on `useful macros'.
You can read variables from the headers of binary files (specified
with the IMAGE
command) using
DEFINE name IMAGE
, although this is only supported for a limited
class of file_type
's (see section Two-Dimensional Graphics).
All currently defined variables may be listed with
LIST DEFINE [ begin end ]where the optional
begin
and end
define the range of variables
(alphabetically) to be listed. You might prefer to use the macro lsv
which won't appear on your history list.
Variables are usually not expanded within double quotes or { 2. If
for some reason you need to force expansion within double quotes, it can be
done with $!name
.
The macro `load' discussed under useful macros gives an
example of this mechanism. If you need to expand a variable, with no questions
asked (and even within {2), use $!!name
.
Sometimes you may want to terminate a variable name where SM doesn't
want to, and this can be done with a trick involving
double quotes. Say you are writing a macro to find all the stars redder
than B-V = 1.0 in a set of data vectors, and you want to rename them with
a trailing "_red", so star
goes to star_red
. So you
write a foreach loop,@br
FOREACH x ( U B V R I J K ) { SET $x_red = $x IF(B-V >1)2Well, that won't work because SM thinks that you are referring to a previously defined variable named
x_red
, so it will
complain that x_red
is not
defined. But if you write it as $x""_red
the ""
separate
the x
from the _red
until $x
is expanded,
and then disappear, and all is well. When a variable is read, SM
skips over all whitespace before the definition, and this can cause
problems if you hit ^C in the middle, as the rest of the command
will be thrown away. If you ever hit a ^C, and can't get a
prompt, try typing any non-whitespace character.
Variables are string-variables, and are not primarily designed for doing arithmetic (that's what vectors are for). This is a common source of confusion so let's consider some examples (at the risk of anticipating some later sections of the manual).
DEFINE a 10defines a variable
a
which consists of the two characters `1' and `2',
and which can be used anywhere -- for example
xlabel $a
. What about vectors? Consider
SET x=10which defines a single-element vector whose value is ten, ready to be used in expressions such as
SET y=$a + x*12Note that the
$a
is still just the two characters `1' and `0',
but in this context that is interpreted as the number ten. So what does
DEFINE y $a+x*12do? Well, actually it results in a syntax error (the `+' ends a word), so try
DEFINE y <$a+x*12>This defines the variable
y
as the string `10+x*12', it doesn't evaluate
the expression. You can evaluate the expression if you want with
DEFINE y ( $a+x*12 )which defines
y
as the string `130'. Incidently, you can sometimes get
away without an explicit variable with the syntax $($a+x*12)
which
also expands to the string `130'.
The fact that variables are simply strings can be used to build complex commands; consider for example the macro
readem # read multiple lines columns with names in row 1 READ ROW names 1.s DEFINE rc <$(names[(0)]) 1> DO i=2,DIMEN(names) { DEFINE rc <$rc $(names[($i - 1)]) $i> } LINES 2 0 READ < $rc >which reads the names of a set of columns from line 1, builds a command to read the data in the variable
rc
, and then reads all the data
in one command. You could of course loop through names
reading
each column in turn, but this should be a good deal faster.
Go to the previous, next section.