Introduction to O'LablObjective Label extends Objective Caml in 3 ways.
All these features are sound with respect to type checking, and integrate smoothly with other parts of O'Caml, like objects and classes.However, except for Smalltalk, it seems that this possibility is not used very much in actual programming. Since in Ada and Common Lisp use of these labels in function calls is facultatory, programmers will most often ommit them.
Reflecting their success in the SmallTalk community, labels in O'Labl are SmallTalk style, with the possibility of providing different call patterns through optional parameters. Moreover they can be combined with Currying to allow out-of-order partial applications.
String.blit : string -> int -> string -> int -> int -> unit String.blit s1 0 s2 0 (String.length s1)
String.blit : string -> pos:int ->
to:string -> to_pos:int -> len:int -> unit
String.blit s1 pos:0 to:s2 to_pos:0 len:(String.length s1)
List.fold_left
(fun st x ->
....
....)
a l
List.fold_left l st:a
fun:(fun x st:st ->
....
....)
# String.blit to:s2 to_pos:0;; - : string -> pos:int -> len:int -> unit = <fun>
In O'Labl this is also possible with functions, within the limits of the type system. That is, the same function may have different call patterns, but they must all
For instance, we can define a powerful string_copy function, based on the above String.blit function.
# let string_copy s1 to:s2 ?:pos [< 0 >] ?:to_pos [< 0 >]
?:len [< min (String.length s1 - pos) (String.length s2 - to_pos) >]
= String.blit s1 :pos to:s2 :to_pos :len ;;
val string_copy : string -> to:string ->
?pos:int -> ?to_pos:int -> ?len:int -> unit
# let string_copy s1 to:s2 ?pos:opos1 ?to_pos:opos2 ?len:olen =
let pos1 = match opos1 with None -> 0 | Some x -> x in
let pos2 = match opos2 with None -> 0 | Some x -> x in
let len = match olen with Some -> x
| None -> min (String.length s1 - pos1) (String.length s2 - pos2)
in String.blit s1 pos:pos1 to:s2 to_pos:pos2 len:len ;;
Calling a function with optional parameters is done exactly the same way as without optionals.
# let s1 = "12345" and s2 = "12345678";; val s1 : string = "12345" val s2 : string = "12345678" # string_copy s1 to:s2;; > String.blit s1 to:s2 pos:0 to_pos:0 len:5 - : unit = () # string_copy s1 to:s2 len:3;; > String.blit s1 to:s2 pos:0 to_pos:0 len:3 - : unit = () # string_copy s1 to:s2 pos:2;; > String.blit s1 to:s2 pos:2 to_pos:0 len:3 - : unit = ()
# string_copy to:s2 to_pos:2;; - : string -> ?pos:int -> ?len:int -> unit = <fun>
You will mainly use them in two cases:
The first case happens when objects take their values in different ranges.
type number = [int(int) float(float)] and basic = [int(int) float(float) bool(bool) char(char) string(string)]
# let print_basic = function
`int i -> print_int i
| `float x -> print_float x
| `bool b -> print_bool b
| `char c -> print_char c
| `string s -> print_string s ;;
val print_basic : [<int(int) float(float) bool(bool) char(char) string(string)] -> unit
# print_basic (`char 'a');;
a- : unit
# print_basic (`int 1 : number);;
1- : unit
val search_string : string -> in:string -> mode:[exact subcase regexp] -> index
For more detailed information, see the manual.