You are currently browsing the archives for the code tag.

Protoml + Camlp4

A little update to this morning's article, I wrote a little camlp4 extension which makes it easier to user the prototype module (and it doesn't overwrite the records).

let _ =
  let p = {} in
  p.foo <- "p.foo";
  p.baz <- "p.baz";

  let o = {}|p| in
  o.foo <- "o.foo";
  o.bar <- (fun f -> f (o.baz));

  print_endline (p.foo);
  print_endline (p.baz);
  print_endline (o.foo);
  ((o.bar) : 'a->'b) print_endline;

Downloaded : 108 times
File : protoml.tar.gz
Size: 957 o

Prototype based OCaml

Talking about prototypes, here is a little module which allows prototype based programming in OCaml. I'll warn you right now : it's horrible, but funny.

type obj =
    Empty
  | Obj of (string, string) Hashtbl.t * obj

let create ?(proto=Empty) () = Obj (Hashtbl.create 111, proto)

let set o k v =
  match o with
    Empty -> raise Not_found
  | Obj (o, p) -> Hashtbl.replace o k (Obj.magic v)

let rec get o k =
  match o with
    Empty -> raise Not_found
  | Obj (o, p) ->
      try
        Obj.magic (Hashtbl.find o k)
      with Not_found -> get p k

There is nothing difficult to understand (it was actually difficult to do). An object is just a hashtable and a parent object. Typing is bypassed using Obj.magic

Let's have a little fun:

open Proto

let _ =
  let p = create () in
  set p "foo" "p.foo";
  set p "baz" "p.baz";

  let o = create ~proto:p () in
  set o "foo" "o.foo";
  set o "bar" (fun f -> f (get o "baz"));

  print_endline (get p "foo");
  print_endline (get p "baz");
  print_endline (get o "foo");
  ((get o "bar") : 'a->'b) print_endline;

The result:

$ ./prototest
p.foo
p.baz
o.foo
p.baz

Note : This is only a proof of concept, never use this in OCaml, it is not at all compliant with OCaml philosophy. It's funny, however :D

Jim, the JavaScript modal framework

Nowadays, there are a lot of Ajax and Web 2.0 JavaScript frameworks. This actually is a good thing, but I believe that a good ol' geek aspect is missing. That's why I developed Jim.

Jim is not :

  • An ajax framework
  • An animation framework

What Jim does:

  • Jim adds a command line interface to a webpage, inspired by vi
  • Jim allows easy developement of keyboard based applications

I know what you think, it sound like WTF?. Here is a simple example to help you understand. The commands are straightforward:

  • : opens the CLI
  • ESC closes the CLI
  • TAB autocompletion
  • Return to execute

If you've ever used a terminal emulator, it won't be difficult…
I've implemented 4 commands in the example:

  • echo : echo pli prints "pli"
  • eval : evaluates a javascript statement : eval "echo(1+1)"
  • set field value : sets the field field to value
  • submit : submit the pseudo form

You might ask how this is a framework, and I'd reply that it was made in such manner that it is possible to define custom commands the way you want. Here is the configuration file used in the example:

_('echo', echo);
_('eval', eval);

_('set', function(what, value) {
  $$('#'+what+' .value')[0].update(value);
},{
  suggestions: function (n, a) {
    switch (n) {
      case 1:
        return $$('.settable').pluck('id');
      case 2:
        switch (a.last())
        {
          case 'name':
            var names;
            new Ajax.Request('names.htm', {
              method: 'get',
              onSuccess: function (e) {
                names = eval(e.responseText);
              },
              asynchronous: false
            });
            return names;
          default:
            return Array();
        }
      default:
        return Array();
    }
  },
  callback: function (id, a) {
    $$('.settable').each(function(e) {
      e.down('.field').removeClassName('highlight');
    });
    if (id)
      if (a.length == 0)
       {
        $$('#'+id+'.settable')[0].down('.field').addClassName('highlight');
       }
  }
});

_('submit', function () {
  var params = {};
  var submit = true;
  $$('.settable').each(function (e) {
    var val = e.down('.value').innerHTML;
    if (val.blank())
     {
      err('Please fill in <b>all</b> fields');
      submit = false;
     }
    params[e.id] = val;
  });
  if (submit)
    new Ajax.Request('names.php', {
      parameters: params,
      onSuccess: function (e) {
        echo(e.responseText);
      }
    });
});

This is highly modular and allows almost all possible commands. I have had a few hesitations about polluting the namespace, but I add only three function echo err _, which can be renamed.

Downloaded : 123 times
File : jim-0.32.tar.gz
Size: 63 ko

List comprehension in OCaml

A nifty thing when working with list is to use list comprehension. This is something natural for a python programmer :

