Commit a5cf614d authored by Pietro Abate's avatar Pietro Abate
Browse files

[r2003-07-05 10:28:28 by cvscast] Beppe : added overloading in the tutorial

Original author: cvscast
Date: 2003-07-05 10:28:28+00:00
parent 93019664
......@@ -74,14 +74,23 @@ code.
<section title="Complex overloading">
<section title="Complex example">
Let us examine a more complex example.
We want to transform the representation of persons introduced
in Section <local href="tutorial_first_functions"/>, using different tags
Let us examine a more complex example. Recall the types used to represent persons
that we defined in Section "<a href="tutorial_getting_started#type_decl">Getting started</a>" that for the purpose of the example we can simplify as follows:
type Person = FPerson | MPerson
type FPerson = <person gender = "{{F}}">[ Name Children ]
type MPerson = <person gender = "{{M}}">[ Name Children ]
type Children = <children>[ Person* ]
type Name = <name>[ PCDATA ]
We want to transform this representation of persons into a different representation that uses different tags
<code>&lt;man></code> and <code>&lt;woman></code>
instead of the gender attribute and, conversely, using an attribute
instead of the gender attribute and, conversely, that uses an attribute
instead of an element for the name.
We also want to distinguish the children of a person into two different
sequences, one of sons, composed of men (i.e. elements tagged by <code>&lt;man></code>), and the other of daughters, composed of
......@@ -95,14 +104,76 @@ type Woman = <woman name=String>[ Sons Daughters ]
type Sons = <sons>[ Man* ]
type Daughters = <daughters>[ Woman* ]
Here is a possible way to implement such a transformation:
<include-verbatim file=""/>
let fun split ({{MPerson -> Man ; FPerson -> Woman}})
<person gender=g>[ <name>n <children>[(mc::MPerson | fc::FPerson)*] ] ->
(* the above pattern collects all the MPerson in mc, and all the FPerson in fc *)
let tag = match g with "F" -> `woman | "M" -> `man in
let s = map mc with x -> split x in
let d = map fc with x -> split x in
<(tag) name=n>[ <sons>s <daughters>d ] ;;
The function <code>split</code> is declared to be an overloaded function that, when
applied to a <code>MPerson</code>, returns an element of type <code>Man</code> and
that, when applied
to a <code>FPerson</code>, returns an element of type <code>Woman</code>. The body
is composed of a single pattern matching
<person gender={{g}}>[ <name>{{n}} <children>[({{mc}}::MPerson | {{fc}}::FPerson)*] ] ->
whose pattern binds four variables: <code>g</code> is
bound to the gender of the argument of the function, <code>n</code> is bound to
its name, <code>mc</code> is bound to the sequence of all children that are of
type <code>MPerson</code>, and <code>fc</code> is bound to the sequence of all children
that are of type <code>FPerson</code>.
On the next line we define <code>tag</code> to be
<code>`man</code> or <code>`woman</code> according to the value of <code>g</code>. Then we
apply <code>split</code> recursively to the elements of <code>mc</code> and <code>fc</code>.
let {{s}} = map {{mc}} with x -> {{split}} x in
let d = map fc with x -> split x in
<(tag) name=n>[ <sons>{{s}} <daughters>d ] ;;
Here is
the use of overloading: since <code>mc</code> is of type <code>[MPerson*]</code>}, then
by the overloaded type of <code>split</code> we can deduce that <code>s</code> is of type
<code>[Man*]</code>}; similarly we deduce for <code>d</code> the type <code>[Woman*]</code>. From this
the type checker deduces that the expressions <code>&lt;sons>s</code> and
<code>&lt;daughters></code> are of type <code>Sons</code> and <code>Daughters</code>, and therefore it
returns for the <code>split</code> function the type <code>(MPerson -> Man) &amp; (FPerson
-> Woman)</code>. Note that the use of overloading here is critical: although
<code>split</code> has <i>also</i> type <code>Person ->(Man | Woman)</code> (since <code>split</code> is of type
<code>MPerson->Man &amp; FPerson->Woman</code>, which is a subtype), had we
declared <code>split</code> of that type, the function would not have type-checked: in
the recursive calls we would have been able to deduce for <code>s</code> and for
<code>d</code> the type <code>[ (Man | Woman)* ]</code>, which is not enough to type-check the
If, for example, we wanted to define the same transformation in XDuce we would
need first to apply a filter (that is our transform) to the children so as to
separate male from females (while in CDuce we obtain it simply by a pattern) and then
resort to two auxiliary functions that have nearly the same definition and
differ only on their type, one being of type <code>MPerson -> Man</code>, the other of
type <code>FPerson -> Woman</code>. The same transformation can be elegantly defined
in XSLT with a moderate nloc increase, but only at the
expense of loosing static type safety and type based optimization:
see the page <local href="bench"/> for preliminary benchmarks.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment