Erlang string to term

June 9, 2009

Evaluation of string to erlang’s term:

-module(evaluator_utils).
-export([eval_string/1]).

eval_string([]) -> []; 
eval_string(String) ->
    {ok, Tokens, _} = erl_scan:string(lists:concat([String, "."])),
    {Status, Term} = erl_parse:parse_term(Tokens),
    case Status of
        ok -> {ok, Term};
        error ->
            {_, _, ErrorMessage} = Term,
            {error, ErrorMessage}
    end.

Clojure tips: patterns matching

May 28, 2009

This is how it can be done in clojure:

user=> (defmulti fib (fn [x] x) :default :default)
#'user/fib
user=> (defmethod fib 0 [x] 0)
#<MultiFn clojure.lang.MultiFn@de1b8a>
user=> (defmethod fib 1 [x] 1)
#<MultiFn clojure.lang.MultiFn@de1b8a>
user=> (defmethod fib :default [n] (+ (fib (- n 2)) (fib (- n 1))))
#<MultiFn clojure.lang.MultiFn@de1b8a>
user=> (fib 32)
2178309
user=> (time (fib 32))
"Elapsed time: 3406.246008 msecs"
2178309
user=>

Factorial pattern matching:

(defmulti fac (fn [x] x) :default :default)
(defmethod fac 1 [x] 1)
(defmethod fac :default [n] (* n (fac (- n 1))))

Erlang tips: remote module loading

May 26, 2009

Context: when remote module pushing is needed.

Initial setup:
1. 2 nodes (physical nodes, each one having one erlang instance started): node1@10.0.0.1 and node2@10.0.0.2
2. both erlang instances must be started with the same cookie, in order to be able to successfully communicate

Steps:

(On node1, create test module)

-module(test).
-export([test_fun/0]).

test_fun() ->
    io:format("Hello ~s~n",["World"]).

(On node1, start erlang instance)

$ erl -name node1@10.0.0.1 -setcookie testcookie
Erlang R13B (erts-5.7.1) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.7.1  (abort with ^G)
(node1@10.0.0.1)1> 

(On node2, start erlang instance)

$ erl -name node2@10.0.0.2 -setcookie testcookie
Erlang R13B (erts-5.7.1) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.7.1  (abort with ^G)
(node1@10.0.0.2)1> 

(On node1, compile/load/remote load test module)

(node1@10.0.0.1)1> c(test).
{ok,test}
(node1@10.0.0.1)2> {Mod, Bin, _} = code:get_object_code(test).
{test,<<70,79,82,49,0,0,1,252,66,69,65,77,65,116,111,109,
        0,0,0,63,0,0,0,7,4,116,101,...>>,
      "/home/alin/test.beam"}
(node1@10.0.0.1)3> rpc:call('node2@10.0.0.2',erlang,load_module, [Mod, Bin]).
{module,test}
(node1@10.0.0.1)4> spawn('node2@10.0.0.2', test, test_fun, []).
Hello World
<8592.45.0>
(node1@10.0.0.1)5> 

(On node1, edit test.erl)

Instead of

... io:format("Hello ~s~n",["World"]).

set

... io:format("Hello ~s~n",["World2"]).

(On node1, go back to opened erlang shell)

(node1@10.0.0.1)5> f().
ok
(node1@10.0.0.1)6> c(test).
{ok,test}
(node1@10.0.0.1)7> {Mod, Bin, _} = code:get_object_code(test).
{test,<<70,79,82,49,0,0,1,252,66,69,65,77,65,116,111,109,
        0,0,0,63,0,0,0,7,4,116,101,...>>,
      "/home/alin/test.beam"}
(node1@10.0.0.1)8> rpc:call('node2@10.0.0.2',code,purge, [Mod]).
false
(node1@10.0.0.1)9> rpc:call('node2@10.0.0.2',erlang,load_module, [Mod, Bin]).
{module,test}
(node1@10.0.0.1)10> spawn('node2@10.0.0.2', test, test_fun, []).
<8592.48.0>
Hello World2
(node1@10.0.0.1)11> 

Note: node2 was not touched for anything else than starting (erl -name node2@10.0.0.2 -setcookie testcookie)

Done.

Erlang tips: standalone manual

May 24, 2009

Just run:

$ erl -man <module>

for instance:

$ erl -man erl
$ erl -man rpc
$ erl -man erlang

etc.

Erlang tips: starting embeded Yaws server

May 20, 2009

OS: Ubuntu 9.04

sudo apt-get install yaws

