Erlang sequential programming

Erlang has forms of conditional evaluation computations, which are interchangeable:

1. The function is selected and executed by pattern matching through the parameters of the function.

2.case structure.

2.1. The case structure relies on pattern matching to determine which statements should be executed, which is very similar to selecting functions to execute through pattern matching. The difference is that instead of pattern matching the actual and formal parameters of the function, case evaluates an expression and then matches its result against a semicolon-separated list of pattern matches.

2.2. In general, case expressions have the following forms:

case conditional-expression of

Pattern1->expression1,expression2,...;

Pattern2->expression1,expression2,...;

...;

Patternn->expression1,expression2,...;

end;

The keywords used are case, of, and end, the conditional-expression is evaluated, and then Pattern1,...,Patternn are matched until the first pattern matches successfully. The -> symbol separates the pattern or head of the statement from the body consisting of a comma-separated list of expressions. Once the pattern is matched, the selected statement expressions are executed one by one in order, and the result of the case structure is the last expression. result of the operation.

2.3. A case expression always returns a value, so it is always possible to bind its return value to a variable.

2.4. The result of a case expression must match a pattern, otherwise you will get a runtime error. If there is _ or an unbound variable in the final pattern, then it will match any Erlang entry.

2.5. A function with one parameter can be directly rewritten using case; a function with multiple parameters can pattern-match all parameters at the same time; a case expression can match a single expression, and can use a structure constructed with multiple parameters. Tuple; pattern matching can match two arguments via nested case expressions.

2.6. Defining functions using pattern matching is more compact than using case expressions, but remember that case expressions are not just for headers, they can be used anywhere in a function definition.

3.if structure.

3.1. The if structure is like a case statement without the condition-expression and of keywords:

if

Guard1->expression1,expression2,...;

Guard2->expression1,expression2,...;

...;

Guardn->expression1,expression2,...;

end

The guard meta-expressions Guard1,Guard2,...,Guardn are evaluated in order until one of them evaluates to true.

3.2. Guarded metaexpressions are a subset of Boolean expression statements in Erlang that can only call a limited set of functions containing comparison and arithmetic operators.

3.3. If the unprotected meta-statement evaluates to the primitive true, then an error is generated at runtime. To get a catch-all statement, the value of the last guard meta-statement can be the primitive true, although this is not mandatory.

variable scope

1. The scope of a variable refers to the area in the program where the variable can be used.

2. The scope of a variable in Erlang is any position in the same function after the variable is bound.

protection element

1. A guard element is an additional restriction that applies to a function's case or receive statement. The guard element should be placed before "->" to separate the body and head of the statement.

2. A guard element consists of the when keyword followed by a guard element expression. This statement will only execute if the pattern match and guard meta-expression evaluates to the primitive true.

3. If pattern matching and guards work together to uniquely determine which statements should be checked, then the order of those statements becomes irrelevant.

4. Individual guard meta-expressions can be obtained using the following structure:

Constraint variables

Data values ​​of Erlang constants, including numbers, primitives, tuples and lists, etc.

Type test statements, such as is_binary, is_atom, is_boolean and is_tuple, etc.

The term comparison operators ==, =/=, <, >, etc. listed in Chapter 2.

Arithmetic expressions using arithmetic operators as listed in Chapter 2.

Boolean expressions listed in Chapter 2.

Protects meta built-in functions.

Guard meta-subexpressions that cause a runtime error are treated as returning false.

5. The reason developers cannot implement their own guard meta-functions with statements is to limit their operations, thus ensuring that guard meta-statements do not have boundary effects. All test guard meta-statements will be executed until a successful statement execution is found, which means that assuming io:format is called in a guard meta, if it fails, it will still see the printout, even if the statement doesn't selected for execution.

6.Erlang allows simple logical combination of guard elements, implemented in different ways:

Separate guard meta-statements with commas (,), which is a logical multiplication because it only evaluates to true if all expressions in the serial sequence evaluate to true.

Separate guard meta-statements with a semicolon (;), which is a logical addition that evaluates to true if an expression evaluates to true.

7. A simple combination of commas or semicolons is beautiful. In practice, we do not recommend mixing commas and semicolons, because it is too easy to make logical errors.

built-in function

1. The shorthand for built-in functions is BIF.

