<?xml version="1.0"?>
<rdf:RDF
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns="http://purl.org/rss/1.0/"
>
<channel rdf:about="http://planet.ocamlcore.org">
	<title>OCaml Planet</title>
	<link>http://planet.ocamlcore.org</link>
	<description>OCaml Planet - http://planet.ocamlcore.org</description>

	<items>
		<rdf:Seq>
			<rdf:li rdf:resource="https://forge.ocamlcore.org/forum/forum.php?forum_id=822" />
			<rdf:li rdf:resource="http://blog.camlcity.org/blog/plasma6.html" />
			<rdf:li rdf:resource="http://alan.petitepomme.net/cwn/2012.01.31.html" />
			<rdf:li rdf:resource="tag:ocsigen.org,2012-01-26:1520" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-2073503406800427577.post-1975673674199781114" />
			<rdf:li rdf:resource="https://forge.ocamlcore.org/forum/forum.php?forum_id=821" />
			<rdf:li rdf:resource="http://caml.inria.fr/cgi-bin/hump.cgi?contrib=796" />
			<rdf:li rdf:resource="https://forge.ocamlcore.org/projects/libsndfile/" />
			<rdf:li rdf:resource="http://alan.petitepomme.net/cwn/2012.01.24.html" />
			<rdf:li rdf:resource="http://www.nicollet.net/?p=2660" />
		</rdf:Seq>
	</items>
</channel>

<item rdf:about="https://forge.ocamlcore.org/forum/forum.php?forum_id=822">
	<title>OCamlCore Forge News: Lacaml v6.0.0 released</title>
	<link>https://forge.ocamlcore.org/forum/forum.php?forum_id=822</link>
	<content:encoded>Lacaml is a binding to the celebrated linear algebra routines BLAS and LAPACK.  This version builds with OASIS.  Moreover the precision dependent code is available with Lacaml.D,... instead of the former Lacaml.Impl.D,...  Enjoy.</content:encoded>
	<dc:date>2012-02-01T22:23:41+00:00</dc:date>
	<dc:creator>Christophe Troestler</dc:creator>
</item>
<item rdf:about="http://blog.camlcity.org/blog/plasma6.html">
	<title>Gerd Stolpmann: Plasma Map/Reduce Slightly Faster Than Hadoop</title>
	<link>http://blog.camlcity.org/blog/plasma6.html</link>
	<content:encoded>&lt;div&gt;
  &lt;b&gt;A performance test&lt;/b&gt;&lt;br /&gt; 
&lt;/div&gt;

&lt;div&gt;
  
Last week I spent some time running map/reduce jobs on Amazon EC2.
In particular, I compared the performance of Plasma, my own map/reduce
implementation, with Hadoop. I just wanted to know how much my implementation
was behind the most popular map/reduce framework. However, the suprise was
that Plasma turned out as slightly faster in this setup.

&lt;/div&gt;

&lt;div&gt;
  
&lt;p&gt;
I would not call this test a &quot;benchmark&quot;. Amazon EC2 is not a
controlled environment, as you always only get partial machines, and
you don't know how much resources are consumed by other users on the
same machines.  Also, you cannot be sure how far the nodes are off
from each other in the network. Finally, there are some special
effects coming from the virtualization technology, especially the
first write of a disk block is slower (roughly half the normal speed)
than following writes.  However, EC2 is good enough to get an
impression of the speed, and one can hope that all the test runs
get the same handicap on average.

&lt;/p&gt;&lt;p&gt;
The task was to sort 100G of data, given in 10 files. Each line has
100 bytes, divided into a key of 8 bytes, a TAB character, 90 random
bytes as value, and an LF character. The key was randomly chosen from
65536 possible values. This means that there were lots of lines with
the same key - a scenario where I think it is more typical of map/reduce
than having unique keys. The output is partitioned into 80 sets.

&lt;/p&gt;&lt;p&gt;
I allocated 1 larger node (m1-xlarge) with 4 virtual cores and 15G of
RAM acting as combined name- and datanode, and 9 smaller nodes
(m1-large) with 2 virtual cores and 7.5G of RAM for the other
datanodes. Each node had access to two virtual disks that were
configured as RAID-0 array. The speed for sequential reading or
writing was around 160 MB/s for the array (but only 80 MB/s for the
first time blocks were written). Apparently, the nodes had Gigabit
network cards (the maximum transfer speed was around 119MB/s).

&lt;/p&gt;&lt;p&gt;
During the tests, I monitored the system activity with the sar utility.
I observed significant cycle stealing (meaning that a virtual core is
blocked because there is no free real core), often reaching values of
25%. This could be interpreted as overdriving the available resources,
but another explanation is that the hypervisor needed this time for
itself. Anyway, this effect also questions the reliability of this
test.

&lt;/p&gt;&lt;h2&gt;The contrahents&lt;/h2&gt;

&lt;p&gt;
Hadoop is the top dog in the map/reduce scene. In this test, the
version from Cloudera 0.20.2-cdh3u2 was used, which contains more than
1000 patches against the vanilla 0.20.2 version. Written in Java, it
needs a JVM at runtime, which was here IcedTea 1.9.10 distributing
OpenJDK 1.6.0_20. I did not do any tuning, hoping that the configuration
would be ok for a small job. The HDFS block size was 64M, without
replication.

