{"id":387,"date":"2007-04-17T08:00:00","date_gmt":"2007-04-17T08:00:00","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2007\/04\/17\/the-calculus-storage-cell\/"},"modified":"2007-04-17T08:00:00","modified_gmt":"2007-04-17T08:00:00","slug":"the-calculus-storage-cell","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2007\/04\/17\/the-calculus-storage-cell\/","title":{"rendered":"The &#960;-Calculus Storage Cell"},"content":{"rendered":"<p> As I did with my first attempt at explaining &pi;-calculus, I think that before getting into any of the deep semantics, it&#8217;s good to look at a few examples of things you can build with &pi;-calculus. But before getting to the meat of the post, I&#8217;ll give you the answer the puzzle I left in the last post. What&#8217;s wrong with the example I gave for &#8220;Hello world&#8221; yesterday?<\/p>\n<p> As a reminder, the question was: Assume &#8220;out&#8221; is the name for a channel that is read by a process that prints whatever it receives to the standard output. What&#8217;s wrong with the following process as an implementation of &#8220;Hello World&#8221;?<\/p>\n<pre>\nnew(in).{ *(?in(x).!out(x).&empty;)\n| !in(hello).!in(world).&empty; }\n<\/pre>\n<p><!--more--><\/p>\n<p> As one commenter correctly answered, there is no guarantee that &#8220;hello&#8221; will be printed before &#8220;world&#8221;. Let&#8217;s first do the two reduction in the non-replicated subprocess. Then we&#8217;ll end up with:<\/p>\n<pre>\nnew(in).{ !out(hello).&empty; | !out(world).&empty; | *(?in(x).&empty;) }\n<\/pre>\n<p> Now, we can do a reduction with <em>either<\/em> of the two processes trying to send to out. There&#8217;s no guarantee that &#8220;<code>!out(hello)<\/code>&#8221; will get reduced before &#8220;<code>!out(world)<\/code>&#8220;.<\/p>\n<p> The correct way to do it is to explicitly synchronize things: don&#8217;t let the message &#8220;world&#8221; get sent, until after you know &#8220;hello&#8221; has been printed out:<\/p>\n<pre>\nnew(in,sync).{ *(?in(x).!out(x).!sync().&empty;)\n| !in(hello).?sync().!in(world).?sync().&empty;  }\n<\/pre>\n<hr \/>\n<p> I&#8217;m going to use the syntax I introduced in the previous post, with<br \/>\n<em>one<\/em> addition: named process definitions.<\/p>\n<p> A named process definition is really just a shorthand. A recursive named-process<br \/>\ndefinition is really just sugar for a replication expression; and a non-recursive one is<br \/>\nobviously just shorthand for a textual replacement of the process name with the process<br \/>\ndefinition assigned to it. Similarly, when a process definition takes parameters, there&#8217;s a<br \/>\ntranslation of that into messages. I&#8217;m not going to explain the expansion of recursive<br \/>\nprocess definitions or parameters in this post &#8211; but I <em>will<\/em> come back to it in a<br \/>\nfuture post when we start getting into the detailed semantics. The way that I&#8217;ll write a<br \/>\nnamed process definition is &#8220;<code>Name[params]&equiv;<em>Process<\/em><\/code>&#8220;; and for<br \/>\nclarity, I&#8217;ll always use names starting with an uppercase letter for processes, and names<br \/>\nstarting with a lowercase character for channel names and variables.<\/p>\n<p> One very useful thing to have if we&#8217;re going to write real programs using &pi;-calculus is mutable storage cells. In terms of &pi;-calculus, a mutable storage cell is a process<br \/>\nwith two channels: one for reading the value of the cell, and one for writing a new value into the cell.<\/p>\n<p> To update the cell, a client will <em>send<\/em> a message to the cell&#8217;s &#8220;write&#8221; channel containing the new value; to read the value of the cell, a client will <em>receive<\/em> a message from channel&#8217;s &#8220;read&#8221; channel. Based on that description, here&#8217;s a process definition which would be most peoples first attempt at defining Cell:<\/p>\n<pre>\nCell[val]&equiv;new(read,write).{?write(v).Cell[v]\n+!read(val).Cell[val]}\n<\/pre>\n<p> What that says is: &#8220;Cell&#8221; is a shorthand for a process expression which is parametric in a value, called &#8220;val&#8221;. Cell introduces its own read and write channels, and then either allows a client to read the value in the cell, or update the value in the cell. There&#8217;s a bit of trickiness for people who aren&#8217;t used to process calculi: writing to replace the value inside the cell is done by <em>reading<\/em> a message: <code>?write(v)<\/code> a client needs to <em>send<\/em> a message containing a value to update the cell; and for clients to read the value from the cell, the cell has to <em>write<\/em> to the read channel: !read(val) &#8211; sending a message <em>to<\/em> the client containing the value in the cell. &#8220;read&#8221; and &#8220;write&#8221; are from the perspective of the client; they&#8217;re backwards from the perspective of the cell.<\/p>\n<p> This cell implementation is close, but it isn&#8217;t correct, and the reason why illustrates some of the subtleties of &pi;-calculus. What&#8217;s wrong with it? There are problems with channel naming &#8211; and channel naming and the subtleties of managing them are at the heart of how things work in &pi;-calculus.<\/p>\n<ol>\n<li> The &#8220;<code>new(read,write)<\/code>&#8221; creates two channels, <em>scoped locally<\/em>  to the Cell process. That means that no one outside of the cell process can see them! They&#8217;re initially scoped to Cell, and there&#8217;s no method inside of Cell to send the channel name outside of its name-scope. So it&#8217;s a storage cell, but no one can ever actually read it or write to it.<\/li>\n<li> The &#8220;new&#8221; that creates the channel is inside of the part that is invoked recursively. So each time that &#8220;Cell&#8221; is invoked, it creates new channel names. So even if some client had access to the channel names of the cell at some point in time, any time that the cell was read or written, it would allocate new names, and the client would no longer be able to access it.<\/li>\n<\/ol>\n<p> To fix it, we need to do two things. First, we need to change the cell definition so that it only allocates its read and write channel names once, and then reuses them. And second, we need to provide some way of making those channel names available to a client.<\/p>\n<p> To remove the allocation of the channel names from the recursive part of the process, we&#8217;ll split the process definition into two parts: one which will only be executed once, and one which executes recursively:<\/p>\n<pre>\nNewCell[val]&equiv;new(read,write)Cell[read,write,val]\nCell[read,write,val]&equiv;{!read(val).Cell[read,write,val]\n+ ?write(v).Cell[read,write,v]}\n<\/pre>\n<p> Fixing the other problem is also easy. We want to make the names of the<br \/>\ncell&#8217;s read and write channels available to a client. How do we do that in &pi;-calculus? There&#8217;s only one way of moving values around in a &pi;-calculus process: message passing. So when someone wants to create a cell, they&#8217;ll send a message to<br \/>\na cell factory process containing an initial value for the cell, and the name of<br \/>\na channel where the new cell&#8217;s read and write channel names should be sent:<\/p>\n<pre>\nNewCell[creator,initval]&equiv;new(read,write).{Cell[read,write,initval]\n| !creator(read,write) }\nCell[read,write,val]&equiv;{!read(val).Cell[read,write,val]\n+ ?write(v).Cell[read,write,v]}\n<\/pre>\n<p> To create and use a cell, the client process just invokes NewCell, passing it<br \/>\na message containing a channel name where it wants to receive the read and write channels of the cell:<\/p>\n<pre>\nnew(self).{ NewCell[self,0]\n| ?(cellread,cellwrite).(...)  }\n<\/pre>\n<p> So, for example, we can write a process which allocates a cell, prints out its initial value, updates the cell value, and then prints out the new value like this:<\/p>\n<pre>\nnew(self).{NewCell[self,0]\n| ?(cellread,cellwrite).?cellread(v).!out(v).!cellwrite(7).?cellread(w).!out(w)}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>As I did with my first attempt at explaining &pi;-calculus, I think that before getting into any of the deep semantics, it&#8217;s good to look at a few examples of things you can build with &pi;-calculus. But before getting to the meat of the post, I&#8217;ll give you the answer the puzzle I left in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[50],"tags":[],"class_list":["post-387","post","type-post","status-publish","format-standard","hentry","category-pi-calculus"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-6f","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/387","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/comments?post=387"}],"version-history":[{"count":0,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/387\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=387"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=387"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=387"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}