Create some document folder:

mkdir /home/alin/public_html

Add data to an test.html file, in order to be rendered:

echo '<html><body><div>Hello from Yaws!</div></body></html>' > /home/alin/public_html/test.html

erlang module for embedded yaws:

-module(test_yaws).
-export([start/1, stop/0]).

-define(YAWS_LIB,"/usr/lib/erlang/lib/yaws-1.80/ebin"). 

start(Port) ->
    code:add_path(?YAWS_LIB),
    SL=[{listen,{0,0,0,0}},
        {port,Port},
        {servername,"localhost"},
        {flags,[{dir_listings,true},{access_log,false}]}],
    GL=[{trace,false},{tmpdir,"/tmp"},{flags,[{auth_log,false},{copy_errlog,false}]}],
    yaws:start_embedded("/home/alin/public_html", SL, GL).

stop() ->
    code:add_path(?YAWS_LIB),
    yaws:stop().

Start embedded yaws:

$ erl
Erlang R13B (erts-5.7.1) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.7.1  (abort with ^G)
1> c(test_yaws).
2> test_yaws:start(5559).
=INFO REPORT==== 24-May-2009::18:28:35 ===
Yaws: Listening to 0.0.0.0:5559 for servers
 - http://localhost:5559 under /home/alin/public_html
ok
3> 

To check if everything is ok, go to: http://localhost:5559/ (listing of public_html folder will be done if no other resource is specified).
If accessing http://localhost:5559/test.html, “Hello from Yaws!” message will be displayed.

Haskell call function from main without using the return value

May 19, 2009

Few days ago I was stuck at some issue:
I wanted to do some profiling of ordinary fibonacci function written in Haskell but I didn’t wanted to display the result (using main function, from Main module). Guys from #haskell irc channel (irc.freenode.net) were very helpful and they guided me to evaluate and rnf

module Main where

import Control.Parallel.Strategies
import Control.Exception

fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib(n - 1) + fib(n - 2)

main = do
   evaluate(rnf (fib 32))

or, using function composition:

module Main where

import Control.Parallel.Strategies
import Control.Exception

fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib(n - 1) + fib(n - 2)

eval = evaluate . rnf
main = do
   eval(fib 32)

ghc --make Fib.hs
time ./Fib

and for better performance:

ghc --make -O2 Fib.hs
time ./Fib

Haskell like infinite sequences for clojure

April 10, 2009
  • Lazy Infinite list of numbers starting with 1:
  • Haskell:

    [1..]
    

    Clojure:

    (iterate inc 1)
    

  • Lazy list of numbers from 1 to 109:
  • Haskell:

    [1..109]
    

    Clojure:

    (range 1 110)
    

    Clojure “dumb” simple lazy example

    February 22, 2009

    user=> (def x (lazy-seq (cons (do (println "evaluated") (+ 1 2)) (list 1 2 3))))
    #'user/x
    user=> (def y (cons (do (println "evaluated") (+ 1 2)) (list 1 2 3)))
    evaluated
    #'user/y
    

    Clojure immutable collections for Java env

    February 22, 2009

    (Include clojure.jar in your lib path)

    List list = new PersistentList("t1");
    try {
    	list.add("t2");
    } catch (UnsupportedOperationException e) {
    	System.out.println("It seems that this operation is not supported.");
    }
    System.out.println("List size: " + list.size());
    
    Map map = new PersistentArrayMap(new Object[]{"key1", "value1"});
    try {
    	map.put("key2", "value2");
    } catch (UnsupportedOperationException e) {
    	System.out.println("It seems that this operation is not supported.");
    }
    System.out.println("Map size: " + map.size());
    

    This can be used as an alternative for
    java.util.Collections.unmodifiableList(…)

    Lazy clojure

    February 21, 2009

    Now, to demonstrate lazy vs. non-lazy behavior in clojure:

    (defn create-lazy [i] 
        (if (zero? i) 
        ()
        (lazy-seq (cons nil (create-lazy (dec i))))))
    
    (defn create-non-lazy [i] 
        (if (zero? i) 
        () 
        (cons nil (create-non-lazy (dec i)))))
    
    (create-lazy 1000000)
    (try (create-non-lazy 1000000)
        (catch java.lang.StackOverflowError e
            (println "StackOverflow error")))
    

    Of course, in real life situations, easier methods can be used, like

    user=> (replicate 7 nil)
    (nil nil nil nil nil nil nil)
    user=>
    


    Follow

    Get every new post delivered to your Inbox.