In the file of "jobs_info.erl" of github project "jobs", it contains the following codes:
pp(L) when is_list(L) ->
[pp(X) || X <- L];
pp(X) ->
case '#is_record-'(X) of %<=========What's meaning of '"#is_record-'?
true ->
RecName = element(1,X),
{RecName, lists:zip(
'#info-'(RecName,fields), %<=======what's meaning of ''#info-'?
pp(tl(tuple_to_list(X))))};
false ->
if is_tuple(X) ->
list_to_tuple(pp(tuple_to_list(X)));
true ->
X
end
end.
What's the expression of '#is_record-' and ''#info-'?
"is_record" may be refered to erlang:is_record?
But what's "'#info-'"?
As Kemal points out have a look at the method declaration at github.com/esl/parse_trans/blob/master/src/exprecs.erl#L116.
If it is the ' that confuses you, remember that a function name in Erlang is an atom and that an atom needs to start with a lower-case letter and if it does not it should be surrounded by '. Check the docs for more info.
Related
I wrote a Hello-World module and compiled it successfully. And then I tried to learn the things under the hood by using erl_scan and erl_parse.
-module(useless).
-export([hello/0]).
hello() -> io:format("hello world\n").
and I type in the erl shell
{ok, S} = file:read_file("useless.erl").
and
{ok, T, _} = erl_scan:string(binary_to_list(S)).
It works fine apparently. But when I try erl_parse:parse_form(T).
It gives {error,{2,erl_parse,["syntax error before: ","'-'"]}}
What am I doing wrong?
Edit:
the module compile is helpful.
Also this is cool.
The function erl_parse:parse_form/1 works on one form only. So you must split the result of erl_scan:string/1 into individual forms first.
you can use erl_scan:tokens to achieve this (this code wors, but I am not sure I use the function in the right way):
-module(useless).
-export([eval/1]).
eval(File) ->
{ok, B} = file:read_file(File),
Forms = scan(erl_scan:tokens([],binary_to_list(B),1),[]),
F = fun(X) -> {ok,Y} = erl_parse:parse_form(X), Y end,
[F(X) || X <- Forms].
scan({done,{ok,T,N},S},Res) ->
scan(erl_scan:tokens([],S,N),[T|Res]);
scan(_,Res) ->
lists:reverse(Res).
Robert suggestion is to use the re-entrant feature of erl_scan:tokens/3.
The docs on this function are not explicit and it took me some time to understand that the initial string needed to be closed by eof. (if not the tokens function runs an endless loop).
Here is the code I finally came up with, I hope that will help others.
eval(File)->
{ok, Data} = file:read_file(File),
String=erlang:binary_to_list(Data),
scan(String).
scan(String) when is_list(String)->
scan(String++eof,[]). %% appended eof
scan({done, Result, LeftOverChars},Acc)->
scan_done(Result,LeftOverChars,Acc);
scan({more, Continuation},Acc)->
scan(erl_scan:tokens(Continuation,[],1),Acc);
scan(String,Acc) when is_list(String)->
scan(erl_scan:tokens([],String,1),Acc).
scan_done({error,ErrorMsg,_Location},_LeftOverChars,_Acc)->
ErrorMsg;
scan_done({eof,Location},LeftOverChars,Acc)->
Acc;
scan_done({ok,Tokens,Location},LeftOverChars,Acc)->
case erl_parse:parse_form(Tokens) of
{ok,R}->scan(LeftOverChars,Acc++[R]);
{error,R}->scan(LeftOverChars,R)
end.
I have recently started learning erlang, but have encountered an error that just leaves me puzzled.
The error is syntax error before: 'end' on the very last line. I have looked at examples an tried to find the error but I'm totally lost at the moment. Any Ideas?
ChannelToJoin = list:keysearch(ChannelName,1,State#server_st.channels),
case ChannelToJoin of
% Channel exists.
{value, Tuple} ->
if
%User is not a member of the channel
not list:member(UserID, Tuple) ->
%Add the user to the channel
Tuple#channel.users = list:append(Tuple#channel.users, [UserID]);
% If the user is already a member of the channel.
true -> true
end;
%Channel doesn't exist
false ->
%Create new channel and add the user to it.
NewState = State#server_st{channels = list:append(State#server_st.channels, NewChannel = #channel{name = ChannelName, users = [UserID]}
end
The second to last line, NewState = ..., is missing two closing parentheses: )}
Also note that you can't use lists:member inside if, as function calls are not allowed inside guard expressions (which is what if lets you use). Instead, use case:
case lists:member(UserID, Tuple#channel.users) of
false ->
%% Add the user to the channel
...;
true ->
%% Already a member
ok
end
I have been learning erlang for the past week and am going through Joe Armstrong's Pragmatic erlang book . I was writing some code to spawn processes and have come across a situation
I have a function in module myatom.erl which looks like this
start(anatom,Fun) ->
case whereis(anatom) of
undefined ->
Pid = spawn(Fun),
try register(anatom,Pid) of
true -> true
catch
error:Reason ->
Reason
end;
Other -> {error,already_defined}
end.
There is a function in another module named tloop.erl
loop() ->
receive
{ From , No } -> From ! { self(), No*4};
Other -> void
end.
if I am to use start() to spawn loop in the erlang shell , how can I do it ?
I get the following error when I do
anatom:start(atomname,tloop:loop).
Thanks in advance !
anatom:start(myatom,fun tloop:loop).
* 2: syntax error before: ')
You must write the following
anatom:start(myatom, fun tloop:loop/0).
You have to specify the arity (number of arguments) of the function, as in erlang functions with the same name but different arity are not considered to be the same function.
Trying to cut a Line, read from a file, into a list of strings. This causes always a exception i don't know to solve.
exception error: no function clause matching string:tokens1
(<<"Cascading Style Sheets CSS are an increasingly common way for website developers to control the look\n">>," ,.",[]) in function readTest:run/1
-module(readTest).
-export([run/1]).
open_file(FileName, Mode) ->
{ok, Device} = file:open(FileName, [Mode, binary]),
Device.
close_file(Device) ->
ok = file:close(Device).
read_lines(Device, L) ->
case io:get_line(Device, L) of
eof ->
lists:reverse(L);
String ->
read_lines(Device, [String | L])
end.
run(InputFileName) ->
Device = open_file(InputFileName, read),
Data = read_lines(Device, []),
close_file(Device),
io:format("Read ~p lines~n", [length(Data)]),
Bla = string:tokens(hd(Data)," ,."),
io:format(hd(Data)).
May its an easy failure. getting just started in erlang.
When you open a file with binary flag, lines are read as binaries rather than lists (strings).
So in your code
Bla = string:tokens(hd(Data)," ,."),
hd(Data) is actually a binary, which causes string:tokens to crash.
You could either remove binary flag from file:open, or convert binary to list explicitly:
Bla = string:tokens(binary_to_list(hd(Data))," ,."),
It's also possible to split the binary without converting it to a list:
Bla = binary:split(Data, [<<" ">>, <<",">>, <<".">>], [global])
(See the documentation for binary:split/3.)
I have the following code
loop(Data) ->
receive
{Key, Value} ->
[{Key, Value}|Data];
{Key} ->
member(Key, Data);
14 loop(Data);
stop ->
io:format("server_stopped"),
ok
end .
and I get the following error (I put the line number 14 in the code)
./dist_erlang.erl:14: syntax error before: ';'
./dist_erlang.erl:2: function loop/1 undefined
./dist_erlang.erl:28: Warning: function member/2 is unused
I am not sure what the syntax problem is with the above code. I have a method called member which is giving the error because of a different syntax error on line 14 I am sure.
Any help is appreciated thanks.
In Erlang, expressions are separated by commas (and clauses are separated by semicolons). Try:
loop(Data) ->
receive
{Key, Value} ->
loop([{Key, Value}|Data]);
{Key} ->
member(Key, Data),
loop(Data);
stop ->
io:format("server_stopped"),
ok
end.