l1 = [(1,2),(2,3),(3,4),(4,5),(5,6),(6,7)]
# [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
l2 = [2*x+y for (x,y) in l1]
# [4, 7, 10, 13, 16, 19]
l3 = [x for x in l2 if x > 12]
# [13, 16, 19]

It is however absent from OCaml… Of course, it can be emulated:

let l1 = [1,2;2,3;3,4;4,5;5,6;6,7]  in
let l2 = (fun fmap l -> List.rev_map fmap (List.rev l)) (fun (x,y) -> 2*x+y) l1 in
let l3 = (fun ffilt fmap l ->
    let rev_filter f l =
      let rec aux d = fun
      [  [] -> d
      | [t::q] -> aux (if f t then [t::d] else d) q]
      in
      aux [] l
    in
    List.rev_map fmap (rev_filter ffilt l)) (fun x -> x > 12) (fun x -> x) l2
in ()

But this is really too much… Wouldn't it be nice to write something like that :

let l1 = [1,2;2,3;3,4;4,5;5,6;6,7]  in
let l2 = [+ 2*x+y | (x,y) <- l1] in
let l3 = [+ x | x <- l2 when x > 12] in
()

The [+ (* ... *)] indicates that this is a list comprehension. This actually is possible using camlp4 ;)

Downloaded : 108 times
File : listcomp.tar.gz
Size: 841 o

Using OCaml to write web scripts - 2

Yesterday I have explained how to use an OCaml .ml script as an executable, and how to display a web page written in OCaml. I'll explain here how to parse a querystring.

The querystring is passed as the environment variable QUERY_STRING. I'll use the following module to fetch the querystring and parse it :

module Get =
  struct
    let query_string = try String.lowercase (Sys.getenv "QUERY_STRING") with
    Not_found -> ""

    let _Hash =
      let return = Hashtbl.create 23 in
      let rec split c = function
          "" -> []
        |s when s.[0] = c -> ""::(split c (String.sub s 1 ((String.length s)-1)))
        |s ->
          begin
            match (split c (String.sub s 1 ((String.length s)-1))) with
               [] -> [String.make 1 (s.[0])]
            |t::q -> ((String.make 1 (s.[0]))^t)::q
          end
      in
      let query_list = split ‘&’ query_string in
      let rec q2h = function
        [] -> ()
       |t::q ->  (
         q2h q;
         match (split ‘=’ t) with
            [] -> ()
          | arg::[] -> Hashtbl.add return arg ""
          | arg::value::_ -> Hashtbl.add return arg value;) in
      q2h query_list;
      return
    let arg x = try Hashtbl.find _Hash x with Not_found -> ""
    let iter f = Hashtbl.iter f _Hash
  end

This is a simple module which allows us to do some simple stuff. Speeking of which, here is a simple example :

let e s = print_string s

let print_arg_val x y = e ("<i>"^x^"</i> : "^y^"<br/>\n")

let fibo n =
  try
    let rec fibo = function
      0 -> 1
     |1 -> 1
     |n -> fibo (n-1) + fibo (n-2)
    in
    string_of_int (fibo (int_of_string n))
  with _ -> ""

let _ =
  e "Content-type: text/html\n\n";

  e "<a href=\"test.ml?arg1=val1&arg2=val2&arg3=val3&n=15\">Examples</a><br/><br/>\n";
 
  e "<b>Get.query_string</b> : <br/>\n";
  e (Get.query_string^"<br/>\n");
  e "<br/>\n";

  e "<b>Get.arg \"arg2\"</b> : <br/>\n ";
  e ((Get.arg "arg2")^"<br/>\n");
  e "<br/>\n";

  e "<b>fibo (Get.arg \"n\")</b> :<br/>\n";
  e (fibo (Get.arg "n"));
  e "<br/>\n";
  e "<br/>\n";

  e "<b>Get.iter print_arg_val</b> : <br/>\n";
  Get.iter print_arg_val;

Those are only simple examples, and there are a lot of things to improve in order to use this in a real website (for example the conversion of url encoded characters, etc.).

But as I stated previously, I did not aim to write a CGI module for OCaml : use ocamlcgi instead, this one was really written to be used in real life.

Moreover, the following module might be useful if you want to plug a MySQL database to a web app writtent in ocaml : ocaml-mysql.

Last, by using camlp4, it should be possible to write scripts which look more like some PHP, using (for example) this kind of syntax : <?caml () ?> (everything which is not between those should just be sent of the output).

As a conclusion, it is possible to write dynamic web pages in OCaml, but is it really useful ? OCaml's strong typing can be a real pain in such context (no

echo

function ala PHP, etc.) but someone might find something useful to it.

Downloaded : 95 times
File : ocaml_script_cgi.tar.gz
Size: 1.3 ko