Hello,

Here is the latest Caml Weekly News, for the week of October 23 to 30, 2007.

1) Working on dependent projects with ocamlbuild
2) Preferred use of Invalid_argument and Failure
3) Camlp4 as a universal pre-processor ?
4) Z3 version 1.1
5) Finger trees
6) lazy patterns (patterns v 0.3)
7) Patch to 3.10.0 compiler enabling simple spell-checking

========================================================================
1) Working on dependent projects with ocamlbuild
Archive: <http://groups.google.com/group/fa.caml/browse_frm/thread/ 1e39219f2117bd17/3b6a5ea1f0c70fe0#3b6a5ea1f0c70fe0>
------------------------------------------------------------------------
** Daniel Bünzli explained:

Somewhat related to the discussion we had about the (bad) idea of
embedding dependencies into projects. I'd like to share the following
setup with ocamlbuild that allows me to work simultaneously on a
'base' project and two independent projects 'p1' and 'p2' that use
'base'. Basically my sources are distributed as follows :

base/src
p1/src
p2/src

What I used to do is to build a .cma out of the sources in base/src
and point the others to that .cma. When I did a change in base, I had
to build that .cma again, sometimes forgetting and seeking for bugs
in code while it was just a .cma freshness issue.

What I do now is that I completly forget about .cma's. I just create
the following links in p1 and p2

ln -s ../base/src p1/base
ln -s ../base/src p2/base

And add the following to their _tags file :

echo "<base>: include" >> p1/_tags
echo "<base>: include" >> p2/_tags

The rest is simply sorted out by ocamlbuild. Whenever I do a change
in base/src I don't need to recompile anything there, if I rework in
p1 or p2 things are automatically updated, I always use the latest
version of base's code. Of course this means longer build time when
you ocamlbuild -clean in p1 and p2 since they each build their own
version of base. But on the scale at which I work it is currently not
an issue.

The only caveat (that may disappear in the future) is that base/src
should be able to build without a plugin. Otherwise you will
have to integrate base's myocamlbuild.ml instructions into p1 and
p2's myocamlbuild.ml (btw. couldn't we find a less egoistic name for
that file). But if you are only working with _tagged caml sources it
should works perfectly, put your tags for base in base/src/_tags.
                        
========================================================================
2) Preferred use of Invalid_argument and Failure
Archive: <http://groups.google.com/group/fa.caml/browse_frm/thread/ afe65861a6c384f1/3162e6c9f0aef307#3162e6c9f0aef307>
------------------------------------------------------------------------
** Michaël Le Barbier asked and Xavier Leroy answered:

> Let's quote the manual (release 3.09):
>   exception Invalid_argument of string
>     Exception raised by library functions to signal that the given
>     arguments do not make sense.
>   exception Failure of string
>     Exception raised by library functions to signal that they are
>     undefined on the given arguments.
> It seems to me that Invalid_argument is a sort of specialisation of
> Failure.

The convention that the standard library tries to follow is this.

Invalid_argument is very much like a failed assertion: it indicates
that something is wrong in the program itself, i.e. negative character
positions in string functions.  Most programs will not catch
Invalid_argument, treating as a fatal error.  Others will catch it,
but only to enter a piece of generic "recover from unexpected error"
code.

Failure, on the other hand, signals errors that can happen in normal
runs of the code.  For instance, you're converting a user-provided
string to a number, and the string does not represent a number.  It is
expected that the client code catches Failure and recovers gracefully,
e.g. by asking for the number again, or producing a precise "syntax
error" message.

I recommend the use of Invalid_argument to report "should never
happen" conditions at the boundary between library functions and user
code.  On the other hand, the "Failure" exception is a bit of a legacy
from earlier designs (Caml Light and even the original LeLisp-based
Caml), and often is not the best way to report "normal error"
conditions: instead, you could consider defining your own exceptions
as Alain suggested, or even have your functions return "option" types
instead of raising exceptions.
                        