&lt;/p&gt;&lt;p&gt;
The contender is Plasma Map/Reduce. I started this project two years
ago in my spare time. It is not a clone of the Hadoop architecture,
but includes many new ideas. In particular, a lot of work went into
the distributed filesystem PlasmaFS which features an almost complete
set of file operations, and controls the disk layout directly. The
map/reduce algorithm uses a slightly different scheme which tries
to delay the partitioning of the data to get larger intermediate files.
Plasma is implemented in OCaml, which isn't VM-based but compiles
the code directly to assembly language. In this test, the blocksize
was 1M (Plasma is designed for smaller-sized blocks). The software
version of Plasma is roughly 0.6 (a few svn revisions before the release
of 0.6).

&lt;/p&gt;&lt;h2&gt;Results&lt;/h2&gt;

&lt;p&gt;The runtimes:

&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;&lt;b&gt;Hadoop:&lt;/b&gt;&lt;/td&gt;     &lt;td&gt;&lt;b&gt;2265 seconds&lt;/b&gt; (37 min, 45 s)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;b&gt;Plasma:&lt;/b&gt;&lt;/td&gt;     &lt;td&gt;&lt;b&gt;1975 seconds&lt;/b&gt; (32 min. 55 s)&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
Given the uncertainty of the environment, this is no big difference.
But let's have a closer look at the system activity to get an idea
why Plasma is a bit faster.

&lt;/p&gt;&lt;h2&gt;CPU&lt;/h2&gt;

In the following I took simply one of the datanodes, and created
diagrams (with kSar):

&lt;p&gt;
&lt;img src=&quot;http://blog.camlcity.org/files/img/blog/edited_hadoop_cpu_all.png&quot; height=&quot;472&quot; width=&quot;799&quot; /&gt;

&lt;/p&gt;&lt;p&gt;
&lt;img src=&quot;http://blog.camlcity.org/files/img/blog/edited_plasma_cpu_all.png&quot; height=&quot;471&quot; width=&quot;800&quot; /&gt;

&lt;/p&gt;&lt;p&gt;
Note that kSar does not draw graphs for %iowait and %steal, although 
these data are recorded by sar. This is the explanation why the sum of
user, system and idle is not 100%. 

&lt;/p&gt;&lt;p&gt;
What we see here is that Hadoop consumes all CPU cycles, whereas
Plasma leaves around 1/3 of the CPU capacity unused. Given the fact
that this kind of job is normally I/O-bound, it just means that Hadoop
is more CPU-hungry, and would have benefit from getting more cores
in this test.

&lt;/p&gt;&lt;h2&gt;Network&lt;/h2&gt;

In this diagram, reads are blue and red, whereas writes are green and
black. The first curve shows packets per second, and the second bytes
per second:

&lt;p&gt;
&lt;img src=&quot;http://blog.camlcity.org/files/img/blog/edited_hadoop_eth0.png&quot; height=&quot;333&quot; width=&quot;800&quot; /&gt;

&lt;/p&gt;&lt;p&gt;
&lt;img src=&quot;http://blog.camlcity.org/files/img/blog/edited_plasma_eth0.png&quot; height=&quot;319&quot; width=&quot;800&quot; /&gt;

Summing reads and writes up, Hadoop uses only around 7MB/s on average
whereas Plasma transmits around 25MB/s, more than three times as
much. There could be two explanations:

&lt;/p&gt;&lt;ul&gt;
  &lt;li&gt;Because Hadoop is CPU-underpowered, it remains below its
      possibilities
  &lt;/li&gt;&lt;li&gt;The Hadoop scheme is more optimized for keeping the network
      bandwidth as low as possible
&lt;/li&gt;&lt;/ul&gt;

The background for the second point is the following: Because Hadoop
partitions the data immediately after mapping and sorting, the data
has (ideally) only to cross the network once.  This is different in
Plasma - which generally partitions the data iteratively. In this
setup, after mapping and sorting only 4 partitions are created, which
are further refined in the following split-and-merge rounds.  As we
have here 80 partitions in total, there is at least one further step
in which data partitioning is refined, meaning that the data has to
cross the network roughly twice. This already explains 2/3 of the
observed difference.  (As a side note, one can configure how many
partitions are initially created after mapping and sorting, and it
would have been possible to mimick Hadoop's scheme by setting this
value to 80.)

&lt;h2&gt;Disks&lt;/h2&gt;

These diagrams depict the disk reads and writes in KB/second:

&lt;p&gt;
&lt;img src=&quot;http://blog.camlcity.org/files/img/blog/edited_hadoop_md0.png&quot; height=&quot;332&quot; width=&quot;800&quot; /&gt;

&lt;/p&gt;&lt;p&gt;
&lt;img src=&quot;http://blog.camlcity.org/files/img/blog/edited_plasma_md0.png&quot; height=&quot;332&quot; width=&quot;800&quot; /&gt;

The average numbers are (directly taken from sar):

&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt; &lt;/td&gt;
    &lt;th&gt;Hadoop&lt;/th&gt;
    &lt;th&gt;Plasma&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Read/s:&lt;/td&gt;
    &lt;td&gt;17.6 MB/s&lt;/td&gt;
    &lt;td&gt;31.2 MB/s&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Write/s:&lt;/td&gt;
    &lt;td&gt;30.8 MB/s&lt;/td&gt;
    &lt;td&gt;33.9 MB/s&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
Obviously, Plasma reads data around twice as often from disk than
Hadoop, whereas the write speed is about the same. Apart from this, it
is interesting that the shape of the curves are quite different:
Hadoop has a period of high disk activity at the end of the job (when
it is busy merging data), whereas Plasma utilizes the disks better
during the first third of the job.

&lt;/p&gt;&lt;h2&gt;Plausibility&lt;/h2&gt;