2. Built-in functions are usually written in C language and integrated into a virtual machine (VM), which can be used to operate, inspect and obtain data, and interact with the operating system.

3. Initially, all built-in functions belonged to erlang modules, but in reality, some of them are also implemented in other modules because of practicality and effectiveness. Among the modules that contain built-in functions are ets and lists.

4. While most built-in functions are considered internal parts of Erlang, others depend on different virtual machine implementations, and they do not necessarily exist in other virtual machine implementations, or in a specific OS version of an existing virtual machine . Standard built-in functions are automatically included, so calling them does not require a module prefix. But non-standard built-in functions must be prefixed with the erlang module, such as erlang:function.

Built-in functions - object access and inspection

1.hd/1: Returns the first element of the list.

2.tl/1: Return the rest after removing the first element.

3.length/1: Returns the length of a list.

4.tuple_size/1: Returns the number of tuple elements.

5.element/2: Returns the nth element of the tuple.

6.selelement/3: Replace an element in a tuple and return a new tuple.

7.erlang:append_element/2: Add an element to the tuple as the last element.

Built-in function - type conversion

1. Type conversions must be built-in functions because they change the internal representation of data. Even if it were possible, it would be impossible to write efficient conversion functions in Erlang. There are many type conversion functions, which not only change numeric types, but also convert between primitive types and printable types (ie, strings) at the same time.

2.atom_to_list/1, list_to_atom/1, list_to_existing_atom/1: They implement the mutual conversion of primitives and strings. If the primitives are not used in the current session in the runtime system, then calling the function list_to_existing_atom/1 will fail.

3.list_to_tuple/1, tuple_to_list/1: These two functions implement mutual conversion between tuple type and list type.

4.float/1, list_to_float/1: These two functions both generate a float type, one is to convert an integer parameter to a floating-point number, and the other is to convert a string to a floating-point number.

5.float_to_list/1, integer_to_list/1: Both functions return strings.

6.round/1, trunc/1, list_to_integer/1, they all return integers.

Built-in function - process dictionary

1. There is a class of built-in functions that allow a function to associate a value with a key and store it, which can later be retrieved elsewhere in the program, they become process dictionaries. Unfortunately, retrieving and manipulating these values ​​will introduce global variables in Erlang.

2. Using a process dictionary can provide a quick way to program, but the result is that the code is very difficult to debug and maintain. Most Erlang functions are free of edge effects, and when the program crashes, the arguments passed to the function usually contain enough information to resolve the error. The introduction of the process dictionary often complicates the process, because when the program crashes, the state value of the process dictionary is also lost.

Built-in functions - metaprogramming

1. Metaprogramming refers to the writing of certain kinds of computer programs that write or manipulate other programs (or themselves) as their data, or do some work at runtime that should be done at compile time. The ability of a function to determine which functions to call at runtime is called metaprogramming, where a program creates a program and runs it.

2. It can be implemented using the apply/3 function with three parameters, namely the module name, the exported function name and the parameter list. When called, it executes the function whose name is given by the argument and returns its result.

The beauty of 3.apply/3 is that modules, functions and parameters don't have to be known at compile time.

Built-in functions - process, port, publish and system info

1. date/0: Returns the current date in the form of a tuple {Year, Month, Day}.

2.time/0: Returns the current time in the form of a tuple {Hour, Minute, Second}.

3.now/0: Returns the number of seconds since midnight on January 1, 1970 as a tuple {MegaSeconds, Seconds, MicroSeconds}.

4.now/1: will return the unique value at a particular Erlang node, even if they are called multiple times in the same subtlety, so it can be used as a unique identifier.

Built-in functions - input and output

1. The io module provides the input and output functions of Erlang programs. It includes the main functions of reading from the standard input device and outputting to the standard output device. Each function can accept a file handle (of type io_device() ) as an additional first argument: define file operations in the file module.

2. To read a line from standard input, there are three ways:

2.1. Use io:get_line/1, which takes a prompt string (or primitive) as its input:

io:get_line("gissa_line>").

gissa_line>lksd.

"lksd.\n"

2.2. Use io:get_chars/2 to read the specified number of characters:

io:get_chars("tell me>",2).

tell me> er

"he"

2.3. Use io:read/1, which reads an Erlang item from standard input:

io:read("ok,then>").

ok,then>atom.