** Yaron Minsky said, Joel Reymont asked, and Yaron Minsky replied:

> > Where I work, we have come to dearly love the practice of returning
> > polymorphic variants with explicit  variants for various "normal"
> > error cases.
>
> Can you elaborate? Are your explicit variants still polymorphic?

As in:

map_of_alist : ('a * 'b) list -> [ `Repeated_key of 'a | `Succ of ('a,'b)
Map.t ]

The return value is both explicit and a polymorphic variant.
                        
========================================================================
3) Camlp4 as a universal pre-processor ?
Archive: <http://groups.google.com/group/fa.caml/browse_frm/thread/ 522333c5bc79d1a9/400ecef341ba4ab5#400ecef341ba4ab5>
------------------------------------------------------------------------
** David Teller asked and Nicolas Pouillard answered:

>  I'm currently playing with camlp4 3.10. I've succeeded in making a
> syntax extension to help me generate annotated trees, which is a good
> start.
>
>  Now, I understand that, by invoking ocpp, camlp4 may be used as a
> pre-processor for non-OCaml language, which sounds interesting, for I
> have need of pre-processing some parser generator input (at the moment, > menhir, but there are good chances I'll switch to Dypgen to get around > some limitations) to maintain consistency between the implementation and
> the specifications. There are very good chances that I could do that
> with cpp, as it's essentially trivial pre-processing, but I'd rather use
> camlp4, if only to learn more about it.
>
> So, my question is: how do I write a pre-processor that doesn't depend
> on the syntax of OCaml ? I'm hoping I can get away with one or two
> quotations and one anti-quotation, but I have no clue how to register
> these without adding dependencies to either OCaml's Original or Revised
> syntax. Does anyone have any examples handy ?

A way to start this is to just keep the lexer and provide a new grammar including quotations [2] and antiquotations. On the wiki [1] there is also a small but complete example of a grammar for the untyped lambda calculus with antiquotations [3], and also a tutorial of making a full parser with Camlp4 [4].

[1]: <http://brion.inria.fr/gallium/index.php/Camlp4>
[2]: <http://brion.inria.fr/gallium/index.php/Quotation>
[3]: <http://brion.inria.fr/gallium/index.php/ Lambda_calculus_quotations>
[4]: <http://brion.inria.fr/gallium/index.php/Full_parser_tutorial>
                        
** David Teller then asked and Nicolas Pouillard replied:

> I've read the Lambda example, but it looked to me like it was a syntax
> extension for OCaml and no other language, unless I completely
> misunderstand the meaning of, say, <:expr<...>> .

You're  right the lambda example is not adapted.

> Now, do you suggest I should write a full lexer and parser with Camlp4
> just in order to write simple macros ?

Hum, in fact that's because ocpp is no longer supported in Camlp4 3.10
(another (external) tool that can replace it is in preparation).

However writing a small lexer that catch some quotation of yours is quite simple; but since you where talking about menhir and dypgen they certainly have lexing conventions quite close to OCaml, so the default lexer should
suffice.

It's mainly about writing a parser that search for some QUOTATION tokens and expand them, in fact it will be even simpler to directly use a stream parser.

(* pseudo untested code *)
let rec go = parse
  | [< '(QUOTATION q, _loc); strm >] -> expand q; go strm
  | [< '(token, _loc); strm >] -> Token.<some function> tok; go strm
  | [< >] -> ()
                        
========================================================================
4) Z3 version 1.1
Archive: <http://groups.google.com/group/fa.caml/browse_frm/thread/ 940f31dd01d454b2/ea7b2cb91cddcd85#ea7b2cb91cddcd85>
------------------------------------------------------------------------
** Leonardo de Moura and Nikolaj Bjorner announced:

We are pleased to announce of Z3 version 1.1.

Z3 is a new high-performance theorem prover for Satisfiability Modulo
Theories (SMT) problems being developed at Microsoft Research. Z3
supports linear real and integer arithmetic, fixed-size bit-vectors,
extensional arrays, uninterpreted functions, and quantifiers. Z3 has
already been integrated in several projects and products at
Microsoft. It can read problems in SMT-LIB, Simplify and a native
low-level format. Z3 can also be invoked programmatically from either
C/C++, OCaml or from .NET.

More information about Z3, including download links are available from:

<http://research.microsoft.com/projects/z3>
                        
========================================================================
5) Finger trees
Archive: <http://groups.google.com/group/fa.caml/browse_frm/thread/ aeff1d0f48e5b36f/8b64513d1f4830c9#8b64513d1f4830c9>
------------------------------------------------------------------------
** Jon Harrop asked, Arnaud Spiwack said, and Matthieu Sozeau replied:

> > I'm just perusing the multitude of tree data structures out there and was > > wondering if anyone has a finger tree implementation written in OCaml?
>
> There's at least been a Coq implementation (proven correct if I'm not
> mistaken). Thus extractible into OCaml in a probably idiomatic way. I don't > know if the library is self contained or just a small proof-of concept,
> though.
>
> <http://www.lri.fr/~sozeau/research/russell/fingertrees.fr.html>

