User Tools

Site Tools


at:tutorial:multiparadigm

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
at:tutorial:multiparadigm [2007/07/27 10:23]
tvcutsem added
at:tutorial:multiparadigm [2011/06/07 18:29] (current)
tvcutsem *minor
Line 1: Line 1:
 ====== On Scoping, Closures, Methods and Messages ====== ====== On Scoping, Closures, Methods and Messages ======
  
-This tutorial chapter goes into a bit more detail on the subtle interplay between AmbientTalk's functional aspects (e.g. block closures, higher-order functions and lexical scoping) and its object-oriented aspects (e.g. objects and delegation). It is also described how methods and messages can be manipulated as first-class objects in their own right.+This tutorial chapter goes into a bit more detail on the interplay between AmbientTalk's functional aspects (e.g. block closures, higher-order functions and lexical scoping) and its object-oriented aspects (e.g. objects and delegation). It is also described how methods and messages can be manipulated as first-class objects in their own right.
  
 ===== Lexical Scope vs Object Scope ===== ===== Lexical Scope vs Object Scope =====
Line 13: Line 13:
   - Qualified access to a variable, e.g. ''o.x'', is **always** resolved in the receiver's object scope.   - Qualified access to a variable, e.g. ''o.x'', is **always** resolved in the receiver's object scope.
  
-These rules also hold for method invocation: the invocation ''f()'' is resolved lexically: ''f'' is looked up in the lexical scope; the invocation ''o.m()'' is resolved dynamically, i.e. ''m'' is looked up in ''o''These rules have a large effect on programs: lexical variable access can be statically determined, while qualified access is subject to //late binding// (enabling object-oriented polymorphism). As a programmer, you must be aware of the fundamental difference in semantics.+These rules also hold for method invocation: the invocation ''f()'' is resolved lexically: ''f'' is looked up in the lexical scope; the invocation ''o.m()'' is resolved dynamically, i.e. ''m'' is looked up in ''o''The difference is significant: lexical variable access can be statically determined, while qualified access is subject to //late binding// (enabling object-oriented polymorphism). As a programmer, you must be aware of the fundamental difference in semantics.
  
-Probably the most important conseqence of these rules is that great care has to be taken when an object accesses its own fields or methods. It can now do so in two ways. For example:+The most important consequence of these rules is that one should think carefully about how an object accesses its own fields or methods. It can now do so in two ways. For example:
  
 <code> <code>
Line 48: Line 48:
  
 <note important> <note important>