&lt;p&gt;
Neither of the contenders utilized the I/O resources at all times
best. Part of the difficulty of developing a map/reduce scheme is to
achieve that the load put onto the disks and onto the network is
balanced. It is not good when e,g, the disks are used to 100% at a
certain point and the network is underutilized, but during the next
period the network is at 100% and the disk not fully used. A balanced
distribution of the load reaches higher throughput in total.

&lt;/p&gt;&lt;p&gt;
Let's analyze the Plasma scheme a bit more in detail. The data set of
100G (which does not change in volume during the processing) is copied
four times in total: once in the map-and-sort phase, and three times
in the reduce phase (for this volume Plasma needs three merging
rounds). This means we have to transfer 4 * 100G of data in total, or
40G of data per node (remember we have 10 nodes). We ran 22 cores for
1975 seconds, which gives a capacity of 43450 CPU seconds. Plasma
tells us in its reports that it used 3822 CPU seconds for in-RAM
sorting, which we should subtract for analyzing the I/O
throughput. Per core these are 173 seconds. This means each node had
1975-173 = 1802 seconds for handling the 40G of data. This makes
around 22 MB per second on each node.

&lt;/p&gt;&lt;p&gt;
The Hadoop scheme differs mostly in that the data is only copied twice
in the merge phase (because Hadoop by default merges more files in
one round than Plasma). However, because of its design there is an
extra copy at the end of the reduce phase (from disk to HDFS).  This
means Hadoop also solves the same job by transferring 4 * 100G of data.
There is no counter for measuring the time spent for in-RAM sorting.
Let's assume this time is also around 3800 seconds. This means each
node had 2265 - 175 = 2090 seconds for handling 40G of data, or
19 MB per second on each node.

&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;
It looks very much as if both implementations are slowed down by
specifics of the EC2 environment. Especially the disk I/O, probably
the essential bottleneck here, is far below what one can expect.
Plasma probably won because it uses the CPU more efficiently, whereas
other aspects like network utilization are better handled by Hadoop.

&lt;/p&gt;&lt;p&gt;
For my project this result just means that it is on the right track.
Especially, this small setup (only 10 nodes) is easily handled, giving
prospect that Plasma is scalable at least to a small multitude of
this. The bottleneck would be here the namenode, but there is still a
lot of headroom.

&lt;/p&gt;&lt;h2&gt;Where to get Plasma&lt;/h2&gt;

&lt;p&gt;Plasma Map/Reduce and PlasmaFS are bundled together in one download. Here is the
&lt;a href=&quot;http://projects.camlcity.org/projects/plasma.html&quot;&gt;project page&lt;/a&gt;.

&lt;/p&gt;&lt;p&gt;

&lt;img src=&quot;http://blog.camlcity.org/files/img/blog/plasma6_bug.gif&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;

&lt;/p&gt;
&lt;/div&gt;

&lt;div&gt;
  Gerd Stolpmann works as O'Caml consultant

&lt;/div&gt;

&lt;div&gt;
  
&lt;/div&gt;</content:encoded>
	<dc:date>2012-02-01T22:00:28+00:00</dc:date>
</item>
<item rdf:about="http://alan.petitepomme.net/cwn/2012.01.31.html">
	<title>Caml Weekly News: Caml Weekly News, 31 Jan 2012</title>
	<link>http://alan.petitepomme.net/cwn/2012.01.31.html</link>
	<content:encoded>SQL engine in OCaml with client side cache / Vim plugin / Other Caml News</content:encoded>
	<dc:date>2012-01-31T12:00:00+00:00</dc:date>