Indeed, this is a certified implementation of Finger Trees, it's just not ready for release yet. I'm actually working on a version using modules which extracts to efficient OCaml code (e.g. ropes built on top of them permit to run the ICFP simulator in reasonnable time). So, the basic extracted code works well but I haven't finished building a certified implementation of the
ropes which I want to release with it. In the meantime you can try this
extracted version:

<http://www.lri.fr/~sozeau/res/fingertrees-0.1.tgz>

Some random notes:
- No documentation / beautifying of the ocaml sources, look at the Coq
  literate code for that, available from the webpage:
  <http://www.lri.fr/~sozeau/research/russell/fingertrees.en.html>
- Uses a bit of Obj.magic for polymorphic recursion
- Some artifacts of extraction make it a bit slower than it could be (useless
  beta-redexes)
- Should still be bug free even at 0.1 !
- Uses ocamlfind for installation
- Released under the LGPL
- It will get polished soon...
                        
========================================================================
6) lazy patterns (patterns v 0.3)
Archive: <http://groups.google.com/group/fa.caml/browse_frm/thread/ acfcb60f77824d38/f02a4ba3b0b9e80c#f02a4ba3b0b9e80c>
------------------------------------------------------------------------
** Jeremy Yallop announced:

I'm pleased to announce a new release of `patterns', an OCaml
extension providing general-purposes additions to pattern matching.
This release includes a new feature, "lazy patterns".

You can download patterns from

    <http://code.google.com/p/ocaml-patterns/>

Lazy patterns extend OCaml pattern syntax with the keyword "lazy",
mirroring the use of lazy in expressions.  With this extension
patterns can be used to deconstruct lazy values; for example, you can
define a function that behaves like Lazy.force as follows

    let force (lazy x) = x

or, given a type of lazy lists in the "odd style":

    type 'a llist = Nil | Cons of 'a * lazy llist

you can write a lazy map function:

    let rec map f = function
     | Nil -> Nil
     | Cons (h, lazy t) -> Cons (f h, lazy (map f t))

You can use "lazy" anywhere you can use a constructor: in nested
patterns, or-patterns, patterns for "let", "function", "match",
"try/with", etc.  Lazy patterns can also be used with the other
extension provided in the current release, pattern guards: you can
write, for example,

    match v with
     | A (x, y) with lazy (z,w) = f x -> e

Paradoxically, lazy patterns make pattern-matching more eager, since
they force evaluation of delayed values.  However, no more forcing
than necessary (for some suitable definition thereof) will occur: the
following will return "true", for example.

    match lazy 3, lazy (assert false) with
     | lazy 2, lazy x -> false
     | lazy 3, _ -> true

Documentation for lazy patterns will be available soon.  Comments are
welcome, bug reports especially so.

