I have a pretty simple doubt, but I can't seem to find a proper solution for it anywhere.
I have 2 erlang modules, module1.erl and module2.erl. As defined by the submission guidelines for my project, both modules belong to different parts and are hence in different folders part1 and part2 respectively under the same directory. This is how the structure looks:
src/
part1/
module1.erl
part2/
module2.erl
Now module2 is dependent on module1, and calls various methods of module1 as module1:method(). I'm able to achieve full functionality when both module1.erl and module2.erl are in the same folder, but now they're in different folders, and I try to run module2.erl from part2 folder, I can't figure out how to allow module2 to compile and call the methods of module1.
Since the emulator is being used, the path to module1 is not in the code path by default when we are launching the emulator in the path of module2 directly and with default options. This can be verified using ...
1> code:get_path().
code:get_path().
[".","/usr/local/lib/erlang/lib/kernel-8.2/ebin",
"/usr/local/lib/erlang/lib/stdlib-3.17/ebin",
"/usr/local/lib/erlang/lib/xmerl-1.3.28/ebin",
"/usr/local/lib/erlang/lib/wx-2.1.1/ebin",
"/usr/local/lib/erlang/lib/tools-3.5.2/ebin",
"/usr/local/lib/erlang/lib/tftp-1.0.3/ebin",
"/usr/local/lib/erlang/lib/syntax_tools-2.6/ebin",
"/usr/local/lib/erlang/lib/ssl-10.6/ebin",
"/usr/local/lib/erlang/lib/ssh-4.13/ebin",
"/usr/local/lib/erlang/lib/snmp-5.11/ebin",
"/usr/local/lib/erlang/lib/sasl-4.1.1/ebin",
"/usr/local/lib/erlang/lib/runtime_tools-1.17/ebin",
"/usr/local/lib/erlang/lib/reltool-0.9/ebin",
"/usr/local/lib/erlang/lib/public_key-1.11.3/ebin",
"/usr/local/lib/erlang/lib/parsetools-2.3.2/ebin",
"/usr/local/lib/erlang/lib/os_mon-2.7.1/ebin",
"/usr/local/lib/erlang/lib/odbc-2.13.5/ebin",
"/usr/local/lib/erlang/lib/observer-2.10.1/ebin",
"/usr/local/lib/erlang/lib/mnesia-4.20.1/ebin",
"/usr/local/lib/erlang/lib/megaco-4.2/ebin",
"/usr/local/lib/erlang/lib/inets-7.5/ebin",
"/usr/local/lib/erlang/lib/hipe-4.0.1/ebin",
"/usr/local/lib/erlang/lib/ftp-1.1/ebin",
"/usr/local/lib/erlang/lib/eunit-2.7/ebin",
"/usr/local/lib/erlang/lib/et-1.6.5/ebin",
"/usr/local/lib/erlang/lib/erts-12.2/ebin",
"/usr/local/lib/erlang/lib/erl_interface-5.1/ebin",
[...]|...]
This list has . in it, but not ../part1, so when when we are compiling, been in the part2 directory, it fails...
2> c(module1).
c(module1).
{error,non_existing}
There are several ways to work around this, few simple ones could be...
c("../part1/module1.erl").. As per the documentation of c
...Module can be either a module name or a source file path, with or without .erl extension...
And here, in the option above, we used the relative path to the source file of module1.
Invoke erl with an option -pa which adds the path of part1 in the code path for that session of the erlang emulator.
part2$ erl -pa "../part1"
Erlang/OTP 25 [DEVELOPMENT] [erts-12.2] [source-c1ab4b5424] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
Eshell V12.2 (abort with ^G)
1> code:get_path().
["../part1",".","/usr/local/lib/erlang/lib/kernel-8.2/ebin",
"/usr/local/lib/erlang/lib/stdlib-3.17/ebin",
"/usr/local/lib/erlang/lib/xmerl-1.3.28/ebin",
"/usr/local/lib/erlang/lib/wx-2.1.1/ebin",
"/usr/local/lib/erlang/lib/tools-3.5.2/ebin",
"/usr/local/lib/erlang/lib/tftp-1.0.3/ebin",
"/usr/local/lib/erlang/lib/syntax_tools-2.6/ebin",
"/usr/local/lib/erlang/lib/ssl-10.6/ebin",
"/usr/local/lib/erlang/lib/ssh-4.13/ebin",
"/usr/local/lib/erlang/lib/snmp-5.11/ebin",
"/usr/local/lib/erlang/lib/sasl-4.1.1/ebin",
"/usr/local/lib/erlang/lib/runtime_tools-1.17/ebin",
"/usr/local/lib/erlang/lib/reltool-0.9/ebin",
"/usr/local/lib/erlang/lib/public_key-1.11.3/ebin",
"/usr/local/lib/erlang/lib/parsetools-2.3.2/ebin",
"/usr/local/lib/erlang/lib/os_mon-2.7.1/ebin",
"/usr/local/lib/erlang/lib/odbc-2.13.5/ebin",
"/usr/local/lib/erlang/lib/observer-2.10.1/ebin",
"/usr/local/lib/erlang/lib/mnesia-4.20.1/ebin",
"/usr/local/lib/erlang/lib/megaco-4.2/ebin",
"/usr/local/lib/erlang/lib/inets-7.5/ebin",
"/usr/local/lib/erlang/lib/hipe-4.0.1/ebin",
"/usr/local/lib/erlang/lib/ftp-1.1/ebin",
"/usr/local/lib/erlang/lib/eunit-2.7/ebin",
"/usr/local/lib/erlang/lib/et-1.6.5/ebin",
"/usr/local/lib/erlang/lib/erts-12.2/ebin",
[...]|...]
2> c(module2).
{ok,module2}
3> c(module1).
Recompiling /home/nalin/source/erlang/part2/../part1/module1.erl
{ok,module1}
4> module2:exec().
"Module2"
5> module1:exec().
"Module1"
6>
I hope this much should be sufficient to get you going. Also, you must take an opportunity to read through the Compilation and Code Loading to have some idea around what goes on.
WYSIWYG => WHAT YOU SHOW IS WHAT YOU GET
Related
I two modules in same src folder. mod1 declares function I wish to use in module mod2:
-module(mod1).
-export([myfunc/1]).
myfunc(A) -> {ok}.
In other module I not import mod1:
-module(mod2).
If I do "mod1:" in mod2 it recognizes "myfunc", problem is at run-time when I call mod1:myfunc(A) I get "undefined function mod1:myfunc/1"
I not understand why I get error if intellisense detect my mod1 function in mod2?
From the shell, you could try doing mod1:module_info(exports) to see the list of all the exported functions, though if your module is written as it is above, it should be generating a syntax error.
If, however, I'm wrong, and you actually do have it written properly in your module, (ie, it's just a typo here), try doing the following at the erlang shell:
c(mod1).
c(mod2).
And see if that works for you. This will compile and load the modules for you. If you don't have the module compiled (ie, it's just a .erl file in the directory), that's insufficient.
EDIT
Also, make sure that the beam files are being loaded properly when erlang launches. This is typically done by launching erl with erl -pa /path/to/beams
I am working on my first real project in erlang, however, this code is simplified for brevity. I want to be able to load a newer version of a file into my project remotely while it's running. I've read about using a behavior like gen_server or gen_fsm which has this for free. While that might achieve the result, I want to use this to learn how to do it, not just get it done. I've read the docs about code replacement, and LYSE's bit about Hot Code Loving, among other things, but I haven't been able to find anything that works for what I'm doing, so here is the basic idea.
-module(reloading).
-export([loop/0]).
loop() ->
receive
upgrade ->
?MODULE:loop();
hello ->
io:format("This is a test~n"),
loop();
_ ->
loop()
end.
I am simply looping with the idea that I can send the message upgrade and it will load a newer version of the code.
$ erl
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1> c(reloading).
{ok,reloading}
2> Loop = spawn(reloading, loop, []).
<0.39.0>
3> Loop ! hello.
This is a test
hello
At this point I change 10 line to io:format("I have changed this!~n"),
4> Loop ! upgrade.
upgrade
5> Loop ! hello.
This is a test
hello
I am expecting this hello call to print I have changed this! not This is a test. I know I can simply call c(reloading). and have this work the way expected, but I'm looking to send the actual project a message rather than manually updating the code. So where is my disconnect? What am I doing wrong, that I should be doing in order to hot load this code? As mentioned before, I am looking for a non-OTP solution for the sake of education.
For the sake of having an explicit answer, I am posting this.
Using #rvirding's suggestion of using the code module, I've modified it to look like this:
-module(reloading).
-export([loop/0]).
loop() ->
receive
upgrade ->
code:purge(?MODULE),
compile:file(?MODULE),
code:load_file(?MODULE),
?MODULE:loop();
hello ->
io:format("This is a test~n"),
loop();
_ ->
loop()
end.
First code:purge the old ?MODULE, then compile:file the new file, and finally, code:load_file the new ?MODULE.
This works as I originally intended.
$ erl
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1> Loop = spawn(reloading, loop, []).
<0.34.0>
2> Loop ! hello.
This is a test
hello
Change line to io:format("I have changed this!~n"),
3> Loop ! upgrade.
upgrade
4> Loop ! hello.
I have changed this!
hello
While erlang can handle two versions of a module and calling a function with mod:func(...) will always call the latest version of a module (if the function is exported) you still have to load the new version of the module into Erlang system. You can't expect it automagically detect that you happen to have a new version of the module somewhere, find it, compile it and load it.
N.B. compiling and loading are two separate things. So c(mod). both compiles and loads the module, while l(mod). just loads the object code (.beam file) of the already compiled module. The Erlang compiler is called from the module compile and it just compiles and generates a .beam file while the code loading is handled by the module code.
In addition to the above I'd like to notice that some tools that reload code automatically for you exist.
You should have a look at sync or active projects.
Compile *.beam locally, then send it to your server and reload it as mentioned in man pages:
http://erlang.org/documentation/doc-1/reference_manual/code_loading.html#id86381
-module(m).
-export([loop/0]).
loop() ->
receive
code_switch ->
m:loop();
Msg ->
...
loop()
end.
i need to extract some data from a 1 GB XML file into tables using
ets and dets.
I search the whole web and also in here but i didn't found any simple example
on how to handle big XML file.
For the beginning i just want to understand how to read the file without uploading the whole of it into memory.
Thnx.
come on ! What you need is a SAX XML parser called Erlsom. For small files, its possible to load it all into memory and then parse it as in the answer i gave to this question. But, for your case, these big files need the SAX method. The Sax examples are here.SAX ensures that you do not load a file into memory to parse it. The tokens that the parser gets , is what it gives to you. You will need an advanced skill of tail recursion, pattern matching and stateful programming.EDIT Now, download erlsom, and extract it into your erlang lib , a location where all built-in applications are located. Rename its extraction folder like this: erlsom-1.0. Create a file called: Emakefile in the erlsom-1.0 folder. Put this inside that file and save.
{"src/*", [verbose,report,warn_obsolete_guard,{outdir, "ebin"}]}.
The erlsom-1.0 folder, should look like this:
erlsom-1.0 |-doc/ |-ebin/ |-examples/ |-include/ |-src/ |-Emakefile
The rest of the other files do not matter. Now, open an erlang shell, whose pwd() is looking into the erlsom-1.0 folder. Run the function: make:all(). like this
Eshell V5.9 (abort with ^G)
1> make:all().
Recompile: src/ucs
Recompile: src/erlsom_writeHrl
Recompile: src/erlsom_write
Recompile: src/erlsom_ucs
Recompile: src/erlsom_simple_form
Recompile: src/erlsom_sax_utf8
Recompile: src/erlsom_sax_utf16le
Recompile: src/erlsom_sax_utf16be
Recompile: src/erlsom_sax_list
Recompile: src/erlsom_sax_lib
Recompile: src/erlsom_sax_latin1
Recompile: src/erlsom_sax
Recompile: src/erlsom_pass2
Recompile: src/erlsom_parseXsd
Recompile: src/erlsom_parse
Recompile: src/erlsom_lib
Recompile: src/erlsom_compile
Recompile: src/erlsom_add
Recompile: src/erlsom
up_to_date
2>
So, its done. So if the folder erlsom-1.0 is in your erlang lib, then, you can call the erlsom methods from any erlang shell whichever pwd() it may have.
Have you checked the xmerl library?
For reading big files and without loading it entirely into memory, you could use file:open/2, doing something like this:
{ok, FileHandler} = file:open(File, [read, raw, read_ahead]),
{ok, Line} = file:read_line(FileHandler)
Also, for working with XML, in Erlang you have xmerl, which unfortunately, is pretty poor documented.
I don't know Erlang, but it seems that it is possible to integrate C libraries. If you are willing to go that path, I can recommend that you have a look at the expat library. It is the quickes, light-weight xml parser library i know. A simple callback mechanism calls your code of each xml-element and you can decide for yourself whether you want to keep it in memory or if you want to skip it.
I know, this is very low-level. But for very large data this is, sadly, often the only way to do it.
Here is something I found googling: http://dudefrommangalore.blogspot.de/2009/04/erlang-xml-parser-comparison.html
This works in my erlang shell:
1> U = default_user_name().
2> crypto:start().
3> crypto:sha(U).
4> crypto:stop().
But when I compile this:
default_pw() ->
U = default_user_name(),
crypto:start(),
crypto:sha(U),
crypto:stop().
And execute it in the erlang shell, I get this:
1> person:default_pw().
** exception error: bad argument
in function port_control/3
called as port_control(crypto_drv04,5,<<"jDoe">>)
in call from crypto:control/2
Two questions:
1) What am I doing wrong?
2) It seems that I need to start and stop the crypto server. But is there a better place to start and stop it in my application?
Many thanks,
LRP
The error you are getting indicates that the crypto application was not started. An easy way to start it is just to add it as a parameter to erl like so:
$ erl -s crypto
I had a look at the current implementation of crypto and the past release notes for erlang and I came to the following conclusions (someone please correct me if I'm wrong):
Erlang releases <14A require crypto to be started prior to calling any functions because the library used a port driver. This makes sense because I got the error you described with 13B04 after not starting crypto.
Erlang releases >=14A don't require crypto to be started as the implementation now uses NIFs. This makes sense because the current implementation of crypto_server.erl is just a gen_server template, and on 14B03 I don't need to start the application in order to make crypto:sha/1 work.
I need to write my outputs from shell into a text file to keeping some required records. Can anyone please tell me how can I do this?
Thanks
If you have the data you wish to store as a single term you can read how here. In the simplest case you can just do file:write_file(Path, Data). If your data is more complex you may want to use io_lib:fwrite/2 to format it in a more readable way. For example:
Data = [1,2,3,{car, "honda"}],
file:write_file("/tmp/foo", io_lib:fwrite("~p.\n", [Data])).
tee command can capture shell output and save it to a file:
$ erl | tee output.txt
Eshell V5.8 (abort with ^G)
1> A = 5.
5
2> 5 + A.
10
3> ^Ca
$ cat output.txt
Eshell V5.8 (abort with ^G)
1> 5
2> 10
3>
There are many possibilities. Here's the first one which came to my mind.
In Erlang, every process is part of a group. For each group, a process - named group leader gets all the output from the group-mates. The shell process is part of the group init. So, what you could do is to change the group leader for the shell process by doing:
{ok, Log} = file:open("log", [write]),
erlang:group_leader(Log, self()).
You might want to create a dedicated process acting as group leader who manages the output in a more clever way. For example, it could wrap the file after a while or when the file reaches a certain size.
The problem with this approach is that you have to execute these lines any time you start your shell. Doing it by using the -s flag:
erl -s shell_log
where shell_log is:
-module(shell_log).
-export([start/0]).
start() ->
{ok, Log} = file:open("log", [write]),
erlang:group_leader(Log, self()).
won't work, because it's still too early (init is still in {starting, started}, as reported by init:get_status()).
In the same way, doing it by using the .erlang file in your HOME directory (whose lines are automatically executed every time you start a shell) will fail for a similar reason (init is still in the {starting, applications_loaded} state).
Not sure which is the best way to circumvent this problem. I'll think about it.
Finally, this question seems a duplicate of this thread.