Previous week Up Next week

Hello

Here is the latest OCaml Weekly News, for the week of March 04 to 11, 2014.

  1. Core Suite 111.03.00
  2. I never succeeded in using Format
  3. Batteries Included syntax extensions?
  4. Other OCaml News

Core Suite 111.03.00

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2014-03/msg00031.html

Ben Millwood announced:
I am pleased to announce the 111.03.00 release of the Core suite.

The following packages were upgraded:

- async
- async_extra
- async_kernel
- async_unix
- bin_prot
- core
- core_extended
- core_kernel
- custom_printf
- jenga
- ocaml_plugin
- re2
- sexplib
- textutils

In addition, with this release we are including a new package:

- enumerate, a syntax extension for enumerating finite types.

Files and documentation for this release are available on our website
and all packages are in opam:

https://ocaml.janestreet.com/ocaml-core/111.03.00/individual/
https://ocaml.janestreet.com/ocaml-core/111.03.00/doc/

Here is the list of changes for this version:

# 111.03.00

## async_extra

- Add `?max_connections:int` argument to `Rpc.Connection.serve`.

`max_connections` is passed to `Tcp.Server.create`, and limits the
number of connections that an Rpc server will accept.

- Improved `Log.Rotation`:

- Made `Log.Rotation.t` abstract; use `create` rather than an
explicit record.
- Added a `` `Dated`` `naming_scheme`.
- Add `Log.Rotation.default`, for getting a sensible default
rotation scheme.
- Added an optional (but discouraged) option to symlink the latest
log file.
- Every log rotation scheme has an associated `Time.Zone.t`.
- Changed the internal representation of `Log.Rotation.t`, but
`t_of_sexp` is backwards compatible, so existing config files will
continue to work.

- Changed `Udp.bind_any` to use `Socket.bind ~reuseaddr:false`, to
ensure a unique port.
- Added `Tcp.Server.listening_socket`, which returns the socket the
server is listening on.

Changed `Tcp.Server` so that if the listening socket is closed, the
server is closed.

- Added to `Udp.Config.t` a `max_ready : int` field to prevent UDP
receive loops from starving other async jobs.
- Improved `File_tail` to cut the number of `fstat` calls in half.

`File_tail` uses a stat loop to monitor a file and continue reading
it as it grows. We had made two `fstat` invocations per loop
iteration, using `Async.Std.Unix.with_file` which constructs an
`Fd.t` and therefore does it own `fstat`. Switching to
`Core.Std.Unix.with_file` with `In_thread.run` eliminated the extra
`fstat`.

## async_unix

- Improved `Socket.accept` to abort and return `` `Socket_closed`` when
the file descriptor underlying the socket is closed.
- Added to `Socket.bind` a `?reuseaddr:bool` argument, preserving the
default as `true`.
- Added `Fd.close_started`, which becomes determined when `close` is
called on an `Fd.t`.

## bin_prot

- Fixed build on ARM.

## core

- Added `Unix.Syslog` module.
- Changed `Command.run` to no longer ignore the first element of its
`~argv` parameter.
- Made `Time.Span.to_short_string` show microsecond precision.

## core_extended

- Added `Set_lang`, a DSL for sets with constants, union, intersection,
and difference.
- In `Process`, use `epoll` rather than `select` when possible,

This prevents errors when selecting on file descriptors numbered
greater than `FD_SETSIZE` (1024).

- Removed `Syslog` module. There is now `Unix.Syslog` in core instead;
the APIs are not compatible, but they are similar.

## core_kernel

- Added `Error.to_string_hum_deprecated` that is the same as
`Error.to_string_hum` pre 109.61.
- Changed `Error.to_string_hum` so that
`Error.to_string_hum (Error.of_string s) = s`.

This fixed undesirable sexp escaping introduced in 109.61 and
restores the pre-109.61 behavior for the special case of
`Error.of_string`. A consequence of the removal of the custom
`to_string_hum` converter in 109.61 was that:

Error.to_string_hum (Error.of_string s) = Sexp.to_string_hum (Sexp.Atom
s)

That introduced sexp escaping of `s`.

- Added to `Doubly_linked` functions for moving an element
within a list.

val move_to_front : 'a t -> 'a Elt.t -> unit
val move_to_back : 'a t -> 'a Elt.t -> unit
val move_after : 'a t -> 'a Elt.t -> anchor:'a Elt.t -> unit
val move_before : 'a t -> 'a Elt.t -> anchor:'a Elt.t -> unit

