{"id":33,"date":"2010-07-19T22:53:50","date_gmt":"2010-07-20T03:53:50","guid":{"rendered":"https:\/\/dalnefre.com\/wp\/?p=33"},"modified":"2022-10-19T13:07:12","modified_gmt":"2022-10-19T19:07:12","slug":"message-passing-part-2-object-oriented-method-invocation","status":"publish","type":"post","link":"https:\/\/dalnefre.com\/wp\/2010\/07\/message-passing-part-2-object-oriented-method-invocation\/","title":{"rendered":"Message Passing, part 2 &#8211; Object-Oriented Method Invocation"},"content":{"rendered":"<p>This is part two of an article exploring what we mean when we say &#8220;message-passing&#8221;. <a title=\"Synchronous Rendezvous\" href=\"https:\/\/dalnefre.com\/wp\/2010\/07\/message-passing-part-1-synchronous-rendezvous\/\">Part one<\/a> described how synchronous rendezvous can be expressed with actors. Part two describes an actor implementation of object-oriented method invocation. For Object-Oriented developers from the Smalltalk tradition, message-passing involves a dynamic method lookup, invocation of that method with the target object as an implicit parameter, and return of a result object. We will deconstruct this mechanism and show it in more primitive form, using actors.<\/p>\n<p>Ian Piumarta and his colleagues on the <a href=\"http:\/\/www.vpri.org\/fonc_wiki\/\">FoNC project<\/a> propose a primitive &#8220;pervasively late-bound&#8221; object model [1]. This model defines a small collection of basic objects and methods, centering around dynamic method lookup and invocation. Late-binding of the lookup mechanism is used to implement an impressive variety of object-oriented method invocation mechanisms. These include single inheritance, multiple inheritance, and sideways composition (Lieberman prototypes) [2]. Unfortunately, even this primitive object-oriented method invocation mechanism itself &#8220;binds&#8221; certain design decisions, such as the call-lookup-invoke-return protocol. Synchronous rendezvous and asynchronous messaging are not supported by this mechanism. Instead, we will use actor primitives to express object-oriented method invocation as a pattern of asynchronous messages.<\/p>\n<p><a name=\"object-oriented\"><\/a><\/p>\n<h2>Implementing Object-Oriented Method Invocation<\/h2>\n<p>Object-oriented method invocation involves method lookup, method invocation with an implicit &#8220;self&#8221; parameter, and return of a result object. Once the applicable method is found, it is invoked in the context of the target object (self). Eventually a result object is returned to the original caller. The FoNC project gains considerable flexibility by allowing late-binding of method-lookup strategies. For example, a simple chain of method dictionaries could provide appropriate semantics for single-inheritance. We encapsulate the lookup policy in the &#8220;class&#8221; actor, allowing flexibility in selecting the strategy. The &#8220;class&#8221; is provided as part of the &#8220;object&#8221; state. The &#8220;object&#8221; behavior supports access to instance variables and invocation of methods.<\/p>\n<pre>LET object_beh(class, vars) = \\(cust, req).[\n\tCASE req OF\n\t(#get, var) : [\n\t\tSEND (cust, SELF, #get, var) TO vars\n\t]\n\t(#set, var, value) : [\n\t\tSEND (cust, SELF, #set, var, value) TO vars\n\t]\n\t(#call, selector, args) : [\n\t\tCREATE call WITH call_beh(cust, SELF, selector, args)\n\t\tSEND (call, #lookup, selector, args) TO class\n\t]\n\tEND\n]<\/pre>\n<p>When an object receives a <code>#get<\/code> or <code>#set<\/code> request, the request is delegated to the instance variables along with the identity of the original object &#8220;self&#8221;. Instance variable are described in more detail later.<\/p>\n<p>When an object receives a method invocation request, it first must perform a lookup to find the applicable method to invoke. This is done by sending a <code>#lookup<\/code> request to the &#8220;class&#8221; object. The <code>#lookup<\/code> request includes the selector and the arguments. The class object is free to use any means it wants to find the applicable method. It may use only the selector, or it may use some or all of the arguments.<\/p>\n<p>The customer of the <code>#lookup<\/code> request is a dynamically created &#8220;call&#8221; actor. The &#8220;call&#8221; actor remembers the original caller, the instance on which to apply the method, the selector and the arguments.<\/p>\n<pre>LET call_beh(caller, instance, selector, args) = \\method.[\n\tSEND (caller, instance, selector, args) TO method\n]<\/pre>\n<p>The <var>struct_class<\/var> implements structured records with public data fields. This simple &#8220;class&#8221; implementation determines the applicable method by matching a static set of selectors. The only methods it understands are <code>#get<\/code> and <code>#set<\/code>.<\/p>\n<pre>CREATE struct_class WITH \\(call, #lookup, selector, args).[\n\tCASE selector OF\n\t#get : [ SEND get_method TO call ]\n\t#set : [ SEND set_method TO call ]\n\tEND\n]<\/pre>\n<p>When a method is returned from a lookup, the method is &#8220;invoked&#8221; by sending the original caller, the &#8220;self&#8221; instance, the selector and the arguments to the &#8220;method&#8221; actor. The method may read and write instance variables by sending <code>#get<\/code> and <code>#set<\/code> messages to the &#8220;instance&#8221; actor. The <var>get_method<\/var> and <var>set_method<\/var> returned by <var>struct_class<\/var> use these <code>#get<\/code> and <code>#set<\/code> messages.<\/p>\n<pre>CREATE get_method WITH \\(caller, instance, selector, args).[\n\tSEND (caller, #get, args) TO instance\n]\nCREATE set_method WITH \\(caller, instance, selector, args).[\n\tSEND (caller, #set, args) TO instance\n]<\/pre>\n<p>Public access to fields can be implemented with generic methods such as the <var>get_method<\/var> and <var>set_method<\/var> shown here. A <code>#get<\/code> message retrieves the field value and sends it to the original caller. A <code>#set<\/code> message updates the field with a new value and sends the instance to the original caller. Note that these method-actors can be reused in many classes and applied to any object.<\/p>\n<p>Each variable is represented by a separate actor. The state of a variable actor includes its name, its value, and a link to the next variable.<\/p>\n<pre>LET variable_beh(name, value, next) = \\(cust, instance, req).[\n\tCASE req OF\n\t(#get, $name) : [\n\t\tSEND value TO cust\n\t]\n\t(#set, $name, value') : [\n\t\tBECOME variable_beh(name, value', next)\n\t\tSEND instance TO cust\n\t]\n\t_ : [\n\t\tSEND (cust, instance, req) TO next\n\t]\n\tEND\n]<\/pre>\n<p>When a variable receives a <code>#get<\/code> request with a matching name, the value is sent to the customer. When a variable receives a <code>#set<\/code> request with a matching name, the actor retains the new value and sends the &#8220;self&#8221; object instance to the customer. All other requests are forwarded to the next variable in the chain. The chain ends with a special &#8220;undefined&#8221; actor, which signals an error.<\/p>\n<pre>CREATE y_var WITH variable_beh(#y, 1, UNDEF)\nCREATE x_var WITH variable_beh(#x, 0, y_var)\nCREATE a_point WITH object_beh(struct_class, x_var)<\/pre>\n<p>Given these definitions, we create an example Point object with instance variables <var>x<\/var> = 0 and <var>y<\/var> = 1, as illustrated in Figure 1.<\/p>\n<div id=\"attachment_34\" style=\"width: 362px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/dalnefre.com\/wp\/2010\/07\/message-passing-part-2-object-oriented-method-invocation\/messaging-models-fig2\/\" rel=\"attachment wp-att-34\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-34\" class=\"size-full wp-image-34\" title=\"A &quot;Point&quot; Object\" src=\"https:\/\/dalnefre.com\/wp\/wp-content\/uploads\/2010\/07\/messaging-models-fig2-e1279597365733.png\" alt=\"\" width=\"352\" height=\"292\"><\/a><p id=\"caption-attachment-34\" class=\"wp-caption-text\">Figure 1 &#8211; A &#8220;Point&#8221; Object<\/p><\/div>\n<p>Now we focus on the message flow involved in handling a &#8220;set&#8221; method call to set the instance variable <var>y<\/var> to -1, as illustrated in Figure 2. Note that the object instance itself is the final &#8220;result&#8221; returned.<\/p>\n<div id=\"attachment_35\" style=\"width: 539px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/dalnefre.com\/wp\/2010\/07\/message-passing-part-2-object-oriented-method-invocation\/messaging-models-fig3\/\" rel=\"attachment wp-att-35\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-35\" class=\"size-full wp-image-35 \" title=\"Setter Message Flow\" src=\"https:\/\/dalnefre.com\/wp\/wp-content\/uploads\/2010\/07\/messaging-models-fig3-e1279597537443.png\" alt=\"\" width=\"529\" height=\"464\"><\/a><p id=\"caption-attachment-35\" class=\"wp-caption-text\">Figure 2 &#8211; Setter Message Flow.<\/p><\/div>\n<p>Each part of the meta-object protocol is represented by a separate actor. This gives very fine-grained control over the process of invoking methods on objects. A shared instance of <var>struct_class<\/var> defines the method lookup policy for any simple structured record object. Shared instances of <var>set_method<\/var> and <var>get_method<\/var> provide &#8220;setter&#8221; and &#8220;getter&#8221; implementations for any objects&#8217; instance variables.<\/p>\n<p>More sophisticated class implementations could restrict access to read-only by withholding the &#8220;set&#8221; method. Access can be controlled for specific variables by matching their names as part of the lookup policy. Method calls may be <a title=\"Implementing Serializers\" href=\"https:\/\/dalnefre.com\/wp\/2010\/05\/composing-actors\/\">serialized<\/a> to prevent concurrent access to shared state. Every part of the meta-object protocol is explicitly exposed and reconfigurable, even within a running system. Mechanisms and policies may even vary between different groups of objects, if desired. Expressing the protocol of object-oriented method calls in terms of actors provides a powerful mechanism for understanding and modifying the semantics of the object model itself.<\/p>\n<p><a name=\"conclusion\"><\/a><\/p>\n<h2>Conclusion<\/h2>\n<p>The phrase &#8220;message-passing&#8221; has a wide range of accepted meanings. Asynchronous messaging is the most primitive in terms of information content. In <a title=\"Implementing Synchronous Rendezvous\" href=\"https:\/\/dalnefre.com\/wp\/2010\/07\/message-passing-part-1-synchronous-rendezvous\/\">part one<\/a>, we implemented synchronous rendezvous. In part two, we showed how the basic mechanism of object-oriented method invocation can be implemented on the asynchronous messaging foundation provided by the Actor model of computation. The additional information flow implicit in these models is made explicit through an actor-based implementation. This allows us to better understand (and explore modifications of) each message-passing model.<\/p>\n<p><a name=\"references\"><\/a><\/p>\n<h2>References<\/h2>\n<dl>\n<dt>[1]<\/dt>\n<dd>I. Piumarta. Open, extensible object models. VPRI Memo 2006-003-a, <a href=\"http:\/\/vpri.org\/pdf\/tr2006003a_objmod.pdf\">http:\/\/vpri.org\/pdf\/tr2006003a_objmod.pdf<\/a><\/dd>\n<dt>[2]<\/dt>\n<dd>I. Piumarta. Efficient Sideways Composition via &#8216;Lieberman&#8217; Prototypes. VPRI Memo 2007-002-a, <a href=\"http:\/\/vpri.org\/pdf\/m2007002a_lieb_proto.pdf\">http:\/\/vpri.org\/pdf\/m2007002a_lieb_proto.pdf<\/a><\/dd>\n<\/dl>\n","protected":false},"excerpt":{"rendered":"<p>This is part two of an article exploring what we mean when we say &#8220;message-passing&#8221;. Part one described how synchronous rendezvous can be expressed with actors. Part two describes an actor implementation of object-oriented method invocation. For Object-Oriented developers from the Smalltalk tradition, message-passing involves a dynamic method lookup, invocation of that method with the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[4,32,10,31,25,33,17,42],"class_list":["post-33","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-actor","tag-cola","tag-composition","tag-fonc","tag-message-passing","tag-object-oriented","tag-protocol","tag-smalltalk"],"_links":{"self":[{"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/posts\/33","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/comments?post=33"}],"version-history":[{"count":0,"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/posts\/33\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/media?parent=33"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/categories?post=33"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalnefre.com\/wp\/wp-json\/wp\/v2\/tags?post=33"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}