208 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			208 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | --- | ||
|  | title: Shell | ||
|  | --- | ||
|  | 
 | ||
|  | ## Shell
 | ||
|  | 
 | ||
|  | Erlang has a shell that can be use as an interpreter. | ||
|  | It can be used as an informal environment in which to try out and test Erlang expressions and simple scripts. | ||
|  | 
 | ||
|  | Note that the Erlang shell is the console for the Erlang virtual machine (known as BEAM). | ||
|  | It is console first, interpreter second and is in some respects awkward and in others limited. | ||
|  | 
 | ||
|  | #### More Information:
 | ||
|  | <!-- Please add any articles you think might be helpful to read before writing the article --> | ||
|  | 
 | ||
|  |   * [Learn You Some Erlang: Starting Out](https://learnyousomeerlang.com/starting-out) | ||
|  | 
 | ||
|  | 
 | ||
|  | ### Entering and Leaving the Shell
 | ||
|  | 
 | ||
|  | Once Erlang has been installed on your PC, the shell may be invoked from the command line terminal | ||
|  | by entering `erl`: | ||
|  | 
 | ||
|  | ```bash | ||
|  |     $ erl | ||
|  |     Erlang/OTP 19 [erts-8.1] [source-e7be63d] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false] | ||
|  | 
 | ||
|  |     Eshell V8.1  (abort with ^G) | ||
|  |     1> | ||
|  | ``` | ||
|  | 
 | ||
|  | To leave the shell again enter `q().` | ||
|  | 
 | ||
|  | ``` | ||
|  |     1> q(). | ||
|  |     ok | ||
|  |     2> $ | ||
|  | ``` | ||
|  | 
 | ||
|  | There may be a short pause before the command line prompt appears. | ||
|  | If you are in a hurry you may use ^G followed by q (lower case). | ||
|  | Entering ^C twice will also exit the Erlang shell abruptly. | ||
|  | 
 | ||
|  | Note `q().` with a full-stop at the end. | ||
|  | The full-stop is a hangover from the early days of Erlang when it ran on top of a Prolog interpreter. | ||
|  | 
 | ||
|  | The full-stop is required.  This may take some getting used to. | ||
|  | If you type in a command and get no response after a second or two, | ||
|  | check that you entered the full-stop. | ||
|  | If not, enter the full-stop and press the carriage return or enter key again. | ||
|  | 
 | ||
|  | ### Use of the Shell
 | ||
|  | 
 | ||
|  | The shell will evaluate Erlang expression and print the result (don't forget the full-stop): | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     2> (1 + 1) * 16 . | ||
|  |     32 | ||
|  |     3> | ||
|  | ``` | ||
|  | 
 | ||
|  | You can bind a value to a variable: | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     3> Joe = 6 . | ||
|  |     6 | ||
|  |     4> | ||
|  | ``` | ||
|  | 
 | ||
|  | You cannot simply bind a new value to a variable | ||
|  | (variables are immutable in the shell too): | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     4> Joe = 8 . | ||
|  |     ** exception error: no match of right hand side value 8 | ||
|  |     5> | ||
|  | ``` | ||
|  | 
 | ||
|  | However, the shell has a special function that allows you to unbind a variable. | ||
|  | Then it can be bound once more. | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     5> f(Joe) . | ||
|  |     ok | ||
|  |     6> Joe = 8 . | ||
|  |     8 | ||
|  |     7> | ||
|  | ``` | ||
|  | 
 | ||
|  | There are a number of functions specific to the shell (not available to Erlang scripts and programs). | ||
|  | For a list, enter `help().` | ||
|  | For a history of what you have entered so far, use `h().`. | ||
|  | 
 | ||
|  | You may call BIFs (built in functions): | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     8> Pi = 3.14 . | ||
|  |     3.14 | ||
|  |     9> is_integer(Pi) . | ||
|  |     false | ||
|  |     10> | ||
|  | ``` | ||
|  | 
 | ||
|  | Most of the Erlang runtime support is already loaded but you will need to use the _module:function_ syntax to invoke them: | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     11> List = ["one", "two", "three"] . | ||
|  |     ["one","two","three"] | ||
|  |     12> lists:reverse(List) . | ||
|  |     ["three","two","one"] | ||
|  | ``` | ||
|  | 
 | ||
|  | To find out which modules are loaded, enter `m().` | ||
|  | 
 | ||
|  | All functions in Erlang belong to a module. | ||
|  | This is part of the reason why you cannot define functions in the shell. | ||
|  | 
 | ||
|  | You can, however, define lambda functions and bind them to variable names: | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     12> AddTen = fun(X) -> X + 10 end . | ||
|  |     #Fun<erl_eval.6.52032458> | ||
|  |     13> AddTen(1) . | ||
|  |     11 | ||
|  |     14> | ||
|  | ``` | ||
|  | 
 | ||
|  | This is not really suitable for anything but the most trivial functions. | ||
|  | See next for anything larger. | ||
|  | 
 | ||
|  | ### How Run and Test Simple Functions using the Shell
 | ||
|  | 
 | ||
|  | The notes in this section show how to use the shell to run and test single functions | ||
|  | without going to the lengths of setting up a proper test harness. | ||
|  | 
 | ||
|  | Suppose you have been asked to write a function that takes a year number as its parameter and | ||
|  | returns true if the number represents a leap year, false otherwise. | ||
|  | 
 | ||
|  | Suppose your solution is in the file _leap.erl_ and looks a lot like: | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     -module(leap). | ||
|  | 
 | ||
|  |     -export([leap_year/1]). | ||
|  | 
 | ||
|  |     year(Year) -> | ||
|  |         case Year of | ||
|  |             _ when Year rem 400 == 0 -> | ||
|  |                 true; | ||
|  |             _ when Year rem 100 == 0 -> | ||
|  |                 false; | ||
|  |             _ when Year rem 4 == 0 -> | ||
|  |                 true; | ||
|  |             _ -> | ||
|  |                 false | ||
|  |         end. | ||
|  | ``` | ||
|  | 
 | ||
|  | The problem now is how to test the solution. | ||
|  | 
 | ||
|  | First you need to be 'in the right directory' (or folder if you prefer): | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     % what directory am I in ? | ||
|  |     14> pwd(). | ||
|  |     /home/fcc/guides/erlang/shell | ||
|  | 
 | ||
|  |     % is the source file in here ? | ||
|  |     15> ls(). | ||
|  |     index.md | ||
|  | 
 | ||
|  |     % guess not - is in an adjacent directory ? | ||
|  |     16> ls("../examples"). | ||
|  |     leap.erl | ||
|  | 
 | ||
|  |     % good - change directory: | ||
|  |     17> cd("../examples"). | ||
|  | ``` | ||
|  | 
 | ||
|  | Now compile and load the module leap (one command): | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     18> c(leap). | ||
|  |     {ok,leap} | ||
|  | ``` | ||
|  | 
 | ||
|  | Now test the function by simply calling it with suitable values: | ||
|  | 
 | ||
|  | ```erlang | ||
|  |     19> leap:year(2018). | ||
|  |     false | ||
|  |     20> leap:year(2020). | ||
|  |     true | ||
|  |     21> leap:year(1066). | ||
|  |     false | ||
|  |     22> leap:year(2000). | ||
|  |     true | ||
|  |     23> leap:year(1100). | ||
|  |     false | ||
|  |     24> | ||
|  | ``` | ||
|  | 
 | ||
|  | If you decide the function does not work, edit and save the source file, | ||
|  | compile and load the module again and test. | ||
|  | Repeat until satisfied. | ||
|  | 
 | ||
|  | <!-- EOF --> |