It is a tiny parse transform.
License: MIT
Author: Uvarov Michael (freeakk@gmail.com)
This operator checks, that X
is one of the [A, B, C, ...]
values
(Xs
).
Xs
is a fixed-size list of variables.
This operator and lists:member/2
are simular, but the second one is
a function, when in
is just an advanced macro command.
It is not possible to write using macros, because lists cannot be processed as a macro's argument.
This code is valid:
valid(X, Y) when in(X, [1,2,3,Y]) -> ok.
It will be replaced with:
valid(X, Y) when (X =:= 1 orelse X =:= 2 orelse X =:= 3 orelse X =:= Y) -> ok.
This code is invalid, because we don't know the actual size of the Y
variable:
invalid(X, Y) when in(X, Y) -> error.
The numeric_in
uses the ==
operator:
valid(X, Y) when numeric_in(X, [1,2,3,Y]) -> ok.
This code will be replaced with:
valid(X, Y) when (X == 1 orelse X == 2 orelse X == 3 orelse X == Y) -> ok.
The next code block demonstrates the difference beetween in
and numeric_in
:
> in(1, [1]).
true
> numeric_in(1, [1]).
true
> in(1, [1.0]).
false
> numeric_in(1, [1.0]).
true
> numeric_in({1}, [{1.0}]).
true
This is a realization of EEP-16.
S
and E
are stand for Start
and End
. X
is a value to check.
beetween(X, S, E)
checks, that X
is inside the closed interval [S, E]
.
The S
and E
endpoints are included.
beetween(X, open(S), open(E))
checks, that X
is inside the open interval (S, E)
.
beetween(X, open(S), E)
checks, that X
is inside the left-open interval (S, E]
.
beetween(X, S, open(E))
checks, that X
is inside the right-open interval [S, E)
.
beetween(X, S, E)
emulates the next macros:
-define(BEETWEEN(X, S, E), (((X) >= (S)) andalso ((X) =< (E))).
Before:
...
case ux_unidata_parser:split($;, Data) of
[Code, Form, Props] when (Form=="NFC_QC" orelse Form=="NFKC_QC"
orelse Form=="NFD_QC" orelse Form=="NFKD_QC")
and (Props=="N"
orelse Props=="Y"
orelse Props=="M") ->
Atom = list_to_atom(string:to_lower(Props)),
...
After:
-compile({parse_transform, gin}).
...
case ux_unidata_parser:split($;, Data) of
[Code, Form, Props] when in(Form, ["NFC_QC", "NFKC_QC", "NFD_QC", "NFKD_QC"])
and in(Props, ["N", "Y", "M"]) ->
Atom = list_to_atom(string:to_lower(Props)),
...
Before:
maybe_change_depth(Depth, Char) when Char =:= $)
orelse Char =:= $]
orelse Char =:= $} ->
Depth - 1;
maybe_change_depth(Depth, Char) when Char =:= $(
orelse Char =:= $[
orelse Char =:= ${ ->
Depth + 1;
maybe_change_depth(Depth, _) ->
Depth.
After:
-compile({parse_transform, gin}).
maybe_change_depth(Depth, Char) when in(Char, ")]}") ->
Depth - 1;
maybe_change_depth(Depth, Char) when in(Char, "([{") ->
Depth + 1;
maybe_change_depth(Depth, _) ->
Depth.
From here.
Before:
type_cast_row_data(Data, #field{type=Type})
when Type == ?FIELD_TYPE_VARCHAR;
Type == ?FIELD_TYPE_TINY_BLOB;
Type == ?FIELD_TYPE_MEDIUM_BLOB;
Type == ?FIELD_TYPE_LONG_BLOB;
Type == ?FIELD_TYPE_BLOB;
Type == ?FIELD_TYPE_VAR_STRING;
Type == ?FIELD_TYPE_STRING ->
Data;
type_cast_row_data(Data, #field{type=Type})
when Type == ?FIELD_TYPE_TINY;
Type == ?FIELD_TYPE_SHORT;
Type == ?FIELD_TYPE_LONG;
Type == ?FIELD_TYPE_LONGLONG;
Type == ?FIELD_TYPE_INT24;
Type == ?FIELD_TYPE_YEAR ->
list_to_integer(binary_to_list(Data));
...
Type cannot be a floated value, use =:=
for comparation.
After:
type_cast_row_data(Data, #field{type=Type}) when
in(Type, [?FIELD_TYPE_VARCHAR, ?FIELD_TYPE_TINY_BLOB,
?FIELD_TYPE_MEDIUM_BLOB, ?FIELD_TYPE_LONG_BLOB,
?FIELD_TYPE_BLOB, ?FIELD_TYPE_VAR_STRING,
?FIELD_TYPE_STRING]) ->
Data;
type_cast_row_data(Data, #field{type=Type}) when
in(Type, [?FIELD_TYPE_TINY, ?FIELD_TYPE_SHORT, ?FIELD_TYPE_LONG,
?FIELD_TYPE_LONGLONG, ?FIELD_TYPE_INT24, ?FIELD_TYPE_YEAR] ->
list_to_integer(binary_to_list(Data));
...
Before:
otp_7198_scan(<<>>, TokAcc) ->
lists:reverse(['$thats_all_folks$' | TokAcc]);
otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when
(D =:= $D orelse D =:= $d) and
((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]);
otp_7198_scan(<<D>>, TokAcc) when
(D =:= $D) or (D =:= $d) ->
otp_7198_scan(<<>>, ['AND' | TokAcc]);
otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when
(N =:= $N orelse N =:= $n) and
((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]);
otp_7198_scan(<<C, Rest/binary>>, TokAcc) when
(C >= $A) and (C =< $Z);
(C >= $a) and (C =< $z);
(C >= $0) and (C =< $9) ->
case Rest of
<<$:, R/binary>> ->
otp_7198_scan(R, [{'FIELD', C} | TokAcc]);
_ ->
otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc])
end.
...
After:
-compile({parse_transform, gin}).
otp_7198_scan(<<>>, TokAcc) ->
lists:reverse(['$thats_all_folks$' | TokAcc]);
otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc)
when in(D, "Dd") and in(Z, "\s()") ->
otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]);
otp_7198_scan(<<D>>, TokAcc) when in(D, "Dd") ->
otp_7198_scan(<<>>, ['AND' | TokAcc]);
otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc)
when in(N, "Nn") and in(Z, "\s()") ->
otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]);
otp_7198_scan(<<C, Rest/binary>>, TokAcc)
when beetween(C, $A, $Z); beetween(C, $a, $z); beetween(C, $0, $9) ->
case Rest of
<<$:, R/binary>> ->
otp_7198_scan(R, [{'FIELD', C} | TokAcc]);
_ ->
otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc])
end.
...