Language extensions introduced in Batteries Included

Several language extensions and convenience features are introduced in Batteries Included. To take advantage of these features, please see the corresponding chapter.

Comprehension expressions

(activated by default, implemented as findlib package batteries.pa_comprehension.syntax)
(designed for Batteries)
A list comprehension syntax for batteries, using enumerations by default.

Output, generators and guards

The global form is [? output | comp_item ; comp_item ; ... ?].
output is an expression and a comp_item is either a guard (a boolean expression), or a generator of the form pattern <- expression. Variables bound in the pattern can be used in the following comprehension items, and in the output expression.

Example :
let pythagorean_triples n =
  [? (a,b,c) | a <- 1--n; b <- a--n; c <- b--n; a*a + b*b = c*c ?]

Module parametrization

By default, the output in an enumeration, and generator expressions are assumed to be enumerations. It is possible to choose a different data structure with the module : expression syntax.

Examples :
let positive_array_of_enum e =
  [? Array : n | n <- e; n > 0 ?]

let combine la lb =
  [? List : (a, b) | a <- List : la; b <- List : lb ?]

Comprehension expressions rely on the presence in the given module of the following operations (where 'a t represents the data-structure type : 'a array, 'a Enum.t...) :

val filter : ('a -> bool) -> 'a t -> 'a t
val concat : 'a t t -> 'a t
val map : ('a -> 'b) -> 'a t -> 'b t
val filter_map : ('a -> 'b option) -> 'a t -> 'b t (* used for refutable patterns in generators *)

val enum : 'a t -> 'a Enum.t
val of_enum : 'a Enum.t -> 'a t

If your module does not provide the first four operations but only the enum conversion functions, you could still benefit from the comprehension syntax by using eg. foo <- Mod.enum bar instead of foo <- Mod : bar.

String syntax

(activated by default, implemented as findlib package batteries.pa_string.syntax)
(part of estring, adapted for Batteries by the author)
As Batteries offers several new types of strings, this extension provides the necessary syntactic sugar to manipulate unicode strings naturally.

Text values

Declaring a Rope is as simple as

let foo = r"Some Unicode text (Latin-1 encoded)"
let bar = ur"Some Unicode text (UTF-8 encoded)"

This defines a new value foo, with type Rope.t, the type of (immutable) Unicode ropes. Of course, this manipulation doesn't have to happen at the highest-level:

let append_string_to_rope x = Rope.append x (r"Some more Unicode text")

Note that ropes, being immutable, are automatically optimized, i.e. this is equivalent to

let some_unique_name = Rope.of_latin1 "Some more Unicode text"
let append_string_to_rope x = Rope.append x some_unique_name
It is possible to use the same syntax to define
Mutable UTF-8 strings
e.g. u"Some UTF-8 string", with type UTF8.t
Immutable Latin 1 strings (with capabilities)
e.g. ro"Some read-only string", with type [`Read] String.Cap.t
Mutable Latin 1 strings (with capabilities)
e.g. rw"Some read-write string", with type [`Read | `Write] String.Cap.t
Write-only Latin 1 strings (with capabilities)
e.g. wo"Some write-only string", with type [`Write] String.Cap.t
Again, immutable latin-1 strings are automatically optimized.

Text patterns

The same syntax may be used to pattern-match against ropes, UTF-8 strings and string with capabilities.

Lazy List syntax

A few new constructs are added to make using lazy lists easier. As an expression, [%] is a shortcut for lazy BatLazyList.Nil, the empty lazy list.

For pattern matching, the empty lazy list can be matched in the same way; | [%] matches lazy BatLazyList.Nil. To destructure lazy lists, | a %:: b is the same as lazy BatLazyList.Cons(a,b).