summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam Bard <github@adambard.com>2013-07-01 08:44:06 -0700
committerAdam Bard <github@adambard.com>2013-07-01 08:44:06 -0700
commit85ec26c3f884c2c13021676f7b2a36ac17925178 (patch)
treef746cfcec89c6355bf2bb7d5d042606f5ee814e8
parent75d86ed0dd78e9c60c777e1ef98d681c251464b7 (diff)
parent1ee6d1b17cbf417adb24db393586f36ab904099a (diff)
Merge pull request #75 from potomak/master
Learn Erlang in Y minutes
-rw-r--r--erlang.html.markdown239
1 files changed, 239 insertions, 0 deletions
diff --git a/erlang.html.markdown b/erlang.html.markdown
new file mode 100644
index 00000000..6ceb3172
--- /dev/null
+++ b/erlang.html.markdown
@@ -0,0 +1,239 @@
+---
+language: erlang
+author: Giovanni Cappellotto
+author_url: http://www.focustheweb.com/
+filename: learnerlang.erl
+---
+
+```erlang
+% Percent sign start a one-line comment.
+
+%% Two percent characters shall be used to comment functions.
+
+%%% Three percent characters shall be used to comment modules.
+
+% We use three types of punctuation in Erlang.
+% Commas (`,`) separate arguments in function calls, data constructors, and
+% patterns.
+% Periods (`.`) (followed by whitespace) separate entire functions and
+% expressions in the shell.
+% Semicolons (`;`) separate clauses. We find clauses in several contexts: in kn
+% function definitions and in `case`, `if`, `try..catch` and `receive`
+% expressions.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 1. Variables and pattern matching.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Num = 42. % All variable names must start with an uppercase letter.
+% Erlang has single assignment variables, if you try to assign a different value
+% to the variable `Num`, you’ll get an error.
+
+% In most languages, `=` denotes an assignment statement. In Erlang, however,
+% `=` denotes a pattern matching operation. `Lhs = Rhs` really means this:
+% evaluate the right side (Rhs), and then match the result against the pattern
+% on the left side (Lhs).
+Num = 7 * 6.
+
+% Floating point number.
+Pi = 3.14159.
+
+% Atoms, are used to represent different non-numerical constant values. Atoms
+% start with lowercase letters, followed by a sequence of alphanumeric
+% characters or the underscore (`_`) or at (`@`) sign.
+Hello = hello.
+
+% Tuples are similar to structs in C.
+Point = {point, 10, 45}.
+
+% If we want to extract some values from a tuple, we use the pattern matching
+% operator `=`.
+{point, X, Y} = Point. % X = 10, Y = 45
+
+% We can use `_` as a placeholder for variables that we’re not interested in.
+% The symbol `_` is called an anonymous variable. Unlike regular variables,
+% several occurrences of _ in the same pattern don’t have to bind to the same
+% value.
+Person = {person, {name, {first, joe}, {last, armstrong}}, {footsize, 42}}.
+{_, {_, {_, Who}, _}, _} = Person. % Who = joe
+
+% We create a list by enclosing the list elements in square brackets and
+% separating them with commas.
+% The individual elements of a list can be of any type.
+% The first element of a list the head of the list. If you imagine removing the
+% head from the list, what’s left is called the tail of the list.
+ThingsToBuy = [{apples, 10}, {pears, 6}, {milk, 3}].
+
+% If `T` is a list, then `[H|T]` is also a list, with head H and tail T.
+% The vertical bar (`|`) separates the head of a list from its tail.
+% `[]` is the empty list.
+% We can extract elements from a list with a pattern matching operation. If we
+% have the nonempty list `L`, then the expression `[X|Y] = L`, where `X` and `Y`
+% are unbound variables, will extract the head of the list into `X` and the tail
+% of the list into `Y`.
+[FirstThing|OtherThingsToBuy] = ThingsToBuy.
+% FirstThing = {apples, 10}
+% OtherThingsToBuy = {pears, 6}, {milk, 3}
+
+% There are no strings in Erlang. Strings are really just lists of integers.
+% Strings are enclosed in double quotation marks (`"`).
+Name = "Hello".
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 2. Sequential programming.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Modules are the basic unit of code in Erlang. All the functions we write are
+% stored in modules. Modules are stored in files with `.erl` extensions.
+% Modules must be compiled before the code can be run. A compiled module has the
+% extension `.beam`.
+-module(geometry).
+-export([area/1]).
+
+% The function area consists of two clauses. The clauses are separated by a
+% semicolon, and the final clause is terminated by dot-whitespace.
+% Each clause has a head and a body; the head consists of a function name
+% followed by a pattern (in parentheses), and the body consists of a sequence of
+% expressions, which are evaluated if the pattern in the head is successfully
+% matched against the calling arguments. The patterns are matched in the order
+% they appear in the function definition.
+area({rectangle, Width, Ht}) -> Width * Ht;
+area({circle, R}) -> 3.14159 * R * R.
+
+% Compile the code in the file geometry.erl.
+c(geometry). % {ok,geometry}
+
+% We need to include the module name together with the function name in order to
+% identify exactly which function we want to call.
+geometry:area({rectangle, 10, 5}). % 50
+geometry:area({circle, 1.4}). % 6.15752
+
+% In Erlang, two functions with the same name and different arity in the same
+% module represent entirely different functions.
+-module(lib_misc).
+-export([sum/1]).
+sum(L) -> sum(L, 0).
+sum([], N) -> N;
+sum([H|T], N) -> sum(T, H+N).
+
+% Funs are "anonymous" functions. They are called this because they have no
+% name.
+Double = fun(X) -> 2*X end.
+Double(2). % 4
+
+% Functions accept funs as their arguments and can return funs.
+Mult = fun(Times) -> ( fun(X) -> X * Times end ) end.
+Triple = Mult(3).
+Triple(5). % 15
+
+% List comprehensions are expressions that create lists without having to use
+% funs, maps, or filters.
+% The notation `[F(X) || X <- L]` means "the list of `F(X)` where `X` is taken
+% from the list `L`."
+L = [1,2,3,4,5].
+[2*X || X <- L]. % [2,4,6,8,10]
+
+% Guards are constructs that we can use to increase the power of pattern
+% matching. Using guards, we can perform simple tests and comparisons on the
+% variables in a pattern.
+% You can use guards in the heads of function definitions where they are
+% introduced by the `when` keyword, or you can use them at any place in the
+% language where an expression is allowed.
+max(X, Y) when X > Y -> X;
+max(X, Y) -> Y.
+
+% A guard is a series of guard expressions, separated by commas (`,`).
+% The guard `GuardExpr1, GuardExpr2, ..., GuardExprN` is true if all the guard
+% expressions `GuardExpr1, GuardExpr2, ...` evaluate to true.
+is_cat(A) when is_atom(A), A =:= cat -> true;
+is_cat(A) -> false.
+is_dog(A) when is_atom(A), A =:= dog -> true;
+is_dog(A) -> false.
+
+% A `guard sequence` is either a single guard or a series of guards, separated
+%by semicolons (`;`). The guard sequence `G1; G2; ...; Gn` is true if at least
+% one of the guards `G1, G2, ...` evaluates to true.
+is_pet(A) when is_dog(A); is_cat(A) -> true;
+is_pet(A) -> false.
+
+% Records provide a method for associating a name with a particular element in a
+% tuple.
+% Record definitions can be included in Erlang source code files or put in files
+% with the extension `.hrl`, which are then included by Erlang source code
+% files.
+-record(todo, {
+ status = reminder, % Default value
+ who = joe,
+ text
+}).
+
+% We have to read the record definitions into the shell before we can define a
+% record. We use the shell function `rr` (short for read records) to do this.
+rr("records.hrl"). % [todo]
+
+% Creating and updating records:
+X = #todo{}.
+% #todo{status = reminder, who = joe, text = undefined}
+X1 = #todo{status = urgent, text = "Fix errata in book"}.
+% #todo{status = urgent, who = joe, text = "Fix errata in book"}
+X2 = X1#todo{status = done}.
+% #todo{status = done,who = joe,text = "Fix errata in book"}
+
+% `case` expressions.
+% `filter` returns a list of all those elements `X` in `L` for which `P(X)` is
+% true.
+filter(P, [H|T]) ->
+ case P(H) of
+ true -> [H|filter(P, T)];
+ false -> filter(P, T)
+ end;
+filter(P, []) -> [].
+
+% `if` expressions.
+max(X, Y) ->
+ if
+ X > Y -> X;
+ X < Y -> Y;
+ true -> nil;
+ end.
+
+% Warning: at least one of the guards in the if expression must evaluate to true;
+% otherwise, an exception will be raised.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 3. Exceptions.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Exceptions are raised by the system when internal errors are encountered or
+% explicitly in code by calling `throw(Exception)`, `exit(Exception)` or
+% `erlang:error(Exception)`.
+generate_exception(1) -> a;
+generate_exception(2) -> throw(a);
+generate_exception(3) -> exit(a);
+generate_exception(4) -> {'EXIT', a};
+generate_exception(5) -> erlang:error(a).
+
+% Erlang has two methods of catching an exception. One is to enclose the call to
+% the function, which raised the exception within a `try...catch` expression.
+catcher(N) ->
+ try generate_exception(N) of
+ Val -> {N, normal, Val}
+ catch
+ throw:X -> {N, caught, thrown, X};
+ exit:X -> {N, caught, exited, X};
+ error:X -> {N, caught, error, X}
+ end.
+
+% The other is to enclose the call in a `catch` expression. When you catch an
+% exception, it is converted into a tuple that describes the error.
+catcher(N) -> catch generate_exception(N).
+
+```
+
+## References
+
+* "Programming Erlang: Software for a Concurrent World" by Joe Armstrong
+* [Erlang - Programming Rules and Conventions](http://www.erlang.se/doc/programming_rules.shtml)
+* [Erlang/OTP Documentation](http://www.erlang.org/doc/) \ No newline at end of file