My version of erlang ‘Ring’ problem

I have been reading ‘Erlang Programming‘ , like a good student, I decided to solve the ring exercise:

Here is the problem in my words:

Create a linked list of N Ring where each Ring is an erlang process. When you pass a message to the head Ring , it should propagate the message to the  next Ring and that propagates to the next ring and so on. I added additional clause  — “Each ring should report its successful message delivery to the previous ring and the previous ring should print successful message delivery from its child rings.

Here is the code:

-module(ring).
-compile(export_all).


createRing(N) ->
    Self = self(),
    Head = spawn(fun() -> ring(N, Self) end),   
    Head.

ring(N, PreviousRing) when N > 0 ->
    Self = self(),
    io:format('~w #ring created PID: [~w] ListenerPid: [~w] ~n',[N, Self, PreviousRing]),
    NextRing = spawn(fun() ->
			     ring(N-1 , Self) end),
    loop(N ,NextRing, PreviousRing);

ring(N, PreviousRing) ->
    io:format('last ring reached! ~w ~n',[N]),
    NullRing = spawn(fun() -> 
			     receive
				 Any ->
				     io:format('dummy ring received ~w ~n', Any)
			     end
		     end),
    loop(N, NullRing, PreviousRing).



loop(N, NextRing, PreviousRing) ->
    receive
	{send_message, Message} ->
	    io:format('ring # ~w with pid: #~w received ~w ~n',[N, self(), Message]),
	    NextRing ! {send_message, Message},
	    PreviousRing ! {ok, self()},
	    loop(N, NextRing, PreviousRing);
	{ok, NextRing} ->
	    io:format('~w with pid# ~w successfully sent message ~n',[N-1, NextRing]),
	    loop(N, NextRing, PreviousRing);
	{quit} ->
	    io:format('quiting ring: ~w with Pid: ~w ~n',[N, self()])
    end.


sendMessage(Head, M) when M > 0 ->
    Head ! {send_message, M},
    sendMessage(Head, M - 1);
sendMessage(Head, M) ->
    io:format('sending last message ~n'),
    Head ! {send_message, M}.

I have had my share of multi-threaded programming in Java, thanks to the telephony applications I’v worked on. Just imagine the pain you would have to go through to implement this in Java / C++ !

Advertisements

Merge Sort implementation in Erlang

What else can you do in a dull Saturday evening 😉

-module (sorting).
-compile (export_all).

merge_sort([]) -> [];
merge_sort(L) ->
    {L1 , L2} = split(L),
    merge(merge_sort(L1),merge_sort(L2)).

merge(X , Y) ->
     merge(X,Y,[]).

merge([], [] , X) -> X;
merge([] , S2, X) -> X ++ S2;
merge(S1 , [], X) -> X ++ S1;
merge([H1 | T1] , [H2 | T2], X) when H1 >= H2 ->
    merge( [H1 | T1] , T2 , append(X,[H2])); %tail recursion
merge([H1 | T1] , [H2 | T2], X) ->
     merge( T1 , [H2 | T2], append(X,[H1])). %tail recursion 

append(X , Y) ->
      X ++ Y. % appending two list ! how cool!

split(L) ->
    split(L , {[] , []}).

split([] , {X , Y}) -> { X , Y };
split([H|T] , {X , Y}) ->
    split( T , { Y , append(X , [H]) }). %tail recursion

How to setup Emacs as Erlang IDE on Windows XP

There are a dozens of links in the web for setting up erlang as an emacs IDE with syntax highlighting, indentation, compilation , debugging support. However, none of them is as straight forward as this one HERE. However, this was written for linux boxes. You can replace the linux relative paths with your windows relative paths. Just keep the following points in mind.

  • Erlang default installation path “C:\Program Files\erl5.6.3” is not supported by Distel (because of the whitespace in ‘Program Files’). You can either install erlang in a different location (C:\erl5.6.3), or use shortcut path location : “C:/progra~1/erl5.6.3”
  • You don’t have to checkout the distel code with svn if you don’t have svn client. You can download it directly from HERE.

Just in case, I am pasting my .emacs file here

;; This is needed for Erlang mode setup
(setq erlang-root-dir "c:/progra~1/")
(setq load-path (cons "C:/progra~1/erl5.6.3/lib/tools-2.6.1/emacs" load-path))
(setq exec-path (cons "c:/progra~1/erl5.6.3/bin" exec-path))
(require 'erlang-start)

;; This is needed for Distel setup
(let ((distel-dir "C:/dev/erlang/distel/elisp"))
  (unless (member distel-dir load-path)
    ;; Add distel-dir to the end of load-path
    (setq load-path (append load-path (list distel-dir)))))

(require 'distel)
(distel-setup)

;; Some Erlang customizations
(add-hook 'erlang-mode-hook
	  (lambda ()
	    ;; when starting an Erlang shell in Emacs, default in the node name
	    (setq inferior-erlang-machine-options '("-sname" "emacs"))
	    ;; add Erlang functions to an imenu menu
	    (imenu-add-to-menubar "imenu")))

;; A number of the erlang-extended-mode key bindings are useful in the shell too
(defconst distel-shell-keys
  '(("\C-\M-i"   erl-complete)
    ("\M-?"      erl-complete)
    ("\M-."      erl-find-source-under-point)
    ("\M-,"      erl-find-source-unwind)
    ("\M-*"      erl-find-source-unwind)
    )
  "Additional keys to bind when in Erlang shell.")

(add-hook 'erlang-shell-mode-hook
	  (lambda ()
	    ;; add some Distel bindings to the Erlang shell
	    (dolist (spec distel-shell-keys)
	      (define-key erlang-shell-mode-map (car spec) (cadr spec)))))