- Improved `Core_map_unit_tests.Unit_tests` to allow arbitrary data
in the map, not just `ints`.

This was done by eta expansion.

## custom_printf

- Simplified the code generated by `pa_custom_printf` to make it
more readable.

## re2

- Fixed a bug with `replace_exn` and anchoring.

Fixed this bug:

$ R.replace_exn ~f:(fun _ -> "a") (R.create_exn "^") "XYZ";;
- : string = "aXaYaZa"
$ R.replace_exn ~f:(fun _ -> "a") (R.create_exn "^X") "XXXYXXZ";;
- : string = "aaaYXXZ"

## textutils

- Changed `Textutils.Console` to not reference `Async.Log`, so that
building inline benchmark runners no longer requires building `Async`.

The change makes `Textutils`, and by extension `Core_extended` and
`Core_bench`, not depend on `Async`.
      

I never succeeded in using Format

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2014-03/msg00025.html

Matthieu Dubuget asked:
Is the following behaviour expected, or a misunderstanding of mine?

In short, I'd like to use the Format module to prepare an
output inside a Buffer.t. But a basic <hov> box does not
break lines as I would expect, while printf does.

OCaml version 4.01.0

# open Format;;
# printf "@[<hov0>111,@,222,@,333,@,444,@,555,@,666@]@.";;
111,222,333,444,555,666
- : unit = ()
# set_margin 9;;
- : unit
= ()
# printf "@[<hov0>111,@,222,@,333,@,444,@,555,@,666@]@.";;
111,222,
333,444,
555,666
- : unit
= ()
# sprintf "@[<hov0>111,@,222,@,333,@,444,@,555,@,666@]@.";;
- : string
=
"111,222,333,444,555,666\n"

Why doesn't sprintf exhibit the same behaviour as printf?
Trying with fprintf…

# fprintf str_formatter "@[<hov0>111,@,222,@,333,@,444,@,555,@,666@]@.";;
- : unit
= ()
# flush_str_formatter ();;
- : string
=
"111,222,333,444,555,666\n"
      
Jeremy Yallop replied:
The set_margin function only affects std_formatter:

   https://github.com/ocaml/ocaml/blob/8ba031a/stdlib/format.ml#L1027

You need to use pp_set_margin for other formatters.
      
Benoit Vaugon also suggested:
The set_margin function configure the std_formatter, ie the formatter of
the standard output (the one used by printf). To change the margin when
printing in a buffer, you can run something like this :

# open Format;;
# let buf = Buffer.create 16;;
val buf : Buffer.t = <abstr>
# let formatter = formatter_of_buffer buf;;
val formatter : Format.formatter = <abstr>
# pp_set_margin formatter 9;;
- : unit = ()
# fprintf formatter "@[<hov0>111,@,222,@,333,@,444,@,555,@,666@]@.";;
- : unit = ()
# Buffer.contents buf;;
- : string = "111,222,\n333,444,\n555,666\n"
      
Martin Jambon later suggested:
Note that I made a library called easy-format that supposedly makes it
easier to pretty-print code exactly the way you want:

project page:
 http://mjambon.com/easy-format.html

sample code + output:
 http://mjambon.com/easy_format_example.html
      
Raphaël Proust then added, and Oleg replied:
> Another alternative to format for pretty-printing code (or other things): PPrint
>
> Release blog post (with some examples of use):
> http://gallium.inria.fr/blog/first-release-of-pprint/
> Documentation: http://gallium.inria.fr/~fpottier/pprint/doc/PPrint.html
> Installation instruction: `opam install pprint`

That formatter uses Wadler's Pretty-printer, which is not optimal. The
optimal one takes linear time in the size of the document (regardless
of the page width), and, for constant page width, formats documents of
any size in constant space. It is obviously incremental and has
bounded latency. There are several optimal formatters. The recent one
was based on simple generators, described in
        http://okmij.org/ftp/continuations/PPYield/index.html#pp

Curiously, a Clojure programmer has read our paper and re-wrote the
algorithm in Clojure -- without any help from us. It seems he is very
satisfied with the results:
        https://github.com/brandonbloom/fipp
That web page has a few examples.
      
Bob Atkey then asked and Oleg replied:
> Have you compared your implementation to Christian Lindig's 'Strictly Pretty'?:
> 
>    http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.2200
> 
> I think the runtime of his implementation is dependent on page width,
> due to repeated use of the fits function to measure whether a group
> fits within the current line. A simple optimisation is to precompute
> this width, as (I think) you do. I did this in my simple
> implementation of Lindig's idea:
> 
>    https://github.com/bobatkey/pretty-monospace/blob/master/lib/Pretty.ml
> 
> Neither of these implementations are incremental though; both require
> the entire document to be present up front.
> 

