Erlang atoms and ".." - erlang

This is output of erlang shell:
1> atom.
atom
2> next_atom.
next_atom
3> atom#erlang.
atom#erlang
4> 'atom in single quotes'.
'atom in single quotes'
5> atom = 'atom'.
atom
6> a.tom.
'a.tom'
7> a..tom.
* 1: syntax error before: '..'
When there is just one dot . within atom (line 6), I get no errors. However, when there is .., I get syntax error. Does .. have some special meaning in Erlang or why do I get error when . works fine?

Dots are not allowed as such in atoms, but a dot between two atoms: 'foo'.'bar',
is a compile time operator that concatenates the atoms to 'foo.bar'.
This is an extension which was made to support the (still not officially
supported) Java-like package system. That's why it's not documented.

Related

Why does pattern matching on this string in erlang result in a "string" for the tail and an ascii value for the list?

I was trying to write a pattern matched function in erlang like:
to_end("A") -> "Z".
The whole idea is to transform a string such as "ABC" into something different such as "ZYX" using pattern matched functions. It looks like a string is represented as a list under the hood...
I was depending on the fact that pattern matching on a "string" in erlang would result in individual string characters. But I find this:
21> F="ABC".
22> F.
"ABC"
23> [H | T]=F.
"ABC"
24> H.
65
25> T.
"BC"
Why does the head of this type of pattern matching on list always result in an ASCII value and the tail result in letters? Is there a better way to pattern match against a "list of string"?
In Erlang, strings are just a list of ascii values. It also displays lists of integers, where every integer is a printable ascii code, as strings. So [48, 49] would print out "01" since 48 corresponds to 0 and 49 to 1. Since you have the string "ABC", this is the same as [65 | [66 | [67]]], and [66, 67] will display as "BC".
If you want to write a function to pattern match on characters, you should use the character literal syntax, which is $ followed by the character. So you would write
to_end($A) -> $Z;
to_end($B) -> $Y;
to_end($C) -> $X;
...
to_end($Z) -> $A.
instead of to_end("A") -> "Z" which is the same as to_end([65]) -> [90].
Why does the head of this type of pattern matching on list always
result in an ASCII value and the tail result in letters?
In erlang, the string "ABC" is a shorthand notation for the list [65,66,67]. The head of that list is 65, and the tail of that list is the list [66,67], which the shell happens to display as "BC". Whaa??!
The shell pretty much sucks when displaying strings/lists: sometimes the shell displays a list and sometimes the shell displays a double quoted string:
2> [0, 65, 66, 67].
[0,65,66,67]
3> [65, 66, 67].
"ABC"
4>
...which is just plain dumb. Every beginning and intermediate erlang programmer gets confused by that at some point.
Just remember: when the shell displays a double quoted string, it should really be displaying a list whose elements are the character codes of each character in the double quoted string. The fact that the shell displays a double quoted string is a TERRIBLE ??feature?? of erlang, and it makes it hard to decipher what is going on in a lot of situations. You have to mentally say to yourself, "That string I'm seeing in the shell is really the list ..."
That fact that the shell displays double quoted strings for some lists really sucks when you want to display, say, a list of a person's test scores: [88, 97, 92, 70] and the shell outputs: "Xa\\F". You can use the io:format() method to get around that:
6> io:format("~w~n", [[88,97,92,70]]).
[88,97,92,70]
ok
But, if you just want to momentarily see the actual list of integers that the shell is displaying as a string, a quick and dirty method is to add the integer 0 to the head of the list:
7> Scores = [88,97,92,70].
"Xa\\F"
Huh?!!
8> [0|Scores].
[0,88,97,92,70]
Oh, okay.
The whole idea is to transform a string such as "ABC" into something
different such as "ZYX" using pattern matched functions.
Because a string is shorthand for a list of integers, you can change those integers by using addition:
-module(my).
-compile(export_all).
cipher([]) -> [];
cipher([H|T]) ->
[H+10|cipher(T)]. %% Add 10 to each character code.
In the shell:
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> my:cipher("ABC").
"KLM"
3>
By the way, all functions are "pattern matched", so saying "a pattern matched function" is redundant, you can just say, "a function".

Erlang printing hex instead of integer