{ok,atom}

io:read("ok,then>").

ok,then>{2,tue,{mon,"weds"}}.

{ok,{2,tue,{mon,"weds"}}}

io:read("ok,then").

ok,then>2+3.

{error,{1,erl_parse,"bad term"}}

The term element is an evaluated value, not an arbitrary Erlang expression, such as 2+3.

3. To output from the standard output device, there are two methods:

3.1. Provided by io:write/1, which prints an Erlang entry.

3.2. Provided by io:format/2, this will print a formatted item, io:format can have:

A formatted string or binary that controls the formatting of the argument.

A list of values ​​to print.

3.3. The format string contains the required typographical characters and a sequence that controls the formatting. The control sequence begins with a tilde (~), which in its simplest form is a single character.

~c: Output the ASCII code of a character.

~f: Output a floating point number with 6 decimal places.

~e: Output a floating-point number with a total of 6 bits in scientific notation.

~w: Output any item in standard syntax.

~p: Output data like ~w, but in pretty printing mode, wrap and indent where appropriate, and output lists as strings when possible.

~W, ~P: The output is like ~w, ~p, but the structure depth is limited to 3, and it has an additional parameter in the data list to indicate the maximum depth of the printed item.

~B: Output an integer in base 10.

The complete control sequence is of the form ~FPPadC. Where F is the output width parameter of the field, P is its precision, Pad is the padding character, and C is the control character. For example, io:format("the sum of ~W is ~8.2.af.~n",[List,3,Sum]), parse it: ~8.2.af: This parameter has a total of 8 bits in the format , in which there are two digits after the decimal point, if it is less than 8 digits, it is filled with a, and f is the preceding control character.

recursion

1. The best solution to a programming problem is a tried-and-true strategy Breaking the problem down into a series of smaller problems, connecting the solutions to a few simple problems, can solve an unexpectedly large problem.

2. The condition that terminates the recursive call is called a base case.

recursion - tail recursive function

There are two types of recursion:

Direct recursion: This is a more direct method of calling.

Tail recursion: A function f is tail recursive as long as the call of the function f occurs in the last expression of the function body of f.

runtime error

1. Erlang runtime errors are exceptions thrown by the system.

2. The reason for the error

2.1.function_clause: It will be returned when none of the existing function patterns match the calling function. This error usually occurs in the following two situations: either you forgot a condition in the conditional analysis, or accidentally used the error parameters to call the function. E.g:

factorial(N) when N > 0->N*factorial(N-1);

factorial(0)->1.

test:factorial(-1).: Report an error.

2.2.case_clause: It is returned when there is no match with an existing pattern in the case structure, the most common reason for this is that you have forgotten one or more possible cases. E.g:

test1(N)->

case N of

-1->false;

1->true

end.

test:test1(0).: Report an error.

2.3.if_clause: It is returned when no existing expression in the if structure evaluates to true. This is a simplified case structure. The error is usually due to a missing pattern.

test2(N)->

if

N<0->false;

N>0->true

end.

test:test2(0).: Report an error.

2.4.badmatch: The error occurs when the pattern match fails and there is no other statement to choose from. It's hard to find a single cause for badmatch exceptions, but often the cause is that you inadvertently try to bind a variable that is already bound, for example:

N=45.

45

{N,M}={23,45}.: An error is reported, 23 cannot be bound to N because N is already bound to 45.

Another common reason is that you are getting partial results from a match in a function call. For example, in a list of tuples, it is common to use the library function lists:keysearch/3 to search for tuples. When successful, it returns a tuple {value, Tuple}, where Tuple is the tuple to be searched. The function is now called in the following way:

lists:keysearch(1,1,[{1,2},{2,4}]).

{value,{1,2}}

lists:keysearch(3,1,[{1,2},{2,4}]).

false

{value,Tuple}=lists:keysearch(3,1,[{1,2},{2,4}]).: false because we want to use the retrieved tuple immediately, but when no match is found with When a tuple of keywords is used, the function returns false, resulting in a badmatch.

2.5.badarg: It will be returned when a built-in function is called with a wrong parameter, for example:

length(helloWorld).: length expects a list, but is called with a primitive.

2.6.undef: It is returned when a global function that is not defined or exported is called. This exception is often caused by misspelling the function name, or calling the function without adding the module name before the function call.

