I want to know Guard Sequence And What Are The Valid Guard Expressions in Erlang?
Guard Sequences
A guard sequence is a sequence of guards, separated by semicolon (;).
The guard sequence is true if at least one of the guards is true. (The
remaining guards, if any, are not evaluated.)
Guard1;...;GuardK
Example:
go(X,Y) when X==1;Y==2 ->
io:format("Yes~n").
In the shell:
2> a:go(1, 2).
Yes
ok
3> a:go(1, 3).
Yes
ok
4> a:go(4, 2).
Yes
ok
5> a:go(4, 3).
** exception error: no function clause matching
a:go(4,3) (a.erl, line 4)
So, a semi-colon is like OR.
A guard is a sequence of guard expressions, separated by comma (,).
The guard is true if all guard expressions evaluate to true.
GuardExpr1,...,GuardExprN
Example:
go(X,Y,Z) when X==1,Y==2, is_atom(Z) ->
io:format("Yes~n").
In the shell:
8> a:go(1, 3, a).
** exception error: no function clause matching
a:go(1,3,a) (a.erl, line 4)
9> a:go(1, 2, a).
Yes
ok
So, a comma is like AND.
Guard Expressions
The set of valid guard expressions is a subset of the set of valid
Erlang expressions. The reason for restricting the set of valid
expressions is that evaluation of a guard expression must be
guaranteed to be free of side effects. Valid guard expressions are the
following:
Variables
Constants (atoms, integer, floats, lists, tuples, records, binaries, and maps)
Expressions that construct atoms, integer, floats, lists, tuples, records, binaries, and maps
Expressions that update a map
The record epxressions Expr#Name.Field and #Name.Field
Calls to the BIFs specified in tables Type Test BIFs and Other BIFs Allowed in Guard Expressions
Term comparisons
Arithmetic expressions
Boolean expressions
Short-circuit expressions (andalso/orelse)
Type Test BIFs:
is_atom/1
is_binary/1
is_bitstring/1
is_boolean/1
is_float/1
is_function/1
is_function/2
is_integer/1
is_list/1
is_map/1
is_number/1
is_pid/1
is_port/1
is_record/2
is_record/3
is_reference/1
is_tuple/1
Notice that most type test BIFs have older equivalents, without the
is_ prefix. These old BIFs are retained for backwards compatibility
only and are not to be used in new code. They are also only allowed at
top level. For example, they are not allowed in Boolean expressions in
guards.
Other BIFs Allowed in Guard Expressions:
abs(Number)
bit_size(Bitstring)
byte_size(Bitstring)
element(N, Tuple)
float(Term)
hd(List)
length(List)
map_get(Key, Map)
map_size(Map)
node()
node(Pid|Ref|Port)
round(Number)
self()
size(Tuple|Bitstring)
tl(List)
trunc(Number)
tuple_size(Tuple)
If an arithmetic expression, a Boolean expression, a short-circuit
expression, or a call to a guard BIF fails (because of invalid
arguments), the entire guard fails. If the guard was part of a guard
sequence, the next guard in the sequence (that is, the guard following
the next semicolon) is evaluated.
This:
A guard sequence is a sequence of guards, separated by semicolon (;).
gives you this:
GuardSequence = Guard1;Guard2;Guard3
What is a Guard? This sentence:
A guard is a sequence of guard expressions, separated by comma (,).
gives you this:
Guard1 = GuardExpr1, GuardExpr2, GuardExpr3
What's a guard expression? This sentence:
The set of valid guard expressions is...
gives you stuff like:
GuardExpr1 = (X==1)
GuardExpr2 = (Y==2)
GuardExpr3 = is_atom(Z)
Now, substitute the GuardExpr's into this line:
Guard1 = GuardExpr1, GuardExpr2, GuardExpr3
giving you:
Guard1 = X==1, Y==2, is_atom(Z)
Now, substitute Guard1 into this line:
GuardSequence = Guard1;Guard2;Guard3
giving you:
GuardSequence = X==1, Y==2, is_atom(Z)
If you also have a Guard2 and Guard3, and they look like this:
Guard2 = is_integer(X)
Guard3 = element(Y, Tuple)
then GuardSequence would look like this:
GuardSequence = X==1, Y==2, is_atom(Z); is_integer(X); element(Y, Tuple)
OKAY??!
Related
Why does this work, but if I comment out the second line it does not? Is it because F# cannot infer msg is a string?
Line 3 = msg can be indexed msg[], and msg is string String.length msg.
Is this one of those situations where it is better to specify the type? let isQuestion (msg:string) = ...
let isQuestion msg =
let n = String.length msg //if I comment this line out the function no longer works
msg[(String.length msg - 1)] = '?'
Yes, the reason here is that the 2nd line is what tells the compiler that msg is unambiguously a string.
It's more complicated than this, but at a high level you can think of F# type inference as working as such:
top -> down
left -> right
In pre-F# 6, you would need to use msg.[...] to index the string, and with that syntax the error message is more clear:
The operator 'expr.[idx]' has been used on an object of indeterminate type based on information prior to this program point.
Consider adding further type constraints
However, in F# 6 it is a warning because you could technically be trying to write msg [expr] = '?', which would mean that msg is a function that takes a list as input and produces a char. Because of this ambiguity, the warning is emitted and you're asked to specify a type to clarify your intent. And because msg is not inferred to be a string, you see an error in the expr part of the indexing expression.
Why is this OK:
let [<Literal>] hi = "hi"
let [<Literal>] bye = "bye"
let [<Literal>] shortMeeting = hi + bye
...but this is not?
let [<Literal>] me = 1
let [<Literal>] you = 1
let [<Literal>] we = me + you
The third line gives the error:
This is not a valid constant expression
What's up with that?
So the spec / docs are a little unclear, but provide hints.
From the spec (for F# 3.0):
A value that has the Literal attribute is subject to the following
restrictions:
It may not be marked mutable or inline. It may not also have the
ThreadStaticor ContextStatic attributes. The righthand side expression
must be a literal constant expression that is made up of either:
A simple constant expression, with the exception of (), native integer
literals, unsigned native integer literals, byte array literals,
BigInteger literals, and user-defined numeric literals.
OR
A reference to another literal
This seems to suggest that even the combination of strings isn't allowed.
The documentation states that this changed in F# 3.1:
https://msdn.microsoft.com/en-us/library/dd233193.aspx
As of F# 3.1, you can use the + sign to combine string literals. You
can also use the bitwise or (|||) operator to combine enum flags. For
example, the following code is legal in F# 3.1:
Note that integer addition is not on that list
I want to use erlang datetime values in the standard format {{Y,M,D},{H,Min,Sec}} in a MNESIA table for logging purposes and be able to select log entries by comparing with constant start and end time tuples.
It seems that the matchspec guard compiler somehow confuses tuple values with guard sub-expressions. Evaluating ets:match_spec_compile(MatchSpec) fails for
MatchSpec = [
{
{'_','$1','$2'}
,
[
{'==','$2',{1,2}}
]
,
['$_']
}
]
but succeeds when I compare $2 with any non-tuple value.
Is there a restriction that match guards cannot compare tuple values?
I believe the answer is to use double braces when using tuples (see Variables and Literals section of http://www.erlang.org/doc/apps/erts/match_spec.html#id69408). So to use a tuple in a matchspec expression, surround that tuple with braces, as in,
{'==','$2',{{1,2}}}
So, if I understand your example correctly, you would have
22> M=[{{'_','$1','$2'},[{'==','$2',{{1,2}}}],['$_']}].
[{{'_','$1','$2'},[{'==','$2',{{1,2}}}],['$_']}]
23> ets:match_spec_run([{1,1,{1,2}}],ets:match_spec_compile(M)).
[{1,1,{1,2}}]
24> ets:match_spec_run([{1,1,{2,2}}],ets:match_spec_compile(M)).
[]
EDIT: (sorry to edit your answer but this was the easiest way to get my comment in a readable form)
Yes, this is how it must be done. An easier way to get the match-spec is to use the (pseudo) function ets:fun2ms/1 which takes a literal fun as an argument and returns the match-spec. So
10> ets:fun2ms(fun ({A,B,C}=X) when C == {1,2} -> X end).
[{{'$1','$2','$3'},[{'==','$3',{{1,2}}}],['$_']}]
The shell recognises ets:fun2ms/1. For more information see ETS documentation. Mnesia uses the same match-specs as ETS.
I am curious why the comma ‹,› is a shortcut for and and not andalso in guard tests.
Since I'd call myself a “C native” I fail to see any shortcomings of short-circuit boolean evaluation.
I compiled some test code using the to_core flag to see what code is actually generated. Using the comma, I see the left hand value and right and value get evaluated and both and'ed. With andalso you have a case block within the case block and no call to erlang:and/2.
I did no benchmark tests but I daresay the andalso variant is the faster one.
To delve into the past:
Originally in guards there were only , separated tests which were evaluated from left-to-right until either there were no more and the guard succeeded or a test failed and the guard as a whole failed. Later ; was added to allow alternate guards in the same clause. If guards evaluate both sides of a , before testing then someone has gotten it wrong along the way. #Kay's example seems to imply that they do go from left-to-right as they should.
Boolean operators were only allowed much later in guards.
and, together with or, xor and not, is a boolean operator and was not intended for control. They are all strict and evaluate their arguments first, like the arithmetic operators +, -, * and '/'. There exist strict boolean operators in C as well.
The short-circuiting control operators andalso and orelse were added later to simplify some code. As you have said the compiler does expand them to nested case expressions so there is no performance gain in using them, just convenience and clarity of code. This would explain the resultant code you saw.
N.B. in guards there are tests and not expressions. There is a subtle difference which means that while using and and andalso is equivalent to , using orelse is not equivalent to ;. This is left to another question. Hint: it's all about failure.
So both and and andalso have their place.
Adam Lindbergs link is right. Using the comma does generate better beam code than using andalso. I compiled the following code using the +to_asm flag:
a(A,B) ->
case ok of
_ when A, B -> true;
_ -> false
end.
aa(A,B) ->
case ok of
_ when A andalso B -> true;
_ -> false
end.
which generates
{function, a, 2, 2}.
{label,1}.
{func_info,{atom,andAndAndalso},{atom,a},2}.
{label,2}.
{test,is_eq_exact,{f,3},[{x,0},{atom,true}]}.
{test,is_eq_exact,{f,3},[{x,1},{atom,true}]}.
{move,{atom,true},{x,0}}.
return.
{label,3}.
{move,{atom,false},{x,0}}.
return.
{function, aa, 2, 5}.
{label,4}.
{func_info,{atom,andAndAndalso},{atom,aa},2}.
{label,5}.
{test,is_atom,{f,7},[{x,0}]}.
{select_val,{x,0},{f,7},{list,[{atom,true},{f,6},{atom,false},{f,9}]}}.
{label,6}.
{move,{x,1},{x,2}}.
{jump,{f,8}}.
{label,7}.
{move,{x,0},{x,2}}.
{label,8}.
{test,is_eq_exact,{f,9},[{x,2},{atom,true}]}.
{move,{atom,true},{x,0}}.
return.
{label,9}.
{move,{atom,false},{x,0}}.
return.
I only looked into what is generated with the +to_core flag, but obviously there is a optimization step between to_core and to_asm.
It's an historical reason. and was implemented before andalso, which was introduced in Erlang 5.1 (the only reference I can find right now is EEP-17). Guards have not been changed because of backwards compatibility.
The boolean operators "and" and "or" always evaluate arguements on both the sides of the operator. Whereas if you want the functionality of C operators && and || (where 2nd arguement is evaluated only if needed..for eg if we want to evalue "true orelse false" as soon as true is found to be the first arguement, the second arguement will not be evaluated which is not the case had "or" been used ) go for "andalso" and "orelse".
First of all, I'm an Erlang rookie here. I need to interface with a MySQL database and I found the erlang-mysql-driver. I'm trying that out, and am a little confused by some of the syntax.
I can get a row of data from the database with this (greatly oversimplified for brevity here):
Result = mysql:fetch(P1, ["SELECT column1, column2 FROM table1 WHERE column2='", Key, "'"]),
case Result of
{data, Data} ->
case mysql:get_result_rows(Data) of
[] -> not_found;
Res ->
%% Now 'Res' has the row
So now here is an example of what `Res' has:
[[<<"value from column1">>, <<"value from column2">>]]
I get that it's a list of records. In this case, the query returned 1 row of 2 columns.
My question is:
What do the << and >> symbols mean? And what is the best (Erlang-recommended) syntax for turning a list like this into a records which I have defined like:
-record(
my_record,
{
column1 = ""
,column2 = ""
}
).
Just a small note: the results are not bit string comprehensions per see, they are just bit strings. However you can use bit string comprehensions to produce a sequence of bit strings (which is described above with the generators and that), much like lists and lists comprehensions.
you can use erlang:binary_to_list/1 and erlang:list_to_binary/1 to convert between binary and strings (lists).
The reason the mysql driver returns bit strings is probably because they are much faster to manipulate.
In your specific example, you can do the conversion by matching on the returned column values, and then creating a new record like this:
case mysql:get_result_rows(Data) of
[] ->
not_found;
[[Col1, Col2]] ->
#my_record{column1 = Col1, column2 = Col2}
end
These are bit string comprehensions.
Bit string comprehensions are analogous to List Comprehensions. They are used to generate bit strings efficiently and succinctly.
Bit string comprehensions are written with the following syntax:
<< BitString || Qualifier1,...,QualifierN >>
BitString is a bit string expression, and each Qualifier is either a generator, a bit string generator or a filter.
• A generator is written as:
Pattern <- ListExpr.
ListExpr must be an expression which evaluates to a list of terms.
• A bit string generator is written as:
BitstringPattern <= BitStringExpr.
BitStringExpr must be an expression which evaluates to a bitstring.
• A filter is an expression which evaluates to true or false.
The variables in the generator patterns shadow variables in the function clause surrounding the bit string comprehensions.
A bit string comprehension returns a bit string, which is created by concatenating the results of evaluating BitString for each combination of bit string generator elements for which all filters are true.
Example:
1> << << (X*2) >> ||
<<X>> <= << 1,2,3 >> >>.
<<2,4,6>>