Thank you for the reference! I should compare with his and your
implementations.

Our pretty-printer is designed from the outset to be incremental. It
operates on a stream of tokens: text-string, newline, begin-group,
end-group.  It is literally a functional composition of four stream
transformers which annotate the stream tokens and then format them,
outputting chunks of the final text. The formatting is simple if the
begin-group token is annotated with the width of the corresponding
group. The key idea is that we need to know this width only up to the
point: if it exceeds the page width, we don't need to know by how
much. So, computing this annotation requires only a bounded
look-ahead. It is crucial for the performance to use a sequence data
structure with the amortized constant-time addition and removal on
both ends. Standard libraries of Haskell and Clojure luckily provide
such a data structure.
      

Batteries Included syntax extensions?

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2014-03/msg00035.html

Yotam Barnoy asked and Simon Cruanes replied:
> I have a question about Batteries Included. Specifically, how do I get the
> syntax extensions working and which syntax extensions are available? The
> various bits of documentation I've found seemed either contradictory or did
> not mention any syntax extensions at all. I'm specifically interested in
> things like automatic rope generation and list comprehensions.

The current version of Batteries is 2.2.0 and its documentation is here:
http://ocaml-batteries-team.github.io/batteries-included/hdoc2/ . As far
as I know, there are no more syntax extensions in Batteries since 2.0.0
(which explains why it doesn't depend on camlp4). I don't know much
about the "rope generation" you talk about, but list comprehensions are
nicely replaced (imho) by the |> operator:

List.range 1 `To 10
    |> List.filter (< 5)
    |> List.map string_of_int

You can ask more questions on the Batteries mailing list
( https://lists.forge.ocamlcore.org/cgi-bin/listinfo/batteries-devel ).
Hope you will find it helpful!
      
Arnaud Spiwack then added:
List comprehension in a few (non-syntax checked) lines. TL;DR: list
comprehension = monadic combinators.

let return a = [a]
let (>>=) x f = List.(flatten (map f x))
let (>>) x y = x >>= fun () -> y
let guard b = if b then [()] else []

With these combinators

[ f (x,y) | x <- l ; y <-r ; x=y+1 ]

then translates to

l >>= fun x ->
r >>= fun y ->
guard (x=y+1) >>
return (f x)

Less compact, no doubt, but still reasonably practical.
      
Ivan Gotovchits then said and ygrek added:
> By the way, list comprehension is already included in standard ocaml
> distribution. It is not as mighty as batteries one, and slightly differs
> in syntax:
> 
> [ x / 2 | x <- [ 2;4;6] ]

$ ocaml
        OCaml version 4.00.1

.ocamlinit done
# #camlp4o;;
	Camlp4 Parsing version 4.00.1

# #require "camlp4.listcomprehension";;
# [ x / 2 | x <- [ 2;4;6] ];;
- : int list = [1; 2; 3]
      

Other OCaml News

From the ocamlcore planet blog:
Thanks to Alp Mestan, we now include in the OCaml Weekly News the links to the
recent posts from the ocamlcore planet blog at http://planet.ocaml.org/.

An original programming pattern in Mezzo:
  http://gallium.inria.fr/blog/mezzo-control-flow-inversion

From Jekyll site to Unikernel in fifty lines of code.:
  http://amirchaudhry.com/from-jekyll-to-unikernel-in-fifty-lines

GUI Event Handling with a Functional Hierarchical State Machine:
  http://cranialburnout.blogspot.com/2014/03/gui-event-handling-with-functional.html

OCaml EFL 1.9.0 and 1.8.2 released:
  https://forge.ocamlcore.org/forum/forum.php?forum_id=899

ocurl 0.7.0 released:
  https://forge.ocamlcore.org/forum/forum.php?forum_id=898

A Component-based GUI with Functional Flavour:
  http://cranialburnout.blogspot.com/2014/03/a-component-based-gui-with-functional.html

OCamlPro Highlights: Feb 2014:
  http://www.ocamlpro.com/blog/2014/03/05/monthly-2014-02.html

Intuitionistic Mathematics and Realizability in the Physical World:
  http://math.andrej.com/2014/03/04/intuitionistic-mathematics-and-realizability-in-the-physical-world/
      

Old cwn

If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a look at the archive or the RSS feed of the archives.

If you also wish to receive it every week by mail, you may subscribe online.


Alan Schmitt