I have been trying to fix a problem for hours now, very new to erlang
lists:sublist([6,9,15,24,39,6,96],7,1).
I want this to print "100" instead of "d"
what I am i doing wrong here?
The shell is going to try to print strings as strings whenever it would be legal. That means lists of integers that happen to all be valid characters will be printed as characters, and lists that contain other things will be printed as lists:
1> [65,66,67].
"ABC"
2> [3,65,66,67].
[3,65,66,67]
But notice that I did not actually call any output functions. That was just the shell's convenience operation of implicitly echoing whatever a returned value was so you, as a programmer, can inspect it.
If I want to explicitly call an output function I should use a format string that specifies the nature of the values to be interpolated:
3> io:format("This is a list: ~tw~n", [List]).
This is a list: [65,66,67]
ok
4> io:format("This is a list rendered as an implied string: ~tp~n", [List]).
This is a list rendered as an implied string: "ABC"
ok
5> io:format("This is a string: ~ts~n", [List]).
This is a string: ABC
ok
Note the additional atom ok after each print. That is because the return value from io:format/2 is ok. So we are getting the explicit output from format/2 and then seeing its return value.
The io module doc page has the gritty details: http://erlang.org/doc/man/io.html#format-1
Back to your example...
6> lists:sublist([6,9,15,24,39,6,96],7,1).
"`"
7> io:format("~tw~n", [lists:sublist([6,9,15,24,39,6,96],7,1)]).
[96]
ok
Addendum
There is a setting called shell:strings/1 that tells the shell to turn string formatting on and off:
1> [65,66,67].
"ABC"
2> shell:strings(false).
true
3> [65,66,67].
[65,66,67]
4> <<65,66,67>>.
<<65,66,67>>
5> shell:strings(true).
false
6> <<65,66,67>>.
<<"ABC">>
But I don't mess with this setting ever anymore for a few reasons:
It is almost never worth the effort to remember this detail of the shell (convenience output from the shell is mostly useful for discovering return value structures, not specific values held by those structures -- and when you want that data you usually want strings printed as strings anyway).
It can cause surprising shell output in any case where you really are dealing with strings.
This is almost never the behavior you actually want.
When dealing with real programs you will need actual output functions using io or io_lib modules, and developing habits around format strings is much more useful than worrying over convenience output from the shell.

How to perform a case-insensitive file search in Erlang/Elixir