</item>
<item rdf:about="tag:ocsigen.org,2012-01-26:1520">
	<title>Ocsigen project: New js_of_ocaml example: Hyperbolic tree viewer</title>
	<link>http://ocsigen.org/</link>
	<content:encoded>&lt;p&gt;New js_of_ocaml example available: &lt;a href=&quot;http://ocsigen.org/js_of_ocaml/files/hyperbolic/index.html&quot;&gt;Hyperbolic tree viewer&lt;/a&gt;. Game: find human beings!
        &lt;/p&gt;
        &lt;p&gt;This program has been fully written in OCaml and compiled to JS using the js_of_ocaml compiler.
          You can find the source code in &lt;a href=&quot;http://ocsigen.org/darcsweb/?r=js_of_ocaml;a=headblob;f=/examples/hyperbolic/hypertree.ml&quot;&gt;js_of_ocaml repository&lt;/a&gt;.
        &lt;/p&gt;</content:encoded>
	<dc:date>2012-01-27T17:20:00+00:00</dc:date>
	<dc:creator>Ocsigen team</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-2073503406800427577.post-1975673674199781114">
	<title>Opa: Sessions: handling state, communication &amp; concurrency in Opa.</title>
	<link>http://blog.opalang.org/2011/09/sessions-handling-state-communication.html</link>
	<content:encoded>&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;As François-Régis mentioned in the previous post (hey, thanks for taking over and making the show go on :) I'm on holidays now. I rarely have access to the internet so this is the main reason why I don't answer comments and won't post much. Please bare with me; I'll be back on 13th of September and then it will again be business as usual. But since I got a chance I decided to make this one sun-charged post while still on holidays :). Ok, let's get started.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://doc.opalang.org/#!/module/stdlib.core.rpc.core/Session&quot;&gt;Sessions&lt;/a&gt; are a very central concept in Opa. And as things stand I don't think enough attention is devoted to them in the manual (we received a lot of compliments about the state of the docs and we're happy to hear you like them, but I think there are still things that can be improved). I've been meaning to write about sessions for a longer while and I think it's high time to do that.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;admonitionblock&quot;&gt;
&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Summary&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;You will learn:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;
About state encapsulation using sessions.
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
About event-driven style of programming with sessions.
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
How communication is accomplished in Opa (yes, you guessed it, with sessions).
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_sessions&quot;&gt;Sessions&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;In case you haven't realized yet, Opa is a functional language (although not pure, as the database manipulations and many client-side operations are impure). That means that there are no variables. This can come as a shocker to some of you not used to this style of programming and the words: &lt;em&gt;`‘How the heck can I program anything without variables??’'&lt;/em&gt; seem to be coming to one's lips. Well, it turns out you can. In fact: it turns out such a programming style has huge benefits; listing them is beyond the scope of this article, I'll only hint: think about debugging and testing (another hint: a pure function will give the same result for the same arguments. Always. Yes, that's a good thing).&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Still, there are times when you simply need to have a state. And to modify it. Not to worry, sessions can do that for you in a safe and elegant manner. So what are they exactly? The description from the standard library is a good start:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;&lt;em&gt;`‘A session is a unit of state and concurrency. A session can be created on a server or on a client, and can be shared between several servers.’'&lt;/em&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;A session is just some value (session's state) and a message handler. Messages can be send to the sessions and upon receipt are handled by the handler, which in turn can change the session's state (or terminate it). Big part of the magic is that it doesn't matter where is the session and where are you sending the message from — client and server or two different servers; whatever the scenario things will just work (of course the location of the session relative to the location of the message sender can have a huge impact on performance, so making sure the session is where it should be is often a good place to start when tweaking your app's performance).&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Let's see how can we create a session:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&lt;tt&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;type&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Session.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;instruction&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'state&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
        &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;set&lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'state&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;font-style: italic;&quot;&gt;&lt;span style=&quot;color: #9A1900;&quot;&gt;/** Carry on with a new value of the state value.*/&lt;/span&gt;&lt;/span&gt;
      &lt;span style=&quot;color: #990000;&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;unchanged&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;   &lt;span style=&quot;font-style: italic;&quot;&gt;&lt;span style=&quot;color: #9A1900;&quot;&gt;/** Carry on with the same state.*/&lt;/span&gt;&lt;/span&gt;
      &lt;span style=&quot;color: #990000;&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;stop&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;        &lt;span style=&quot;font-style: italic;&quot;&gt;&lt;span style=&quot;color: #9A1900;&quot;&gt;/** Stop this session. Any further message will be ignored */&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color: #990000;&quot;&gt;Session.&lt;/span&gt;make &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; 'message &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Session.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;instruction&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'state&lt;span style=&quot;color: #990000;&quot;&gt;))&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;channel&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'message&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;A &lt;tt&gt;Session.instruction&lt;/tt&gt; can either change the state of the session (&lt;tt&gt;set&lt;/tt&gt;), leave it unchanged (&lt;tt&gt;unchanged&lt;/tt&gt;) or terminate the session (&lt;tt&gt;stop&lt;/tt&gt;). We can create a new session with &lt;tt&gt;Session.make&lt;/tt&gt; that takes two arguments: initial state of the session and a message handler, i.e., a function that given the state and a message can do some work and then respond with &lt;tt&gt;Session.instruction&lt;/tt&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;&lt;tt&gt;Session.make&lt;/tt&gt; after creating the session gives us a &lt;tt&gt;channel&lt;/tt&gt;. We can then send messages to this channel with:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&lt;tt&gt;send &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;channel&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'message&lt;span style=&quot;color: #990000;&quot;&gt;),&lt;/span&gt; 'message &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;void&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;…and that's mostly it. There are more things that sessions can do and I encourage you to browse the &lt;a href=&quot;http://doc.opalang.org/#!/module/stdlib.core.rpc.core/Session&quot;&gt;Session API&lt;/a&gt; but those two functions are the backbone of Opa sessions.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Simple? Quite so, yes. But don't be fooled by the simplicity (actually something being simple is often an indication of a good design, not of lack of versatility) — sessions are mighty animals. They're powerful. They're very important. You better learn them if you want to become an Opa-ninja.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_example&quot;&gt;Example&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Remember the simple watch example we developer &lt;a href=&quot;http://blog.opalang.org/2011/07/interactivity-even-handling.html&quot;&gt;a while back&lt;/a&gt;? For convenience let me put the source code here.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&lt;tt&gt;&lt;span style=&quot;color: #008080;&quot;&gt;Id&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{{&lt;/span&gt; &lt;span style=&quot;color: #008080;&quot;&gt;time&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;&quot;time&quot;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;}}&lt;/span&gt;

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;show_time&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
  &lt;span style=&quot;color: #008080;&quot;&gt;time&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Date.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;to_string&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(Date.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;now&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;())&lt;/span&gt;
  &lt;span style=&quot;color: #990000;&quot;&gt;Dom.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;transform&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;([&lt;/span&gt;#&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;Id.&lt;/span&gt;time&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;time&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;/&amp;gt;])&lt;/span&gt;

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;page&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
  &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;&lt;/span&gt;span &lt;span style=&quot;color: #008080;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;#&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;Id.&lt;/span&gt;time&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #008080;&quot;&gt;onready&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;_ &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Scheduler.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;timer&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #993399;&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; show_time&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;one_page_server&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&quot;What's the time?&quot;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; page&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;span class=&quot;run&quot;&gt;&lt;a href=&quot;http://watch.tutorials.opalang.org&quot; target=&quot;_blank&quot;&gt;Run&lt;/a&gt;&lt;/span&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;It's a very simple code but it has one annoying feature: we need to repeat the id of the &lt;tt&gt;&amp;lt;span&amp;gt;&lt;/tt&gt; element; first we mention it when we create the element in the &lt;tt&gt;page()&lt;/tt&gt; function and then when we modify the time in &lt;tt&gt;show_time()&lt;/tt&gt;. In order to avoid easy mistakes that id was factored out as a constant. That's a good practice but let's see a different approach with sessions.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Let's try to implement a small abstraction for an interactive HTML fragment — we will call it just that, a &lt;em&gt;fragment&lt;/em&gt;. According to Opa's taxonomy it is a component, so following our naming practice it will be put in a module &lt;tt&gt;CFragment&lt;/tt&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Such a fragment should be able to render itself and then to possibly re-render itself upon a &lt;em&gt;notification&lt;/em&gt;. To make it more interesting we will also equip it with some state, so that it will be able to render its new version based both on the incoming notification and its previous state and it will be able to subsequently modify this state.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Let's start defining a type for an answer to a notification send to a fragment.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&lt;tt&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;package&lt;/span&gt;&lt;/span&gt; hands&lt;span style=&quot;color: #990000;&quot;&gt;-&lt;/span&gt;on&lt;span style=&quot;color: #990000;&quot;&gt;-&lt;/span&gt;opa&lt;span style=&quot;color: #990000;&quot;&gt;.&lt;/span&gt;fragment

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;type&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;action&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'state&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
  &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt; re_render &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;option&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;color: #990000;&quot;&gt;;&lt;/span&gt; change_state &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;option&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'state&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;such an answer can (optionally) request re-rendering of the HTML and (optionally) change fragment's state. Let me present the rest of the code of this fragment abstraction and then I'll try to explain what's happening.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&lt;tt&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;@abstract&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;type&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fragment&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;channel&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color: #008080;&quot;&gt;CFragment&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
&lt;span style=&quot;color: #FF0000;&quot;&gt;{{&lt;/span&gt;

  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;@private&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;on_notification&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;id&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; handler&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;res&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;handler&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;re_render&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Dom.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;transform&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;([&lt;/span&gt;#&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;id&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;])&lt;/span&gt;
    &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;do&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Option.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iter&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;re_render&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; res&lt;span style=&quot;color: #990000;&quot;&gt;.&lt;/span&gt;re_render&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;match&lt;/span&gt;&lt;/span&gt; res&lt;span style=&quot;color: #990000;&quot;&gt;.&lt;/span&gt;change_state &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;with&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;none&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;unchanged&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;some&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;new_state&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;new_state&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;

  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;create&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;init_state &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; init_xhtml &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt;
         handler &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; 'msg &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;action
        &lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fragment&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'t&lt;span style=&quot;color: #990000;&quot;&gt;))&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;id&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Dom.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fresh_id&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;xhtml&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;&lt;/span&gt;span &lt;span style=&quot;color: #008080;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;id&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;init_xhtml&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;session&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Session.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;init_state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;on_notification&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;id&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; handler&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; _&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; _&lt;span style=&quot;color: #990000;&quot;&gt;))&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; session&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;

  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;notify&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;fragment &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fragment&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'msg&lt;span style=&quot;color: #990000;&quot;&gt;),&lt;/span&gt; msg &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #008080;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;Session.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;send&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;fragment&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color: #FF0000;&quot;&gt;}}&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;First of all we will implement the fragment using a session, so an initialized fragment is just represented by a channel. However, due to the &lt;tt&gt;@abstract&lt;/tt&gt; keyword this representation will not be visible from outside of the package &lt;tt&gt;hands-on-opa.fragment&lt;/tt&gt;. That means that we will be able to manipulate fragments only using functions exposed by the &lt;tt&gt;CFragment&lt;/tt&gt; module — a neat way to accomplishing abstraction and ensure invariants on data.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;The &lt;tt&gt;create&lt;/tt&gt; function takes 3 arguments:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;
&lt;tt&gt;init_state&lt;/tt&gt;: the initial state of the fragment,
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
&lt;tt&gt;init_xhtml&lt;/tt&gt;: the initial XHTML representation of the fragment,
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
&lt;tt&gt;handler&lt;/tt&gt;: the handler for fragment notifications, which given the &lt;tt&gt;state&lt;/tt&gt; and the incoming &lt;tt&gt;msg&lt;/tt&gt; should return a &lt;tt&gt;CFragment.action&lt;/tt&gt; indicating how to handle this event.
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;What happens within the function is that we obtain a fresh DOM id, wrap the &lt;tt&gt;init_xhtml&lt;/tt&gt; with a &lt;tt&gt;&amp;lt;span&amp;gt;&lt;/tt&gt; with that id, create a session with the &lt;tt&gt;init_state&lt;/tt&gt; and finally return a pair of the XHTML for the fragment and the fragment itself (which as I mentioned we represent with a session).&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;The message handler for the session, &lt;tt&gt;on_notification&lt;/tt&gt;, uses the &lt;tt&gt;handler&lt;/tt&gt; given in the &lt;tt&gt;create&lt;/tt&gt; function to decide what to do with the incoming notification. It optionally re-renders the XHTML (using the produced id) and optionally modifies the state of the session (i.e. fragment).&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Finally we expose a &lt;tt&gt;notify&lt;/tt&gt; function which let's us send notifications to the fragment. Remember that the &lt;tt&gt;CFragment.fragment&lt;/tt&gt; type is abstract so anywhere outside of this package it is &lt;strong&gt;not&lt;/strong&gt; visible as a session. So if we did not expose this functionality, users of this module would not be able to send messages using &lt;tt&gt;Session.send&lt;/tt&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Ok, time to use our fragment component to implement the timer functionality. Below is the final code:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;ftabs&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;
&lt;a href=&quot;http://blog.opalang.org/feeds/posts/default#watch&quot;&gt;watch.opa&lt;/a&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
&lt;a href=&quot;http://blog.opalang.org/feeds/posts/default#fragment&quot;&gt;fragment.opa&lt;/a&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div id=&quot;watch&quot;&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&lt;tt&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;import&lt;/span&gt;&lt;/span&gt; hands&lt;span style=&quot;color: #990000;&quot;&gt;-&lt;/span&gt;on&lt;span style=&quot;color: #990000;&quot;&gt;-&lt;/span&gt;opa&lt;span style=&quot;color: #990000;&quot;&gt;.&lt;/span&gt;fragment

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;show_time&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;t&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;Date.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;to_string&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;t&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;on_msg&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;_state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;date&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
  &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;re_render&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;some&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;show_time&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;date&lt;span style=&quot;color: #990000;&quot;&gt;))&lt;/span&gt; &lt;span style=&quot;color: #008080;&quot;&gt;change_state&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;none&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;page&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
  &lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;timer_xhtml&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; timer&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;create&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;show_time&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(Date.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;now&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()),&lt;/span&gt; on_msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;update_timer&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;notify&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;timer&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=Date.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;now&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;do&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Scheduler.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;timer&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #993399;&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; update_timer&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
  timer_xhtml

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;one_page_server&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&quot;What's the time?&quot;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; page&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;fragment&quot;&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&lt;tt&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;package&lt;/span&gt;&lt;/span&gt; hands&lt;span style=&quot;color: #990000;&quot;&gt;-&lt;/span&gt;on&lt;span style=&quot;color: #990000;&quot;&gt;-&lt;/span&gt;opa&lt;span style=&quot;color: #990000;&quot;&gt;.&lt;/span&gt;fragment

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;type&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;action&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'state&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
  &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt; re_render &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;option&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;color: #990000;&quot;&gt;;&lt;/span&gt; change_state &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;option&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'state&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;

&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;@abstract&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;type&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fragment&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;channel&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color: #008080;&quot;&gt;CFragment&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
&lt;span style=&quot;color: #FF0000;&quot;&gt;{{&lt;/span&gt;

  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;@private&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;on_notification&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;id&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; handler&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;res&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;handler&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;re_render&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Dom.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;transform&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;([&lt;/span&gt;#&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;id&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;])&lt;/span&gt;
    &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;do&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Option.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iter&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;re_render&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; res&lt;span style=&quot;color: #990000;&quot;&gt;.&lt;/span&gt;re_render&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;match&lt;/span&gt;&lt;/span&gt; res&lt;span style=&quot;color: #990000;&quot;&gt;.&lt;/span&gt;change_state &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;with&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;none&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;unchanged&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;some&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;new_state&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;new_state&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;

  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;create&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;init_state &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; init_xhtml &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt;
         handler &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; 'msg &lt;span style=&quot;color: #990000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;action
        &lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fragment&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'t&lt;span style=&quot;color: #990000;&quot;&gt;))&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;id&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Dom.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fresh_id&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;()&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;xhtml&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;&lt;/span&gt;span &lt;span style=&quot;color: #008080;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;id&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;{&lt;/span&gt;init_xhtml&lt;span style=&quot;color: #FF0000;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span style=&quot;color: #008080;&quot;&gt;session&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;Session.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;init_state&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;on_notification&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;id&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; handler&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; _&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; _&lt;span style=&quot;color: #990000;&quot;&gt;))&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;xhtml&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; session&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;

  &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;notify&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;fragment &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;CFragment.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;fragment&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;'msg&lt;span style=&quot;color: #990000;&quot;&gt;),&lt;/span&gt; msg &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; 'msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #008080;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #990000;&quot;&gt;=&lt;/span&gt;
    &lt;span style=&quot;color: #990000;&quot;&gt;Session.&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;send&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #990000;&quot;&gt;(&lt;/span&gt;fragment&lt;span style=&quot;color: #990000;&quot;&gt;,&lt;/span&gt; msg&lt;span style=&quot;color: #990000;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color: #FF0000;&quot;&gt;}}&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span class=&quot;run&quot;&gt;&lt;a href=&quot;http://watch_fragment.tutorials.opalang.org&quot; target=&quot;_blank&quot;&gt;Run&lt;/a&gt;&lt;/span&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;The &lt;tt&gt;show_time&lt;/tt&gt; function converts a &lt;tt&gt;Date.date&lt;/tt&gt; to its &lt;tt&gt;xhtml&lt;/tt&gt; representation. The &lt;tt&gt;on_msg&lt;/tt&gt; function reacts to notifications send to the timer fragment — we don't use the state, handle only one type of messages, namely requests to update the timer &lt;tt&gt;date&lt;/tt&gt; and instruct the fragment to re-render itself with &lt;tt&gt;show_time(date)&lt;/tt&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;In the &lt;tt&gt;page()&lt;/tt&gt; function we first create a fragment with empty state (&lt;tt&gt;void&lt;/tt&gt;), &lt;tt&gt;show_time(Date.now())&lt;/tt&gt; as the initial representation and &lt;tt&gt;on_msg&lt;/tt&gt; as the notification handler — this gives us initial HTML (&lt;tt&gt;timer_xhtml&lt;/tt&gt;) and the fragment itself (&lt;tt&gt;timer&lt;/tt&gt;). The &lt;tt&gt;update_timer()&lt;/tt&gt; function sends a notification to the timer asking it to update itself with &lt;tt&gt;Date.now()&lt;/tt&gt;. Finally we schedule calls to &lt;tt&gt;update_timer&lt;/tt&gt; every second (or 1000 milliseconds) and return the initial HTML, &lt;tt&gt;timer_xhtml&lt;/tt&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;admonitionblock&quot;&gt;
&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Exercise&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Note that in the above code the &lt;tt&gt;timer&lt;/tt&gt; fragment lives on the server, which means that every timer update will make a round trip to the server. It's equivalent to the slow variant of this example that we developer in the &lt;a href=&quot;http://blog.opalang.org/2011/07/interactivity-even-handling.html&quot;&gt;original timer post&lt;/a&gt;. How would you fix that? (i.e. make the timer update fully in the browser without any communication with the server).&lt;/p&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Uff. We're done. Only after writing this explanation I realized that this example can be quite heavy. Please take your time to slowly go through it and understand it (and if you're lost give me a shout in the comments… just please be patient if I don't react before coming back from holidays). If you really want to nail it down I'd suggest experimenting with this example, or developing something of your own.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Now, let's sit back and evaluate what we've achieved. The code is certainly not simpler than what we started with — on the contrary. However, the &lt;tt&gt;CFragment&lt;/tt&gt; module is a useful abstraction that can be re-used in different contexts (maybe it should even make its way to Opa's stdlib?).&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;The code in &lt;tt&gt;watch.opa&lt;/tt&gt; may not look simpler than what we had, but I'd argue it's cleaner. Imagine a more complex code with many fragments being updated in different places, by different triggers. Before we had dirty, direct DOM manipulations and all it took for things to go wrong was to make a typo in element's id or mistakenly use another id.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Now we replaced that with an event-based update system. To update a fragment we need to pass it to &lt;tt&gt;CFragment.notify&lt;/tt&gt; so we cannot notify a non-existing fragment (though it can still happen that we forget to place the fragment within a page, resulting in the update having no effect). And fragments with different functionalities will likely respond to different type of notifications, so, to some extent, the type system will help us detect attempts at updating a wrong fragment.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;&lt;em&gt;Open a mental parenthesis for a side note&lt;/em&gt;. By the way, we received some complaints that in spite of all the fancy features, Opa is in some sense quite low-level because it work on the level of HTML. I'll be the first to agree with some criticism of Opa (it's a very new language after all), but I cannot agree with this one. To begin whatever framework/language you believe in ultimately pages &lt;strong&gt;are&lt;/strong&gt; just HTML (unless what you believe in is Flash, but in that case I'd suggest you consider learning HTML, and fast). Abstracting it away, building something on top of HTML and exposing only this more high-level language to the developer is of course possible. But is that a good thing? I think at one time or another it'll come back biting your head; for instance when one wants to do something more fancy which is possible in HTML but was lost in the abstraction (and preserving all the features while simplifying the formalism is not an easy task).&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;But even more importantly: you can do that in Opa. No one stops you from building some higher-level abstraction over HTML — in fact Opa is quite well equipped to do so! In a sense, this is already slowly happening with extensions to our library of widgets and components which are higher-level elements to build pages with. Another interesting development in this direction is the &lt;a href=&quot;http://doc.opalang.org/#!/module/stdlib.web.template/Template&quot;&gt;Templating machinery&lt;/a&gt;, which allows, err, templating. Finally there is no reason not to develop a domain-specific language in Opa that could be used to replace (or complement) HTML markup, although I'm not aware of any efforts in that direction (and frankly personally I don't see a need for that).&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Long story short: Opa maps to HTML in a very truthful manner. And that's good. If you want some higher-level framework on top, Opa is well equipped to handle that too. &lt;em&gt;End of the side note.&lt;/em&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;&lt;p&gt;Ok, time to wrap up this post. I'm not sure how successful I was in persuading you that sessions are important (and powerful) (and versatile). If I didn't, not to worry, we'll see them over and over again on this blog and I hope that eventually I'll prove my point.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/tracker/2073503406800427577-1975673674199781114?l=blog.opalang.org&quot; alt=&quot;&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;&lt;/div&gt;</content:encoded>
	<dc:date>2012-01-27T13:33:23+00:00</dc:date>
	<dc:creator>Adam Koprowski</dc:creator>
</item>
<item rdf:about="https://forge.ocamlcore.org/forum/forum.php?forum_id=821">
	<title>OCamlCore Forge News: libsndfile-ocaml 0.8 available</title>
	<link>https://forge.ocamlcore.org/forum/forum.php?forum_id=821</link>
	<content:encoded>This is Erik de Castro Lopo own binding to it's libsndfile, maintained by Ph.Strauss. Usefull for reading/writing various audio file formats. Tarball and public git should be ok now.</content:encoded>
	<dc:date>2012-01-26T18:35:25+00:00</dc:date>
	<dc:creator>Philippe STRAUSS</dc:creator>
</item>
<item rdf:about="http://caml.inria.fr/cgi-bin/hump.cgi?contrib=796">
	<title>The Caml Humps: Zermelo Proof Checker 1.0</title>
	<link>http://caml.inria.fr/cgi-bin/hump.cgi?contrib=796</link>
	<content:encoded>The Zermelo Proof Checker (ZPC) is a lightweight proof assistant based on standard set theory and Hindley-Milner type theory.</content:encoded>
	<dc:date>2012-01-26T09:42:09+00:00</dc:date>
</item>
<item rdf:about="https://forge.ocamlcore.org/projects/libsndfile/">
	<title>OCamlCore Forge Projects: libsndfile</title>
	<link>https://forge.ocamlcore.org/projects/libsndfile/</link>
	<content:encoded>Binding to Libsndfile, audio files reading/writing</content:encoded>
	<dc:date>2012-01-24T13:00:43+00:00</dc:date>
</item>
<item rdf:about="http://alan.petitepomme.net/cwn/2012.01.24.html">
	<title>Caml Weekly News: Caml Weekly News, 24 Jan 2012</title>
	<link>http://alan.petitepomme.net/cwn/2012.01.24.html</link>
	<content:encoded>otags reloaded 3.12.1 for OCaml 3.12.1 / ounit v1.1.1: Unit testing framework / polymorphic variants in match statements / Other Caml News</content:encoded>
	<dc:date>2012-01-24T12:00:00+00:00</dc:date>
</item>
<item rdf:about="http://www.nicollet.net/?p=2660">
	<title>Victor Nicollet: OCaml Submodule Pattern</title>
	<link>http://www.nicollet.net/2012/01/ocaml-submodule-pattern/</link>
	<content:encoded>&lt;p&gt;My code is quite large for an OCaml project. The main RunOrg repository alone contains 46212 lines of OCaml code (plus an additional 5631 lines of OCaml mli files) — and then, there’s the web framework code and the independent plugins code.&lt;/p&gt;
&lt;p&gt;It’s is Better™ to have many short files than a few long ones. One reason is incremental compiling with &lt;em&gt;ocamlbuild&lt;/em&gt; : that the smaller your files are, the smaller the percentage of code to be compiled when you make a small change. Another reason is that files provide a natural delineation of code that makes it slightly easier to reason about.&lt;/p&gt;
&lt;p&gt;The very process of splitting a large file into smaller files is also an excellent way to clean up the code. Every split is an opportunity to move some code to a more generic location — why have a &lt;code&gt;CMember_importParser&lt;/code&gt; module when all of its functionality could fit into an &lt;code&gt;OzCsv&lt;/code&gt; plugin module ? Even when no such generic solution exists, cutting through the jungle that a 2000-line module contains helps clean up dependencies, identify shared functionality and imagine better ways to design code.&lt;/p&gt;
&lt;p&gt;Still, when cutting up code this way, the problem of encapsulation remains. If code that relates to pictures (an upload module, a transform module, a download module, an access rights module) is split across several files, it is desirable to let each file access functions and values from other values that would not otherwise be shown to modules not related to picture processing. For instance, a &lt;code&gt;get_download_link&lt;/code&gt; function should be available throughout all picture-related modules, but the rest of the application should use the &lt;code&gt;get_download_link_for_user&lt;/code&gt; function that checks whether the user is allowed to download the file.&lt;/p&gt;
&lt;p&gt;In order to achieve several nested levels of encapsulation required to work with modules this way, I have come up with a convention :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A module name (and thus, a file name) is composed of segments written in camelCase and separated by underscores. For instance, &lt;code&gt;CEntity_view_grid&lt;/code&gt; is a module name containing segments &lt;code&gt;CEntity,&lt;/code&gt; &lt;code&gt;view&lt;/code&gt; and &lt;code&gt;grid&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Modules with only one segment are public. Any other module may include, open or otherwise reference them with no limitations beyond what the module signature says. So, &lt;code&gt;CEntity&lt;/code&gt; may access &lt;code&gt;MGroup&lt;/code&gt; freely.&lt;/li&gt;
&lt;li&gt;Modules with N &amp;gt; 1 segments are private. They may only be accessed by modules which share the first N-1 segments. So, &lt;code&gt;CEntity_view&lt;/code&gt; is available to modules &lt;code&gt;CEntity&lt;/code&gt; and &lt;code&gt;CEntity_edit&lt;/code&gt; but not &lt;code&gt;CPicture&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A module with N segments may export any module with N+1 segments it can access, possibly under a more restrictive signature. For instance, &lt;code&gt;CEntity_view&lt;/code&gt; is available to all other modules as &lt;code&gt;CEntity.View&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To make these rules easier to respect, private module dependencies are made explicit by adding a list of module aliases at the top of each file. The top of my &lt;code&gt;cEntity_view.ml&lt;/code&gt; file starts with :&lt;/p&gt;
&lt;pre style=&quot;padding-left: 30px;&quot;&gt;&lt;code&gt;module Sidebar     = CEntity_sidebar
module Unavailable = CEntity_unavailable
module Edit        = CEntity_edit
module Info        = CEntity_view_info
module Directory   = CEntity_view_directory
module Grid        = CEntity_view_grid
module Wall        = CEntity_view_wall
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is forbidden to use a private module without going through such an alias, and it is forbidden to define such an alias anywhere except at the top of the file. This makes it extremely easy to determine whether private access rules are respected.&lt;/p&gt;
&lt;p&gt;The rule of thumb for splitting files (in my particular coding style) is :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code for separate layers (model, view, controller…) go into separate public modules.&lt;/li&gt;
&lt;li&gt;For complex code (such as complex rules in model or controller code), consider splitting files larger than 200 lines.&lt;/li&gt;
&lt;li&gt;For simple code (such as HTML template or JSON serialization definitions), there is no splitting limit except for factoring out common behavior.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
	<dc:date>2012-01-23T16:55:59+00:00</dc:date>
	<dc:creator>Victor Nicollet</dc:creator>
</item>

</rdf:RDF>