A caveat: due to the translation used, lazy patterns can sometimes
give rise to spurious warnings.  For example, for the following
function

    function
       lazy (Some _) -> 1
     | lazy None     -> 0

OCaml gives the warning

    "Warning X: bad style, all clauses in this pattern-matching are
guarded."

It is of course possible to avoid these warnings by using "-w x" or by
adding redundant match cases.

For information on pattern guards see the previous announcements

    v0.1: <http://groups.google.com/group/fa.caml/msg/b0ec5324180bfeba>
    v0.2: <http://groups.google.com/group/fa.caml/msg/016e76d7a51559c8>

and the documentation on the website

    <http://code.google.com/p/ocaml-patterns/wiki/PatternGuards>
                        
========================================================================
7) Patch to 3.10.0 compiler enabling simple spell-checking
Archive: <http://groups.google.com/group/fa.caml/browse_frm/thread/ 97d67528b2c832fa/9d528ae994d45191#9d528ae994d45191>
------------------------------------------------------------------------
** Edgar Friendly announced:

Editor note: the patches are available at the archive link above.

One random little feature of GNAT that comes in handy for me is its
habit of, when I misspell an identifier, giving me a possible correction
in its compile error message.  Spending some time with the 3.10.0
sources, I have created a "second draft" patch creating this
functionality in my favored language.

Example:
========

# /home/thelema/Projects/ocaml-custom/bin/ocamlc -o coml -I +lablgtk2
lablgtk.cma gtkInit.cmo coml.ml
File "coml.ml", line 61, characters 16-25:
Unbound value is_arcive, possible misspelling of is_archive

Impacts:
========

Efficiency in the case of finding a mistake should be quite good,
although this shouldn't matter too much since the compiler quits pretty
early in compilation when it finds an unbound identifier.

In the case of no unbound identifiers, the cost is an extra try/with
block around the standard lookup. I haven't made any benchmarks, though.

I expect this code to have little long term maintenance issues - the
major source of code changes was adding a "* string list" to a number of
exceptions to carry the list of possible correct spellings to the point
they get output by the compiler.  These exceptions are still usable as
before with an empty list in this spot.

It's possible the code has created opportunities for uncaught exceptions
in the compiler as I only checked for instances of "Not_found" in a few
files -- those which dealt with the Unbound_* exceptions.  Someone who
knows the internals better might find places the "Found_nearly"
exception that carries possible corrections might escape into.

Dedicated to:
Yaron Minsky and the team at Jane Street
                        
** Julien Moutinho asked and Edgar Friendly answered:

> I'm sorry but could it be that you have posted an incomplete patch?

I did.  Here's a "third draft" which should include all the necessary
bits to patch off 3.10.0.  There's still plenty of rough edges to smooth
out in the patch, but it should suffice for people to have something
working.
                        
========================================================================
Using folding to read the cwn in vim 6+
------------------------------------------------------------------------
Here is a quick trick to help you read this CWN if you are viewing it using
vim (version 6 or greater).

:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'<1':1
zM
If you know of a better way, please let me know.

========================================================================
Old cwn
------------------------------------------------------------------------

If you happen to miss a CWN, you can send me a message
([EMAIL PROTECTED]) and I'll mail it to you, or go take a look at
the archive (<http://alan.petitepomme.net/cwn/>) or the RSS feed of the
archives (<http://alan.petitepomme.net/cwn/cwn.rss>). If you also wish
to receive it every week by mail, you may subscribe online at
<http://lists.idyll.org/listinfo/caml-news-weekly/> .

========================================================================


--
Alan Schmitt <http://alan.petitepomme.net/>

The hacker: someone who figured things out and made something cool happen.
 .O.
 ..O
 OOO


Attachment: PGP.sig
Description: This is a digitally signed message part

_______________________________________________
caml-news-weekly mailing list
caml-news-weekly@lists.idyll.org
http://lists.idyll.org/listinfo/caml-news-weekly

Reply via email to