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.)
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'm new to Erlang and N2O but have some experience in python web development. I want to create authentication by email address (email - password) in my application instead of using AVZ. I've created Sign Up page with this code (other code is as n2o_sample). But instead of putting user to kvs I have {error, no_container}
-module(signup_page).
-compile(export_all).
-include_lib("n2o/include/wf.hrl").
-include_lib("n2o_sample/include/users.hrl").
title() -> [ <<"Sign Up Page">> ].
main() -> #dtl{file = "login", app = n2o_sample,
bindings = [{title,title()},{body,body()}]}.
body() ->
[ #span{id=display}, #br{},
#span{body="Email: "}, #textbox{id=user}, #br{},
#span{body="Password: "}, #password{id=pass}, #br{},
#span{body="Confirm Password"}, #password{id=confirm}, #br{},
#button{id=signup, body="Sign Up",
postback=signup,source=[user,pass,confirm]}].
event(signup) ->
User = wf:q(user), Password = wf:q(pass), Confirm = wf:q(confirm),
U = kvs:get(user, User, undefined),
case U of
{ok, undefined} ->
case Password of
undefined -> wf:update(display, <<"No pass">>);
Confirm -> Status = kvs:put(#user{id=User}),
% -> {error, no_container}
io:format("~w~n", [Status]);
B -> io:format("~w~n", [B]) end;
A -> io:format("~w~n", [A]),
wf:update(display, <<"Already registered!">>) end;
event(_) -> [].
You do everything right.
The question is essentially with KVS configuring. To make KVS properly working you should do several steps:
1. Put the kvs into rebar.config
{kvs, ".*", {git, "git://github.com/synrc/kvs", {tag,"1.5.0"}}},
Use frozen tag version, e.g. "1.5.0" is the latest stable.
2. Configure KVS application in sys.config
{n2o, [{port,8000},{transition_port, 8000}]},
{kvs, [{dba,store_mnesia},
{schema, [kvs_user, kvs_acl, kvs_feed, kvs_subscription ]} ]},
I put in example N2O configuring to see where is should be placed.
3. Just after first launch of "make console" you should initialize the DB in Erlang shell:
1> kvs:join().
This will instantiate MNESIA tables.
4. After that in Erlang shell please do the check of your problem:
2> rr(kvs_user).
First load all records from kvs_user module.
Then perform your check:
3> kvs:put(#user{id="maxim#synrc.com"}).
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.
Is there a straightforward way to convert an Erlang fun to a string? A call to io_lib:format only prints the function reference, e.g. something like "#Fun<erl_eval.20.67289768>". For example, I'd like to be able to do this:
1> Fun = fun() -> atom_to_list('hello world') end.
2> FunStr = fun_to_str(Fun).
"fun() -> atom_to_list('hello world') end."
I'm looking for how to implement fun_to_str. In javascript, some interpreters have a .toSource() function that can be called on any object, including functions, that print their string representation. Any info is appreciated, thanks.
First, get the environment variables for the fun (which includes the abstract code):
1> {env, [{_, _, _, Abs}]} = erlang:fun_info(Fun, env).
{env,[{[],
{eval,#Fun<shell.21.83096281>},
{value,#Fun<shell.5.83096281>},
[{clause,1,[],[],
[{call,1,{atom,1,atom_to_list},[{atom,1,hello_world}]}]}]}]}
Pretty print the abstract code using erl_pp:
3> Str = erl_pp:expr({'fun', 1, {clauses, Abs}}).
[[[["fun",
[[[[["()"]," ->"],
["\n ",
[["atom_to_list",[[40,["'hello world'",41]]]]]]]]]]],
[10,["end"]]]]
4> io:format([Str|"\n"]).
fun() ->
atom_to_list('hello world')
end
ok
(You have to add {'fun', 1, {clauses, ...}} around it to make it a complete Erlang expression)
You might be able to use erlang:fun_info/2 for that, atleast i get some information from the shell when doing
1> erlang:fun_info(fun() -> test,ok end, env).
{env,[[],
{value,#Fun<shell.7.37281544>},
{eval,#Fun<shell.24.85590193>},
[{clause,1,[],[],[{atom,1,test},{atom,1,ok}]}]]}
2>
You want the last list with the clause atom and then pretty print it using for instance erl_pp
I'm trying to write a simple Thrift server in Erlang that takes a string and returns a string.
Everything seems to be working up to the point of calling my function:
handle_function(Function, Args) when is_atom(Function), is_tuple(Args) ->
case apply(?MODULE, Function, tuple_to_list(Args)) of
ok -> ok;
Reply -> {reply, Reply}
end.
test([X]) ->
"You sent: " ++ X.
I'm getting a function_clause. The stack trace shows the following:
{function_clause, [{server, test,
[<<"w00t">>]},
{server,handle_function, 2}, ...
My handle_function is copied from the tutorial file so I won't be surprised if I need to tweak it. Any ideas?
That last argument of apply should be a list of arguments to 'test', e.g., if tuple_to_list(Args) resulted in:
[1]
...then:
test(1)
If tuple_to_list(Args) resulted in:
[1,2]
...then:
test(1,2)
So, if {<<"woot">>} is being passed to tuple_to_list, that's going to be:
[<<"woot">>]
...so:
test(<<"woot">>)
...but test's signature asks for a list as the argument, so there's a mismatch.