Skip to content
David Jeske edited this page May 14, 2017 · 4 revisions

Of all the languages out there, Irken has most in common with OCaml. In fact, Irken could be called a simplified OCaml with a Lisp (Scheme) syntax. Explaining the similarities and differences is a good way to understand Irken.

Before we get into the details, two of the biggest differences between the languages, and which we'd like to call out first, are..

  • Ocaml is mature, while Irken still in it's infancy with few programs written in it
  • Ocaml has extensive libraries and documentation, while Irken is sparsely documented with few libraries

In other words, Irken is very much still a research project, while OCaml has lots of 'real things' written in it. With that disclaimer aside...

Similarities

Both languages:

  • Are strong static typed, with Parametrics
  • Are Garbage Collected
  • Compile to native code
  • Have Global Type-Inference using Hindley-Milner extended with Row Polymorphism
  • Have immutable Static and Polymorphic Variants
  • Have Compile time macro expansion
  • Have pattern matching
  • Have a functional programming bias, yet support imperative side effects
  • Have Exceptions

Differences

  • Irken uses a Scheme inspired syntax with a few postfix operators, while OCaml syntax is a functional currying syntax
  • Irken does not allow type specifications in as many places as OCaml does
  • Irken records are row polymorphic, while OCaml records are not (instead OCaml object methods are row polymorphic)
  • Irken records fields are mutable, while OCaml record fields are immutable unless specifically declared mutable
  • OCaml variant forms exist in a global namespace, while Irken variant forms must be qualified with their type
  • OCaml uses currying (int -> int -> int) , while Irken applications have n-arity (int int -> int)
  • OCaml has a partial revelation system called signatures, Irken does not
  • OCaml has field punning, while Irken does not
  • OCaml has a module/namespace system, Irken (currently) does not
  • OCaml has an object mixin-style implementation inheritance system, Irken (currently) does not
  • OCaml has a REPL, while Irken (currently) does not

Static Variants

  type color_name = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White 
  type weight = Regular | Bold
  type color =
  | Basic of color_name * weight   (* color_name, regular and bold *)
  | RGB   of int * int * int       (* 6x6x6 color cube *)
  | Gray  of int                   (* 24 grayscale levels *)

[RGB (250,70,70); Basic (Green, Regular)]
- : color list = [RGB (250, 70, 70); Basic (Green, Regular)]
;; Note: a future change will allow variants with zero arguments to omit the surrounding ()s. 
;;
(datatype color_name (:Black) (:Red) (:Green) (:Yellow) (:Blue) (:Magenta) (:Cyan) (:White))
(datatype weight (:Regular) (:Bold))
(datatype color 
  (:Basic color_name weight)
  (:RGB int int int)
  (:Gray int))
(list (color:RGB 250 70 70) (color:Basic (color_name:Green) (weight:Regular))

Pattern Matching

let host_info_to_string 
   { hostname = h; os_name = os;
     cpu_arch = c; timestamp = ts; _ } =
        sprintf "%s (%s / %s, on %s)" h os c (Time.to_sec_string ts);;
(define host_info_to_string

Records

OCaml Records are non-polymorphic. The get_session_id function below must be for a specific record type. If a type declaration is not supplied, OCaml picks the most recent record type with a matching field name. Two functions are required, as one function can't get the session id out of different types of records. (to get Row Polymorphism in OCaml, one must use OCaml objects)

  type heartbeat =
    { session_id: string;
      time: Time.t;
      status_message: string;
    }
  type logon =
    { session_id: string;
      time: Time.t;
      user: string;
      credentials: string;
    }
  let get_session_id t = t.session_id                              (* function is ( login -> string ) *)
  let get_session_id_from_heartbeat (t:heartbeat) = t.session_id   (* function is ( heartbeat -> string ) *)

In Irken, records are row-polymorphic. The type {session_id=string ..} means any record containing a string session_id field, which may contain other fields as well. Only one get_session_id function is required.

(typealias heartbeat 
  {  session_id = string
     time = Time
     statis_message = string })
(typealias logon
  {  session_id = string
     time = Time
     user = string
     credentials = string })
(define get_session_id t -> t.session_id )  ;; function is ( {sesssion_id=string ...} -> string )

Polymorphic Variants

Polymorphic variants are a bit like static variants, except they don't belong to a named type. For example, here we see polymorphic variants put into a list in OCaml:

[ `Int 3 ; `Float 4. ; `Not_a_number ]

Here is the same code in Irken:

(list (:Int 3) (:Float 4.) (:Not_a_number))