The following example is a long dialog with the shell. Commands
starting with > are inputs to the shell. All other lines
are output from the shell.
strider 1> erl
Erlang (BEAM) emulator version 5.3 [hipe] [threads:0]
Eshell V5.3 (abort with ^G)
1> Str = "abcd".
"abcd"
Command 1 sets variable Str to string "abcd".
Command 2 sets L to the length of string Str.
3> Descriptor = {L, list_to_atom(Str)}.
{4,abcd}
Command 3 builds the tuple Descriptor, evaluating the BIF
list_to_atom/1
.
Command 4 prints the value of variable L.
5> b().
Descriptor = {4,abcd}
L = 4
Str = "abcd"
ok
Command 5 evaluates the internal shell command b(), which
is an abbreviation of "bindings". This prints
the current shell variables and their bindings. ok at
the end is the return value of function b().
Command 6 evaluates the internal shell command f(L) (abbreviation
of "forget"). The value of variable L is removed.
7> b().
Descriptor = {4,abcd}
Str = "abcd"
ok
Command 7 prints the new bindings.
Command 8 has no effect, as L has no value.
9> {L, _} = Descriptor.
{4,abcd}
Command 9 performs a pattern matching operation on
Descriptor, binding a new value to L.
Command 10 prints the current value of L.
11> {P, Q, R} = Descriptor.
** exception error: no match of right hand side value {4,abcd}
Command 11 tries to match {P, Q, R} against
Descriptor, which is {4, abc}. The match fails and
none of the new variables become bound. The printout starting
with "** exception error:" is not the value of the
expression (the expression had no value because its evaluation
failed), but a warning printed by the system to inform
the user that an error has occurred. The values of the other
variables (L, Str, and so on) are unchanged.
12> P.
* 1:1: variable 'P' is unbound
13> Descriptor.
{4,abcd}
Commands 12 and 13 show that P is unbound because the
previous command failed, and that Descriptor has not
changed.
14>{P, Q} = Descriptor.
{4,abcd}
15> P.
4
Commands 14 and 15 show a correct match where P and
Q are bound.
Command 16 clears all bindings.
The next few commands assume that test1:demo(X) is
defined as follows:
demo(X) ->
put(aa, worked),
X = 1,
X + 10.
17> put(aa, hello).
undefined
18> get(aa).
hello
Commands 17 and 18 set and inspect the value of item
aa in the process dictionary.
19> Y = test1:demo(1).
11
Command 19 evaluates test1:demo(1). The evaluation
succeeds and the changes made in the process dictionary become
visible to the shell. The new value of dictionary item
aa can be seen in command 20.
20> get().
[{aa,worked}]
21> put(aa, hello).
worked
22> Z = test1:demo(2).
** exception error: no match of right hand side value 1
in function test1:demo/1
Commands 21 and 22 change the value of dictionary item
aa to hello and call test1:demo(2). Evaluation
fails and the changes made to the dictionary in
test1:demo(2), before the error occurred, are discarded.
23> Z.
* 1:1: variable 'Z' is unbound
24> get(aa).
hello
Commands 23 and 24 show that Z was not bound and that
dictionary item aa has retained its original value.
25> erase(), put(aa, hello).
undefined
26> spawn(test1, demo, [1]).
<0.57.0>
27> get(aa).
hello
Commands 25, 26, and 27 show the effect of evaluating
test1:demo(1) in the background. In this case, the
expression is evaluated in a newly spawned process. Any
changes made in the process dictionary are local to the newly
spawned process and therefore not visible to the shell.
28> io:format("hello hello\n").
hello hello
ok
29> e(28).
hello hello
ok
30> v(28).
ok
Commands 28, 29 and 30 use the history facilities of the shell.
Command 29 re-evaluates command 28. Command 30 uses the value (result)
of command 28. In the cases of a pure function (a function
with no side effects), the result is the same. For a function
with side effects, the result can be different.
The next few commands show some record manipulation. It is
assumed that ex.erl defines a record as follows:
-record(rec, {a, b = val()}).
val() ->
3.
31> c(ex).
{ok,ex}
32> rr(ex).
[rec]
Commands 31 and 32 compile file ex.erl and read
the record definitions in ex.beam. If the compiler did not
output any record definitions on the BEAM file, rr(ex)
tries to read record definitions from the source file instead.
33> rl(rec).
-record(rec,{a,b = val()}).
ok
Command 33 prints the definition of the record named
rec.
34> #rec{}.
** exception error: undefined shell command val/0
Command 34 tries to create a rec record, but fails
as function val/0 is undefined.
35> #rec{b = 3}.
#rec{a = undefined,b = 3}
Command 35 shows the workaround: explicitly assign values to record
fields that cannot otherwise be initialized.
36> rp(v(-1)).
#rec{a = undefined,b = 3}
ok
Command 36 prints the newly created record using record
definitions maintained by the shell.
37> rd(rec, {f = orddict:new()}).
rec
Command 37 defines a record directly in the shell. The
definition replaces the one read from file ex.beam.
38> #rec{}.
#rec{f = []}
ok
Command 38 creates a record using the new definition, and
prints the result.
39> rd(rec, {c}), A.
* 1:15: variable 'A' is unbound
40> #rec{}.
#rec{c = undefined}
ok
Command 39 and 40 show that record definitions are updated
as side effects. The evaluation of the command fails, but
the definition of rec has been carried out.
For the next command, it is assumed that test1:loop(N) is
defined as follows:
loop(N) ->
io:format("Hello Number: ~w~n", [N]),
loop(N+1).
41> test1:loop(0).
Hello Number: 0
Hello Number: 1
Hello Number: 2
Hello Number: 3
User switch command
--> i
--> c
.
.
.
Hello Number: 3374
Hello Number: 3375
Hello Number: 3376
Hello Number: 3377
Hello Number: 3378
** exception exit: killed
Command 41 evaluates test1:loop(0), which puts the
system into an infinite loop. At this point the user types
^G (Control G), which suspends output from the
current process,
which is stuck in a loop, and activates JCL mode. In JCL
mode the user can start and stop jobs.
In this particular case, command i ("interrupt")
terminates the looping program, and command c
connects to the shell again. As the process was
running in the background before we killed it, more
printouts occur before message "** exception exit: killed"
is shown.
42> E = ets:new(t, []).
#Ref<0.1662103692.2407923716.214192>
Command 42 creates an ETS table.
43> ets:insert({d,1,2}).
** exception error: undefined function ets:insert/1
Command 43 tries to insert a tuple into the ETS table, but the
first argument (the table) is missing. The exception kills the
evaluator process.
44> ets:insert(E, {d,1,2}).
** exception error: argument is of wrong type
in function ets:insert/2
called as ets:insert(16,{d,1,2})
Command 44 corrects the mistake, but the ETS table has been
destroyed as it was owned by the killed evaluator process.
45> f(E).
ok
46> catch_exception(true).
false
Command 46 sets the exception handling of the evaluator process
to true. The exception handling can also be set when
starting Erlang by erl -stdlib shell_catch_exception true.
47> E = ets:new(t, []).
#Ref<0.1662103692.2407923716.214197>
48> ets:insert({d,1,2}).
* exception error: undefined function ets:insert/1
Command 48 makes the same mistake as in command 43, but this time
the evaluator process lives on. The single star at the beginning
of the printout signals that the exception has been caught.
49> ets:insert(E, {d,1,2}).
true
Command 49 successfully inserts the tuple into the ETS table.
50> ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).
true
Command 50 inserts another tuple into the ETS table. This time
the first argument is the table identifier itself. The shell can
parse commands with pids (<0.60.0>), ports
(#Port<0.536>), references
(#Ref<0.1662103692.2407792644.214210>), and external
functions (#Fun<a.b.1>), but the command fails unless
the corresponding pid, port, reference, or function can be created
in the running system.
Command 51 exits the Erlang runtime system.