-For many object-oriented programmers, this distinction between performing ''m()'' and ''self.m()'' may seem confusing and even error-prone. After all, merely "forgetting" the qualified access disallows child objects to override the invocation to ''m''. The confusion stems from the fact that many OO languages -- like Java -- make no distinction between both access forms because they are not truly lexically scopedThey only consider the object scopeand hence unify ''m()'' with ''self.m()'' or ''this.m()''.+For many object-oriented programmers, this distinction between performing ''m()'' and ''self.m()'' may seem confusing and even error-prone. After all, merely "forgetting" the qualified access disallows child objects to override the invocation to ''m''. 
 + 
 +The confusion stems from the fact that many OO languages -- like Java -- make no distinction between both access forms. For examplein Java, if one writes ''m()'' and ''m'' is not lexically visible, it will be interpreted as if the programmer had written ''this.m()''. This solution, however, brings its own set of fragility problems to the table. Gilad Bracha provides a good overview of these in his paper [[http://dyla2007.unibe.ch/?download=dyla07-Gilad.pdf|on the Interaction of Method Lookup and Scope with Inheritance and Nesting]]. In terms of the categorization proposed in that paper, AmbientTalk adopts Bracha's 3rd option in dealing with the interaction between scoping and inheritance.
 </note> </note>
  
Line 67: Line 69:
 It is important that ''assertEquals'' is invoked by means of a self-send and not as ''assertEquals(1+1,1*2)''. The latter would result in an exception because ''assertEquals'' is not lexically visible, it is only visible within ''myTest'''s object scope. It is important that ''assertEquals'' is invoked by means of a self-send and not as ''assertEquals(1+1,1*2)''. The latter would result in an exception because ''assertEquals'' is not lexically visible, it is only visible within ''myTest'''s object scope.
  
-==== Nesting Objects ====+===== Nesting Objects =====
  
 AmbientTalk exploits its lexical scoping rules to the fullest extent by allowing as much program elements as possible to be nested. For example, it is possible to lexically nest objects within other objects, or even to nest functions within other functions. In this section, we describe how nested objects interact with the scoping rules presented above. AmbientTalk exploits its lexical scoping rules to the fullest extent by allowing as much program elements as possible to be nested. For example, it is possible to lexically nest objects within other objects, or even to nest functions within other functions. In this section, we describe how nested objects interact with the scoping rules presented above.
  
-=== Facets ===+==== Facets ====
  
 One of the most appealing use cases for nesting objects is that it allows a very secure kind of //sharing// between objects: all objects that are nested within another object have the privilege of all sharing the same lexical scope. This form of sharing is much more secure that sharing data via delegation, because the set of objects sharing the scope is statically fixed. In the E language, such nested objects are called [[http://www.erights.org/elib/capability/ode/ode-objects.html|facets]]. One of the most appealing use cases for nesting objects is that it allows a very secure kind of //sharing// between objects: all objects that are nested within another object have the privilege of all sharing the same lexical scope. This form of sharing is much more secure that sharing data via delegation, because the set of objects sharing the scope is statically fixed. In the E language, such nested objects are called [[http://www.erights.org/elib/capability/ode/ode-objects.html|facets]].
Line 97: Line 99:
 The ''distrustedFunction'' only has a reference to the ''reader'' object, allowing it to only invoke the ''read'' method. Because ''reader'' is lexically nested within the ''cell'', it has privileged access to the ''cell'''s fields, which it shares //only// with the ''writer'' object. If ''reader'' and ''writer'' would have shared ''cell'' by means of delegation, the ''distrustedFunction'' would still be able to access the ''contents'' field by means of delegation. Because ''reader'' is lexically nested within ''cell'' and the lexical scope is inaccessible to regular objects, the ''cell'' object remains entirely encapsulated w.r.t. ''distrustedFunction''. The ''distrustedFunction'' only has a reference to the ''reader'' object, allowing it to only invoke the ''read'' method. Because ''reader'' is lexically nested within the ''cell'', it has privileged access to the ''cell'''s fields, which it shares //only// with the ''writer'' object. If ''reader'' and ''writer'' would have shared ''cell'' by means of delegation, the ''distrustedFunction'' would still be able to access the ''contents'' field by means of delegation. Because ''reader'' is lexically nested within ''cell'' and the lexical scope is inaccessible to regular objects, the ''cell'' object remains entirely encapsulated w.r.t. ''distrustedFunction''.
  
-=== Nesting and Delegation ===+==== Nesting and Delegation ====
  
 Thanks to AmbientTalk's lexical scoping rules, nested objects have full access to the fields and methods of lexically enclosing objects. Note that within a nested object, the ''self'' pseudo-variable does refer to the nested object itself, as expected. Also, it is perfectly legal for a lexically nested object to have its own dynamic parent, for example: Thanks to AmbientTalk's lexical scoping rules, nested objects have full access to the fields and methods of lexically enclosing objects. Note that within a nested object, the ''self'' pseudo-variable does refer to the nested object itself, as expected. Also, it is perfectly legal for a lexically nested object to have its own dynamic parent, for example:
Line 129: Line 131:
 In the example above, writing ''self.assertEquals(a,b)'' would fail because ''self'' is then bound to ''inner'' which does not delegate to ''UnitTest''. Similarly, writing ''assertEquals(a,b)'' would fail because it is not lexically visible to ''inner'', it is only visible in the object scope of ''theTest''. In the example above, writing ''self.assertEquals(a,b)'' would fail because ''self'' is then bound to ''inner'' which does not delegate to ''UnitTest''. Similarly, writing ''assertEquals(a,b)'' would fail because it is not lexically visible to ''inner'', it is only visible in the object scope of ''theTest''.
  
-==== Methods vs Closures ====+===== Methods vs Closures =====
  
 As mentioned previously, AmbientTalk not only allows objects to be nested within other objects, but also allows functions to be nested within other functions. At this point, it becomes important to distinguish between //closures// and //methods//. As mentioned previously, AmbientTalk not only allows objects to be nested within other objects, but also allows functions to be nested within other functions. At this point, it becomes important to distinguish between //closures// and //methods//.
Line 152: Line 154:
 In the above example, ''meth'' is a method of ''o'' because it is defined as a function directly within an object clause. ''clo'' on the other hand, is a closure because it is nested within another method, so it does not belong to an object directly. This example also shows why methods do not close over ''self'' and closures do. A method can be thought of as a closure which is explicitly parameterized with an extra ''self'' variable, filled in by the interpreter upon method invocation. A closure is not parameterized with this extra variable, it simply inherits the value of ''self'' from its nested method. In the above example, ''meth'' is a method of ''o'' because it is defined as a function directly within an object clause. ''clo'' on the other hand, is a closure because it is nested within another method, so it does not belong to an object directly. This example also shows why methods do not close over ''self'' and closures do. A method can be thought of as a closure which is explicitly parameterized with an extra ''self'' variable, filled in by the interpreter upon method invocation. A closure is not parameterized with this extra variable, it simply inherits the value of ''self'' from its nested method.
  
-=== Top-level Functions ===+==== Top-level Functions ====
  
 Top-level functions are actually methods in AmbientTalk. This is because all top-level code is treated as the initialization code of that file's module object. Hence, it is legal to use ''self'' in top-level functions. Top-level functions are actually methods in AmbientTalk. This is because all top-level code is treated as the initialization code of that file's module object. Hence, it is legal to use ''self'' in top-level functions.
  
-=== Block closures ===+==== Block closures ====
  
 Block closures, as created by means of the syntax ''{ |args| body }'' always evaluate to closures and hence always capture the value of ''self''. Block closures, as created by means of the syntax ''{ |args| body }'' always evaluate to closures and hence always capture the value of ''self''.
  
-==== External Methods ====+===== External Methods and Fields =====
  
-It is possible to define methods externally on an object. For example:+It is possible to define methods and fields externally on an object. For example:
  
 <code> <code>
Line 180: Line 182:
  
 The rationale behind this decision is that ''self'' and ''super'' are inherently related to the object hierarchy of which a method is a part. Hence, even if a method is defined externally on an object, ''super'' should properly refer to the parent object of which the method is a part, rather than the lexically visible value of ''super''. The rationale behind this decision is that ''self'' and ''super'' are inherently related to the object hierarchy of which a method is a part. Hence, even if a method is defined externally on an object, ''super'' should properly refer to the parent object of which the method is a part, rather than the lexically visible value of ''super''.
 +</note>
 +
 +<note warning>
 +External methods, while powerful, introduce many subtle issues in the language. Therefore, this feature may disappear from later releases of AmbientTalk. It is therefore wise to stay clear from using this feature. For an overview of the problem introduced by external field or method declarations, see Gilad Bracha's blog post on [[http://gbracha.blogspot.com/2008/03/monkey-patching.html|monkey patching]].
 </note> </note>
  
at/tutorial/multiparadigm.1185524609.txt.gz · Last modified: 2007/08/22 11:40 (external edit)