I mentioned that I had some pseudo code comparing erlang and felix.
Anyway, rather than trying to get it perfect, here's what I got. The
code is based off of Joe Armstrong's book "Programming Erlang", which
happens to be quite interesting:

First the chat server in erlang:

########################################
chat_server.erl:
%% ---
%%  Excerpted from "Programming Erlang"
%%  Copyrights apply to this code. It may not be used to create
training material,
%%  courses, books, articles, and the like. Contact us if you are in doubt.
%%  We make no guarantees that this code is fit for any purpose.
%%  Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more
book information.
%%---

-module(chat_server).
-import(lib_chan_mm, [send/2, controller/2]).
-import(lists, [delete/2, foreach/2, map/2, member/2,reverse/2]).

-compile(export_all).

start() ->
    start_server(),
    lib_chan:start_server("chat.conf").

start_server() ->
    register(chat_server,
             spawn(fun() ->
                           process_flag(trap_exit, true),
                           Val= (catch server_loop([])),
                           io:format("Server terminated with:~p~n",[Val])
                   end)).

server_loop(L) ->
    receive
        {mm, Channel, {login, Group, Nick}} ->
            case lookup(Group, L) of
                {ok, Pid} ->
                    Pid ! {login, Channel, Nick},
                    server_loop(L);
                error ->
                    Pid = spawn_link(fun() ->
                                             chat_group:start(Channel, Nick)
                                     end),
                    server_loop([{Group,Pid}|L])
            end;
        {mm_closed, _} ->
            server_loop(L);
        {'EXIT', Pid, allGone} ->
            L1 = remove_group(Pid, L),
            server_loop(L1);
        Msg ->
            io:format("Server received Msg=~p~n",
                      [Msg]),
            server_loop(L)
    end.

lookup(G, [{G,Pid}|_]) -> {ok, Pid};
lookup(G, [_|T])       -> lookup(G, T);
lookup(_,[])           -> error.

remove_group(Pid, [{G,Pid}|T]) -> io:format("~p removed~n",[G]), T;
remove_group(Pid, [H|T])       -> [H|remove_group(Pid, T)];
remove_group(_, [])            -> [].
########################################

pseudo-felix:

########################################
include "lib_chan";
include "chat_group";

module Chat_server
{
  open List;
  open Assoc_list;

  union input_msg =
    | Login of Chat_client::input_channel * string * string
    | Closed of Chat_group::input_channel
  ;

  typedef input_channel = schannel[Return[input_msg,
Chat_group::input_channel]];
  typedef group_list_t = list[string*Chat_group::input_channel];

  proc start () {
    val chat_server = start_server ();
    Lib_chan::start chat_server;
  }

  gen start_server () : schannel[input_channel] =>
    spawn (proc (server_input:input_channel) {
      val v = server_input.server_loop Empty[group_list_t];
      println $ f"server terminated with: %S" v;
    })
  ;

  gen server_loop (server_input:input_channel) (gs:group_list_t) =>
    match server_input.read with
    | Msg $ Login (?client_channel, ?group, ?nick) =>
        let ?gs =
          match gs.find group with
          | Some ?group_channel =>
              let () = group_channel.write $ Chat_group::Login
(client_channel, nick) in
              gs
          | None[Chat_group::input_channel] =>
              let ?group_channel = Chat_group::start_group nick in
              gs + (group, group_channel)
          endmatch
        in
          server_input.server_loop gs

    | Msg $ Closed _ =>
        server_input.server_loop gs

    | Exit $ ?group_channel =>
        let ?gs = gs.remove_group group_channel in
        server_input.server_loop gs

    endmatch
  ;

  private fun remove_group (gs:group_list_t)
(g:schannel[Chat_group::input_channel]) =>
    match gs with
    | Cons ((_, ?x), ?t) when x == g => t
    | Cons (?h, ?t) => h + (remove_group gs t)
    | Empty => gs
    endmatch
  ;
}
########################################

You'll see that it actually looks quite similar to one another.
However, the felix code feels a lot heavier. Most of that comes from
the types I feel.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to