2.7. badarith: It is returned when an arithmetic operation takes an inappropriate argument, such as a non-integer, floating-point number, or attempting to divide by 0.

handle errors

1. When a runtime error occurs while executing an expression, you may want to catch the exception and prevent the thread of execution from being terminated. Also, you might want to disable it and let another part of the system handle recovery.

2. Methods of handling errors:

2.1. Using try...catch

2.1.1. The idea behind the try...catch structure is to evaluate an expression and provide methods for handling the normal result of the expression as well as abnormal termination. More importantly, this result allows you to distinguish between the different return values ​​thrown by Erlang's different exception result handling mechanisms, and handle them differently.

Before the expression is evaluated, you insert the keyword try. In case statements you pattern match (normal) results, but instead of terminating the statement immediately with end, you use catch statements to handle exceptions, which include an exception type (also called a class) and the exception pattern in its header, There is also a corresponding return expression.

The try...catch construct has the following form:

try Exprs of

Pattern1[when Guard1]->

ExpressionBody1;

Pattern2[when Guard2]->

ExpressionBody2;

catch

[Class1:]ExpressionPattern1

[when ExceptionGuardSeq1]->

ExpressionBody1;

[ClassN:]ExpressionPatternN

[when ExceptionGuardSeqN]->

ExpressionBodyN;

In try...catch, you can use the throw/1 built-in function to invoke a non-local access. Through the call stack, the try...catch expression returns the return value passed to the throw expression.

Throw should be avoided because returning it as a non-local will make your code hard to trace and debug.

2.1.2. Error type:

error: This is the main type of error, error can also be triggered by calling the built-in function erlang:error(Term).

throw: This is a class that is generated by explicitly calling throw to throw an exception. The try...catch expression will catch it. Throw is not recommended in Erlang because it greatly increases the difficulty of understanding the program.

exit: This can be triggered by calling the exit/1 built-in function, which includes a reason for termination, and exits can also be generated by an exit signal.

2.1.3. Wildcards can be used in try...catch, if not matching the return value pattern, you can omit of.

2.2. Using catch

2.2.1. The catch expression allows you to catch runtime errors that occur. Its format is "catch expression", if the expression evaluates correctly, it returns the value of the expression, but if a runtime error occurs, it returns the tuple {'EXIT', Error}, where Error contains the runtime error message.

2.2.2. Precedence in Erlang is sometimes counterintuitive. If you bind the return value of an expression in a catch, you need to wrap the catch expression in parentheses, giving it higher precedence than the assignment. If you don't do this, the compiler will return a syntax error such as:

catch 1/0.

{'EXIT',{badarith,[{erlang,'/',[1,0]},

     {erl_eval,do_apply,5},

     {erl_eval,expr,5},

     {shell,exprs,6},

     {shell,eval_exprs,6},

     {shell,eval_loop,3}]}}

X=catch 1/0.

syntax error before:'catch'

X=(catch 1/0).

{'EXIT',{badarith,[{erlang,'/',[1,0]},

     {erl_eval,do_apply,5},

     {erl_eval,expr,5},

     {shell,exprs,6},

     {shell,eval_exprs,6},

                                                  {shell,eval_loop,3}]}}

Another problem with 2.2.3.catch is that it does not distinguish the semantics of runtime errors, whether it is thrown, exited, or the return value of a function, it treats it the same, it has no way to determine {'EXIT',Error} How is it returned, it may be the result of an error when executing the call encapsulated in the catch throw {'EXIT', Error}: or the result of a runtime error; or the result of calling the built-in function exit/1, Or just an expression that returned the tuple {'EXIT',Error}.

module library

1. Document access address

By visiting file://<erl_root_dir>//doc/index.html.

In windows, shortcuts to open documents are included in the Erlang/OTP installation directory under the Program Files menu.

On unix systems, the "erl-man" command is a convenient way to access the manual.

2. The menu on the left side of the document

Above the menu on the left side of the document are the following links:

Glossary:

Commonly used in Erlang belongs to the list.

Modules:

An alphabetical list of modules included in the Erlang release. Each module is accompanied by web documentation. This includes both Erlang and erl modules. Many modules have appropriate descriptive titles. A search for this page in a browser will bring up You find the desired function page.

Index:

A permuted index of Erlang/OTP functions and commands, browser search again comes in handy here, providing you with links to related modules once you find something of interest.

3. Useful modules

3.1.array

The array module contains a functional abstract data type for extensible arrays. They can have a fixed size or be as large as needed. This module contains functions for setting and checking values, and defining recursion based on these.

3.2.calendar

The calendar module provides functions to retrieve local and global times and to provide day, date and time conversions. The time interval can be calculated, and the time unit can be from day to microsecond. The calendar module is based on the Gregorian calendar and the built-in function now/0.

3.3.dict

The dict module is a simple key-value dictionary that can store, retrieve and delete elements, merge dictionaries and iterate over them.

3.4.erlang

All built-in functions are considered to be implemented in erlang modules. The man page for this module lists all Erlang built-in functions, which are different in different virtual machines, so some virtual machines are automatically imported and some are not.

3.5.file

The file module provides an interface to the file system, enabling reading, manipulation, and deletion of files.

3.6.filename

The filename module allows you to write common file manipulation and inspection functions, regardless of their symbolic representation of the file in the underlying operating system.

3.7.io

The io library module encapsulates the interface functions of standard I/O services, which allow you to read and write strings to I/O devices, including standard devices of course.

3.8.lists

List manipulation is undoubtedly the most used library module of all major Erlang systems, providing functions for inspecting, manipulating, and manipulating lists.

3.9.math

All standard math functions, including pi/0, sin/1, cos/1 and tan/1 are implemented in the math library module.

3.10.queue

The queue module implements an abstract data type for FIFO queues.

3.11.random

The random module gives a pseudo-random number generator based on a supplied seed.

3.12.string

The string module contains an array of string manipulation functions. Unlike the list module, it takes into account the fact that the content of the list module is actually ASCII.

3.13.timer

The timer module contains time-related functions, which include generating time and converting different time formats to milliseconds, which is the main time unit used in this module.

Debugger

1. A debugger in Erlang is a graphical tool that provides mechanisms for debugging ordered code and altering program execution. It allows the user to view and manipulate variables while running the program step by step. You can set breakpoints to stop execution and examine the recursion stack and variable bindings at various levels.

2. Use debugger:start(). to start the debugger, and a monitor window will appear, which displays a list of trace compiled modules, attached (traced) processes, and other debugging-related settings.

3. Trace a module and compile it with the debug_info flag.

Compile under unix system:

erlc +debug_info Module.erl.

Compile under windows system:

c(Module,[dubug_info]).

compile:file(exception,[debug_info]).

4. Then select the module in the debugger by opening the explain dialog in the module menu. The modules compiled with trace and the modules compiled without trace will be listed together in this window. The module you want to trace on a single machine, and then in its A * appears next to it. Just start executing a process under the trace module, an entry will appear on the monitor window, you can double click on it, this will open the additional window we belong to, this window allows you to step through the code, view and manipulate variables, and inspect recursive stack. Another way to open an additional window is to prepend the trace window with options including setting breakpoints in the code, running the interpreted module and exiting, or calling the interpreted module only on the first execution.

5. You can select an appropriate menu item in the break menu or a line in a stand-alone monitor or a line in the module window to set a breakpoint. Breakpoints can only be set on executable expressions, so set them in the head, mode Or a breakpoint on a statement delimiter has no effect, the breakpoint has a valid or invalid state, and when a valid breakpoint is reached, the breakpoint can be removed, disabled, or kept valid by triggers.

6. The specific steps are as follows:

6.1. Enter debugger:start() on the erlang terminal to start the debugger.

6.2. Use c("module name", [debug_info]). to track and compile a module in the erlang terminal.

6.3. Then open the Interpret in the module, there are tracked and untracked modules in it, choose to start an untracked module, and the selected module will appear in the debugger window.

6.4. Call a method of this module in the erlang terminal, a record will appear in the debugger, and then click to double-click this record, an additional window will appear.

6.5. Select any one of line break, conditional break or function break in the break in the additional window, and then select the line where a breakpoint needs to be added.

6.6. Call a method of this module in the erlang terminal, you can see the breakpoint where the function is executed in the additional window, and then select Next in the additional window Process (skip the internal method called by this method), continue ( Execute the internal method of the breakpoint call), finish (complete the call of this module, that is, skip all breakpoints).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326440598&siteId=291194637