Elixir provides Path.wildcard, which uses the Erlang :filelib.wildcard function internally.
Matching is case-sensitive, for example, "a" does not match "A".
(http://erlang.org/doc/man/filelib.html#wildcard-1)
Please is there a case-insensitive alternative?
There's no built in option to do this, but since the wildcard syntax supports character alternations similar to regex, you can replace every letter with an alternation of its lower and upper case versions, e.g. f0o -> [fF]0[oO], and then pass that to Path.wildcard/1. Here's a simple implementation that does this for ASCII letters:
defmodule A do
def case_insensitive_glob(glob) do
Regex.replace(~r/[a-zA-Z]/, glob, fn letter ->
"[#{String.downcase(letter)}#{String.upcase(letter)}]"
end)
end
end
glob = A.case_insensitive_glob("**/*reAdmE.*") |> IO.inspect
Path.wildcard(glob) |> IO.inspect
Running this in the OTP source code produces all files with their name containing "reAdmE." in any case.
"**/*[rR][eE][aA][dD][mM][eE].*"
["README.md", "erts/emulator/pcre/README.pcre_update.md",
"lib/erl_interface/src/README.internal",
"lib/ic/examples/pre_post_condition/ReadMe.txt", "xcomp/README.md"]
I've verified the output's correctness with find:
$ find . -iname 'readme.*'
./erts/emulator/pcre/README.pcre_update.md
./lib/erl_interface/src/README.internal
./lib/ic/examples/pre_post_condition/ReadMe.txt
./README.md
./xcomp/README.md

Value from binding in LFE interpreter using Erlang

I'd like to use Lisp Flavored Erlang as a scripting extension language for an Erlang application. If you want, in a similar way GNU Emacs is configured and extended via Emacs Lisp.
I know that the argument is wide and structured; but in the specific case of this question I'd like being able to read a binding name (or variable, if you prefer) defined in LFE from Erlang code.
I'm not an expert of LFE internal architecture (which is an excellent example of software engineering and Erlang programming), but I was not able to find an answer neither in the sources nor in the documentation.
Looking at sources I can see that LFE contains both a compiler that target Erlang VM and an interpreter.
The latter is the one I'm trying to use.
If I start Erlang shell/REPL in LFE installation path (on my system $HOME/opt/lfe):
$ cd /path/to/LFE-install-dir
$ erl -pa ./ebin
I'm able to calculate a value:
1> {ok, Expr} = lfe_io:read_string("(+ 1 10)").
{ok,['+',1,10]}
2> Result = lfe_eval:expr(Expr).
11
This is a first step, but not exactly what I want. I'd like rather to bind a variable and read its value; that's my issue:
3> {ok, Expr2} = lfe_io:read_string("(set a 10)").
{ok,[set,a,10]}
4> lfe_eval:expr(Expr2).
** exception error: {unbound_func,{set,2}}
in function lfe_eval:eval_expr/2
Why set is recognized as an unbound function? In LFE REPL this expression is valid:
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] ...
LFE Shell V6.4 (abort with ^G)
> (set a 10)
10
> a
10
I'm obviously using the API in the wrong way. How can I read the content of a and/or properly initialize the LFE interpreter?
(If this is explained somewhere, please provide the reference).
I won't attempt to answer completely your broader question about the "best practices" of adding scripting. It seems to me that choosing between "hook-based" solution (in which you define hook implementations by name convention and they are automatically recognized) and "explicit api" solution (in which you use functions predefinied in the scripting enviroment to register your hooks or otherwise call configuration functions) is largely a matter of taste. Explicit calls like (set-connection-timeout-handler ...) may be more readable, easier to debug (no misspelling problems, no surprises on api changes), easier to document, and a bit more flexible, but more, well, explicit.
Building from your simple variable definition example, here are a few ways you could get started going further the "interpreted" path:
1> {ok, Expr} = lfe_io:read_string("'((a 10))").
{ok,[quote,[[a,10]]]}
2> lfe_eval:expr (Expr).
[[a,10]]
3> EvalAll = fun (Conf) -> {ok, E} = lfe_io:read_string("'(" ++ Conf ++ ")"), lfe_eval:expr(E) end.
#Fun<erl_eval.6.90072148>
4> EvalAll ("(a 10) (b 11)").
[[a,10],[b,11]]
5> EvalAllL = fun (Conf) -> {ok, E} = lfe_io:read_string("(list " ++ Conf ++ ")"), lfe_eval:expr(E) end.
#Fun<erl_eval.6.90072148>
6> [{f, F}] = EvalAllL ("(tuple 'f (lambda (x) (+ 10 x)))").
[{f,#Fun<lfe_eval.12.2018457>}]
7> F (12).
22
8> G = fun (X) -> X * 2 end.
#Fun<erl_eval.6.90072148>
9> lfe_eval:expr (element (2, lfe_io:read_string ("(g 15)")), lfe_eval:add_lexical_func(g, 1, G, lfe_env:new ())).
30
A simple way is use to the 'lfe' command to run LFE scripts. The 'lfe' behaves in similar fashion to 'bash' in that you can use it to run scripts. The 'lfec' script defined in bin/lfec is a good example of this. It is an LFE shell script which parses it arguments and run the LFE compiler.

erlang - passing a number as the Name argument to register/2

When using register/2, I get an error when I try to pass a number as the process name argument. Here I try to name the shell process '1', and get the following error:
43> register(1,self()).
** exception error: bad argument
in function register/2
called as register(1,<0.93.0>)
Contrast this to naming the shell 'shelly':
44> register(shelly,self()).
true
The documentation says the Name argument in register(Name,PID) has to be an atom. I thought the number 1 was indeed an atom.
My question is: how do pass successfully pass a number to register/2, such that passing the bound variable P=1, for example, succeeds?
An atom is a symbol, nothing to do with integers. There is no direct conversion from integer to atom, but you can use an intermediate list for that:
1> Int_to_atom = fun(X) -> list_to_atom(integer_to_list(X)) end.
#Fun<erl_eval.6.106461118>
2> Int_to_atom(2).
'2'
3> P = 1.
1
4> Int_to_atom(P).
'1'
5>
From the Erlang documentation on datatypes:
An atom is a literal, a constant with name. An atom should be enclosed
in single quotes (') if it does not begin with a lower-case letter or
if it contains other characters than alphanumeric characters,
underscore (_), or #.
You can do
register('1',self()).
(Note the single-quotes, making this an atom and not a number. You can see that it's not a number but an atom by trying
'1' + 1
You were probably thinking of "term" when you expected them to be interchangeable. An Erlang term is an singular piece of data. Some examples of things that are terms:
an atom
a number
a tuple (itself containing more terms)
a list (itself containing more terms)
a binary
a function

Resources