Example
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"
.
2> L = length(Str).
4
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
.
4> L.
4
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()
.
6> f(L).
ok
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.
8> f(L).
ok
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
.
10> L.
4
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.
16> f().
ok
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.
51> halt().
strider 2>
Command 51 exits the Erlang runtime system.