You are currently browsing the archives for the ocaml tag.

Joo, JavaScript on OCaml

My readers might have noticed that I really like JavaScript and OCaml. Thus, it's natural to write a webserver in OCaml which serves scripts written in JavaScript. Crazy ? Maybe a little, but as the guys from mod_js said: others do worse.

I started by modifying Thumper which I slightly modified (in order to deal with post queries). Then I added OCaml CGI to encode and decode queries, SpiderCaml which includes SpiderMonkey in OCaml and OCaml Mysql to use MySQL. Actually this was more like doing Lego than coding…

What can it do ?
URIs are parsed as : /module/action/arg1/arg2/arg3. This will execute Module.action(arg1, arg2, arg3), where Module is defined in the file modules/module.js. The default module being home and the default action, index.

This being said, their is a Joo object in the global namespace which contains useful stuff:

// headers
for (e in Joo.Headers) print(e+" "+Joo.Headers[e]+"<br/>");

//  GET
for (e in Joo.Get) print(e+" "+Joo.Headers[e]+"<br/>");

// POST
for (e in Joo.Post) print(e+" "+Joo.Headers[e]+"<br/>");

// a mysql wrapper
Joo.mysql.connect({
    host:"localhost",
    user:"user",
    name:"database"
  });
Joo.mysql.query('select * from foo');
while(r = Joo.mysql.fetch()) print(r.id + "<br/>");

// an include function
Joo.include('foo/bar.js');

Note : the print function just adds text to the output buffer, their is no control on the flushing, sorry. Everything is sent at the end.
Moreover, I have added the MIME types only for html and jpeg files, you may want to add other MIME types in main.ml

Downloaded : 112 times
File : joo.tar.gz
Size: 47.1 ko

Sandclick

Often when I feel depressed I have this imperious need to create something, anything. And those days, I'm not so well, so I code quite a lot. Let me introduce you to Sandclick, a stupid little game written in less than an hour in OCaml. The code is awful, but nevermind…

First, what does it look like ?

I bet most of you have already played to those games where you have to click on colored boxes on a grid to make them disappear. Sandclick is exactly this king of game, the only difference is in the way it deals with falling boxes.

Usually, in those games, when a colored block is above and empty space, it falls into it. In Sandclick, blocks fall like sand : grains can fall on the side, here is what happens when there is an empty space:

  • if there is something above, this something falls down
  • if not, then the content of what is on the top left or top right falls

And it goes on and on until it stabilizes.

Downloaded : 138 times
File : sandclick.tar.gz
Size: 9.5 ko

OCaml zipper and holidays

This blog will be in holidays until the 15th of August. This is a little something to keep you busy while waiting for my holiday pictures : a light and nifty implementation of list zippers.

Basically a zipper is a list which has a cursor, thus reading and moving through is non destructive.

sig
  type 'a t = 'a list * 'a list
  exception Out_of_bound
  exception End_of_zip
  val empty : 'a Zip.t
  val next : 'a Zip.t -> 'a Zip.t
  val previous : 'a Zip.t -> 'a Zip.t
  val first : 'a Zip.t -> 'a Zip.t
  val last : 'a Zip.t -> 'a Zip.t
  val get : 'a Zip.t -> 'a
  val insert : 'a -> 'a Zip.t -> 'a Zip.t
  val delete : 'a Zip.t -> 'a Zip.t
  val replace : 'a -> 'a Zip.t -> 'a Zip.t
  val rev : 'a Zip.t -> 'a Zip.t
  val append : 'a Zip.t -> 'a Zip.t -> 'a Zip.t
  val iter : ('a -> unit) -> 'a Zip.t -> unit
  val chop : 'a Zip.t -> 'a Zip.t
  val from_list : 'a list -> 'a Zip.t
  val to_list : 'a Zip.t -> 'a list
end

A simple example :

open Printf

let _ =
  let print = function
      b, [] -> List.iter (printf " %d") (List.rev b); printf ".\n"
    | b, c::a -> List.iter (printf " %d") (List.rev b); printf ".%d" c; List.iter (printf " %d") a; printf "\n"
  in
  let z = Zip.empty in
  let z = Zip.insert 5 z in
    print z;
  let z2 = Zip.from_list [1;2;3;4] in
    print z2;
  let z = Zip.append z2 z in
    print z;
  let z = Zip.next z in
    print z;
  let z = Zip.next z in
    print z;
  let z = Zip.next z in
    print z;
  let z = Zip.previous z in
    print z;
  let z = Zip.last z in
    print z;
  let z = Zip.previous z in
    print z;
  let z = Zip.previous z in
    print z;
  let z = Zip.previous z in
    print z;
  let z = Zip.insert 7 z in
    print z;
  let z = Zip.replace 9 z in
    print z;
  let z = Zip.delete z in
    print z

Its result :

.5
.1 2 3 4
.1 2 3 4 5
 1.2 3 4 5
 1 2.3 4 5
 1 2 3.4 5
 1 2.3 4 5
 1 2 3 4 5.
 1 2 3 4.5
 1 2 3.4 5
 1 2.3 4 5
 1 2.7 3 4 5
 1 2.9 3 4 5
 1 2.3 4 5

Downloaded : 113 times
File : ml_zipper.tar.gz
Size: 1 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

Ocaml et hexadécimal

Je vois qu'il y a beaucoup de gens qui tombent sur mon blog en cherchant "ocaml hexadecimal". Et ils doivent être décus de ne rien trouver… C'est pourquoi j'ai décidé d'écrire rapidement un petit quelque chose à ce sujet là.

Tout d'abord, il faut savoir qu'en caml, les choses suivantes sont équivalentes :
# 0xf;;
- : int = 15
# 0o17;;
- : int = 15
# 0b1111;;
- : int = 15
# 15;;
- : int = 15

Le premier est écrit en hexadécimal, le second en ocal, le troisième en binaire, et le dernier en décimal. Donc la gestion de l'hexadécimal en OCaml est native.

Une des utilisations courantes de l'hexadécimal est pour représenter les couleurs en 65536 couleurs. Pour convertir un entier en tuple r,g,b on peut utiliser la fonction suivante :

let hex_to_rgb n =  (n / 0×10000, (n/0×100) mod 0×100, n mod 0×100)

Dans l'autre sens, c'est un peu plus compliqué : en effet, en mémoire tous les entiers sont stockés de la même manière (int31 à la caml), et on s'en fiche de savoir sous quelle forme ils sont entrés. Mais ce n'est pas un drame ; effectivement, on a besoin d'avoir un entier sous forme hexadécimale principalement pour l'affichage, donc on utilise les fonctions du module Printf1 :

let print_hexa = printf "0x%x"

Je vous renvoie à la documentation du module Pervasives pour plus de détails.

Espérons que maintenant ceux qui passeront ici en cherchant ocaml hexadécimal repartirons heureux ;)

  1. C'est la seule exception à la règle ne jamais faire un open Module en début de fichier []