1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset= ISO-8859-1">
<TITLE>
Language extensions
</TITLE>
</HEAD>
<BODY >
<A HREF="manual006.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="manual020.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<HR>
<H1>Chapter 6: Language extensions</H1> <A NAME="c:extensions"></A>
This chapter describes the language features that are implemented in
Objective Caml, but not described in the Objective Caml
reference manual. In contrast with the fairly stable kernel language
that is described in the reference manual, the extensions presented
here are still experimental, and may be removed or changed in the
future.<BR>
<BR>
<H2>6.1 Streams and stream parsers</H2>
<A NAME="s:streams"></A>Objective Caml comprises a library type for <I>streams</I>
(possibly infinite sequences of elements, that are evaluated on
demand), and associated stream expressions, to build streams, and
stream patterns, to destructure streams. Streams and stream patterns
provide a natural approach to the writing of recursive-descent
parsers.<BR>
<BR>
Streams are presented by the following extensions to the syntactic
classes of expressions:<A NAME="@manual.kwd157"></A><BR>
<BR>
<A NAME="@manual.kwd158"></A>
<A NAME="@manual.kwd159"></A><BR>
<BR>
<DIV ALIGN=center>
<TABLE CELLSPACING=2 CELLPADDING=0>
<TR><TD ALIGN=right NOWRAP>
<TT><I><FONT COLOR=maroon>expr</FONT></I></TT></TD>
<TD ALIGN=right NOWRAP>::=</TD>
<TD ALIGN=left NOWRAP>
...</TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><FONT COLOR=blue>[<</FONT></TT> <TT><FONT COLOR=blue>>]</FONT></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><FONT COLOR=blue>[<</FONT></TT> <TT><I><FONT COLOR=maroon>stream-component</FONT></I></TT> { <TT><FONT COLOR=blue>;</FONT></TT> <TT><I><FONT COLOR=maroon>stream-component</FONT></I></TT> } <TT><FONT COLOR=blue>>]</FONT></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><FONT COLOR=blue>parser</FONT></TT> [<TT><I><FONT COLOR=maroon>pattern</FONT></I></TT>] <TT><I><FONT COLOR=maroon>stream-matching</FONT></I></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><FONT COLOR=blue>match</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> <TT><FONT COLOR=blue>with</FONT></TT> <TT><FONT COLOR=blue>parser</FONT></TT> [<TT><I><FONT COLOR=maroon>pattern</FONT></I></TT>] <TT><I><FONT COLOR=maroon>stream-matching</FONT></I></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP>
<TT><I><FONT COLOR=maroon>stream-component</FONT></I></TT></TD>
<TD ALIGN=right NOWRAP>::=</TD>
<TD ALIGN=left NOWRAP>
<TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP>
<TT><I><FONT COLOR=maroon>stream-matching</FONT></I></TT></TD>
<TD ALIGN=right NOWRAP>::=</TD>
<TD ALIGN=left NOWRAP>
<TT><I><FONT COLOR=maroon>stream-pattern</FONT></I></TT> [<TT><I><FONT COLOR=maroon>pattern</FONT></I></TT>] <TT><FONT COLOR=blue>-></FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>
{ <TT><FONT COLOR=blue>|</FONT></TT> <TT><I><FONT COLOR=maroon>stream-pattern</FONT></I></TT> [<TT><I><FONT COLOR=maroon>pattern</FONT></I></TT>] <TT><FONT COLOR=blue>-></FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> }</TD>
</TR>
<TR><TD ALIGN=right NOWRAP>
<TT><I><FONT COLOR=maroon>stream-pattern</FONT></I></TT></TD>
<TD ALIGN=right NOWRAP>::=</TD>
<TD ALIGN=left NOWRAP>
<TT><FONT COLOR=blue>[<</FONT></TT> <TT><FONT COLOR=blue>>]</FONT></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><FONT COLOR=blue>[<</FONT></TT> <TT><I><FONT COLOR=maroon>stream-pat-comp</FONT></I></TT> { <TT><FONT COLOR=blue>;</FONT></TT> <TT><I><FONT COLOR=maroon>stream-pat-comp</FONT></I></TT> [ <TT><FONT COLOR=blue>?</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> ] }<TT><FONT COLOR=blue>>]</FONT></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP>
<TT><I><FONT COLOR=maroon>stream-pat-comp</FONT></I></TT></TD>
<TD ALIGN=right NOWRAP>::=</TD>
<TD ALIGN=left NOWRAP>
<TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>pattern</FONT></I></TT> [ <TT><FONT COLOR=blue>when</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> ]</TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><I><FONT COLOR=maroon>pattern</FONT></I></TT> <TT><FONT COLOR=blue>=</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT></TD>
</TR>
<TR><TD ALIGN=right NOWRAP> </TD>
<TD ALIGN=right NOWRAP>|</TD>
<TD ALIGN=left NOWRAP> <TT><I><FONT COLOR=maroon>ident</FONT></I></TT></TD>
</TR></TABLE></DIV><BR>
Stream expressions are bracketed by <CODE>[<</CODE> and <CODE>>]</CODE>. They
represent the concatenation of their components. The component
<TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> represents the one-element stream whose element is the
value of <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>. The component <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> represents a
sub-stream. For instance, if both <TT>s</TT> and <TT>t</TT> are streams of integers,
then <CODE>[<'1; s; t; '2>]</CODE> is a stream of integers containing the
element <TT>1</TT>, then the elements of <TT>s</TT>, then those of <TT>t</TT>, and finally
<TT>2</TT>. The empty stream is denoted by <CODE>[< >]</CODE>.<BR>
<BR>
Unlike any other kind of expressions in the language, stream
expressions are submitted to lazy evaluation: the components are not
evaluated when the stream is built, but only when they are accessed
during stream matching. The components are evaluated once, the first
time they are accessed; the following accesses reuse the value
computed the first time.<BR>
<BR>
Stream patterns, also bracketed by <CODE>[<</CODE> and <CODE>>]</CODE>, describe
initial segments of streams. In particular, the stream pattern
<CODE>[< >]</CODE> matches all streams. Stream pattern components are
matched against the corresponding elements of a stream. The component
<TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>pattern</FONT></I></TT> matches the corresponding stream element against the
pattern; if followed by <TT><I><FONT COLOR=maroon>when</FONT></I></TT>, the match is accepted only if the
result of the guard expression is <TT>true</TT>. The component <TT><I><FONT COLOR=maroon>pattern</FONT></I></TT> <TT><FONT COLOR=blue>=</FONT></TT>
<TT><I><FONT COLOR=maroon>expr</FONT></I></TT> applies the function denoted by <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> to the current stream,
then matches the result of the function against <TT><I><FONT COLOR=maroon>pattern</FONT></I></TT>. Finally,
the component <TT><I><FONT COLOR=maroon>ident</FONT></I></TT> simply binds the identifier to the stream being
matched.<BR>
<BR>
Stream matching proceeds destructively: once a component has been
matched, it is discarded from the stream (by in-place modification).<BR>
<BR>
Stream matching proceeds in two steps: first, a pattern is selected by
matching the stream against the first components of the stream
patterns; then, the following components of the selected pattern are
checked against the stream. If the following components do not match,
the exception <TT>Stream.Error</TT> is raised. There is no backtracking
here: stream matching commits to the pattern selected according to the
first element. If none of the first components of the stream patterns
match, the exception <TT>Stream.Failure</TT> is raised. The
<TT>Stream.Parse</TT><TT>_</TT><TT>failure</TT> exception causes the next alternative to be
tried, if it occurs during the matching of the first element of a
stream, before matching has committed to one pattern.<BR>
<BR>
The streams hold the count of their elements discarded. The optional
<TT><I><FONT COLOR=maroon>pattern</FONT></I></TT> before the first stream pattern is bound to the stream
count before the matching. The one after each stream pattern
(optional, too) is bound to the stream count after the matching.<BR>
<BR>
The exception <TT>Parse</TT><TT>_</TT><TT>error</TT> has a string parameter coming from the
optional <TT><FONT COLOR=blue>?</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> after the stream pattern components (its default
is the empty string). This expression is evaluated only in case of
error.<BR>
<BR>
See <EM>Functional programming using Caml Light</EM> for a more gentle
introductions to streams, and for some examples of their use in
writing parsers. A more formal presentation of streams, and a
discussion of alternate semantics, can be found in <EM>Parsers in ML</EM>
by Michel Mauny and Daniel de Rauglaudre, in the proceedings of the
1992 ACM conference on Lisp and Functional Programming.<BR>
<BR>
<H2>6.2 Range patterns</H2>In patterns, Objective Caml recognizes the form
<TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>c</FONT></I></TT> <TT><FONT COLOR=blue>'</FONT></TT> <TT><FONT COLOR=blue>..</FONT></TT> <TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>d</FONT></I></TT> <TT><FONT COLOR=blue>'</FONT></TT>
(two character literals separated by <TT>..</TT>) as shorthand for the pattern
<DIV ALIGN=center>
<TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>c</FONT></I></TT> <TT><FONT COLOR=blue>'</FONT></TT> <TT><FONT COLOR=blue>|</FONT></TT> <TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>c</FONT></I></TT><SUB><FONT SIZE=2>1</FONT></SUB> <TT><FONT COLOR=blue>'</FONT></TT> <TT><FONT COLOR=blue>|</FONT></TT> <TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>c</FONT></I></TT><SUB><FONT SIZE=2>2</FONT></SUB> <TT><FONT COLOR=blue>'</FONT></TT> <TT><FONT COLOR=blue>|</FONT></TT> ...
<TT><FONT COLOR=blue>|</FONT></TT> <TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>c</FONT></I></TT><SUB><FONT SIZE=2><I>n</I></FONT></SUB> <TT><FONT COLOR=blue>'</FONT></TT> <TT><FONT COLOR=blue>|</FONT></TT> <TT><FONT COLOR=blue>'</FONT></TT> <TT><I><FONT COLOR=maroon>d</FONT></I></TT> <TT><FONT COLOR=blue>'</FONT></TT>
</DIV>
where <I>c</I><SUB><FONT SIZE=2>1</FONT></SUB>, <I>c</I><SUB><FONT SIZE=2>2</FONT></SUB>, ..., <I>c</I><SUB><FONT SIZE=2><I>n</I></FONT></SUB> are the characters
that occur between <I>c</I> and <I>d</I> in the ASCII character set. For
instance, the pattern <TT>'0'..'9'</TT> matches all characters that are digits.<BR>
<BR>
<H2>6.3 Assertion checking</H2>
<A NAME="@manual.kwd160"></A>Objective Caml supports the <TT>assert</TT> construct to check debugging assertions.
The expression <TT><FONT COLOR=blue>assert</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> evaluates the expression <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> and
returns <TT>()</TT> if <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> evaluates to <TT>true</TT>. Otherwise, the exception
<TT>Assert</TT><TT>_</TT><TT>failure</TT> is raised with the source file name and the
location of <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> as arguments. Assertion
checking can be turned off with the <TT>-noassert</TT> compiler option.<BR>
<BR>
As a special case, <TT>assert false</TT> is reduced to
<TT>raise (Assert</TT><TT>_</TT><TT>failure ...)</TT>, which is polymorphic (and
is not turned off by the <TT>-noassert</TT> option).
<A NAME="@manual3"></A><BR>
<BR>
<H2>6.4 Deferred computations</H2>
<A NAME="@manual.kwd161"></A>The expression <TT><FONT COLOR=blue>lazy</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> returns a value <I>v</I> of type <TT>Lazy.t</TT> that
encapsulates the computation of <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>. The argument <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> is not
evaluated at this point in the program. Instead, its evaluation will
be performed the first time <TT>Lazy.force</TT> is applied to the value
<I>v</I>, returning the actual value of <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>. Subsequent applications
of <TT>Lazy.force</TT> to <I>v</I> do not evaluate <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> again.<BR>
<BR>
The expression <TT><FONT COLOR=blue>lazy</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> is equivalent to
<TT><FONT COLOR=blue>ref</FONT></TT>(<TT><FONT COLOR=blue>Lazy.Delayed</FONT></TT>(<TT><FONT COLOR=blue>fun</FONT></TT> <TT><FONT COLOR=blue>()</FONT></TT> <TT><FONT COLOR=blue>-></FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>)).
For more information, see the description of module <TT>Lazy</TT> in the
standard library (section <A HREF="manual042.html#s:Lazy">17.12</A>).
<A NAME="@manual4"></A><A NAME="@manual5"></A><BR>
<BR>
<H2>6.5 Record copy with update</H2>
<A NAME="@manual.kwd162"></A>The expression
<TT><FONT COLOR=blue>{</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT> <TT><FONT COLOR=blue>with</FONT></TT> <TT><I><FONT COLOR=maroon>lbl</FONT></I></TT><SUB><FONT SIZE=2>1</FONT></SUB> <TT><FONT COLOR=blue>=</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT><SUB><FONT SIZE=2>1</FONT></SUB> <TT><FONT COLOR=blue>;</FONT></TT> ... <TT><FONT COLOR=blue>;</FONT></TT> <TT><I><FONT COLOR=maroon>lbl</FONT></I></TT><SUB><FONT SIZE=2><I>n</I></FONT></SUB> <TT><FONT COLOR=blue>=</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT><SUB><FONT SIZE=2><I>n</I></FONT></SUB> <TT><FONT COLOR=blue>}</FONT></TT>
builds a fresh record with fields <TT><I><FONT COLOR=maroon>lbl</FONT></I></TT><SUB><FONT SIZE=2>1</FONT></SUB> ... <TT><I><FONT COLOR=maroon>lbl</FONT></I></TT><SUB><FONT SIZE=2><I>n</I></FONT></SUB> equal to
<TT><I><FONT COLOR=maroon>expr</FONT></I></TT><SUB><FONT SIZE=2>1</FONT></SUB> ... <TT><I><FONT COLOR=maroon>expr</FONT></I></TT><SUB><FONT SIZE=2><I>n</I></FONT></SUB>, and all other fields having the same value as
in the record <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>. In other terms, it returns a shallow copy of
the record <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>, except for the fields <TT><I><FONT COLOR=maroon>lbl</FONT></I></TT><SUB><FONT SIZE=2>1</FONT></SUB> ... <TT><I><FONT COLOR=maroon>lbl</FONT></I></TT><SUB><FONT SIZE=2><I>n</I></FONT></SUB>,
which are initialized to <TT><I><FONT COLOR=maroon>expr</FONT></I></TT><SUB><FONT SIZE=2>1</FONT></SUB> ... <TT><I><FONT COLOR=maroon>expr</FONT></I></TT><SUB><FONT SIZE=2><I>n</I></FONT></SUB>. For example:
<PRE>
type point = { x : float; y : float; z : float }
let proj p = { p with x = 0.0 }
let proj p = { x = 0.0; y = p.y; z = p.z }
</PRE>
The two definitions of <TT>proj</TT> above are equivalent.<BR>
<BR>
<H2>6.6 Local modules</H2>
<A NAME="@manual.kwd163"></A>
<A NAME="@manual.kwd164"></A>The expression
<TT><FONT COLOR=blue>let</FONT></TT> <TT><FONT COLOR=blue>module</FONT></TT> <TT><I><FONT COLOR=maroon>module-name</FONT></I></TT> <TT><FONT COLOR=blue>=</FONT></TT> <TT><I><FONT COLOR=maroon>module-expr</FONT></I></TT> <TT><FONT COLOR=blue>in</FONT></TT> <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>
locally binds the module expression <TT><I><FONT COLOR=maroon>module-expr</FONT></I></TT> to the identifier
<TT><I><FONT COLOR=maroon>module-name</FONT></I></TT> during the evaluation of the expression <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>.
It then returns the value of <TT><I><FONT COLOR=maroon>expr</FONT></I></TT>. For example:
<PRE>
let remove_duplicates comparison_fun string_list =
let module StringSet =
Set.Make(struct type t = string
let compare = comparison_fun end) in
StringSet.elements
(List.fold_right StringSet.add string_list StringSet.empty)
</PRE><HR>
<A HREF="manual006.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="manual020.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
</BODY>
</HTML>
|