http://wiki.erights.org/mediawiki/index.php?title=Special:Contributions&feed=atom&target=ThomasLeonardErights - User contributions [en]2024-03-19T01:45:55ZFrom ErightsMediaWiki 1.15.5-7http://wiki.erights.org/wiki/SAMSAM2011-11-18T12:02:12Z<p>ThomasLeonard: /* Example */</p>
<hr />
<div>The [http://serscis.eu/sam/ SERSCIS Access Modeller] (SAM) takes a model of a system (e.g. a set of objects within a computer program or a set of machines on a network) and attempts to verify certain security properties about the system, by exploring all the ways access can propagate through the system. For example, it could prove that a web-server's logs can never be deleted except by the logging system or the administrator.<br />
<br />
It is designed to handle dynamic systems (e.g. systems containing factories which may create new objects at runtime) and systems where behaviour of some of the objects is unknown or not trusted.<br />
<br />
It is greatly inspired by [[Scollar]], but extends it by:<br />
<br />
* Using a Java-like syntax for expressing behaviour, which is hopefully more natural for programmers.<br />
* Considering multiple contexts (e.g. so that objects created by a factory for client A can be kept separate from objects created by the same factory for client B).<br />
<br />
SAM is Open Source.<br />
<br />
== Example ==<br />
<br />
This factory.sam file defines known/trusted behaviour for a Factory and then sets up a scenario where the factory has two clients (objects with references to the factory). The clients and the Task objects created by the factory all have unknown behaviour, but are assumed to be running on a capability platform (and therefore confined):<br />
<br />
/* Behaviour */<br />
<br />
class Factory {<br />
public Task newInstance() {<br />
Task task = new Task();<br />
return task;<br />
}<br />
}<br />
<br />
config {<br />
Factory factory;<br />
<br />
setup {<br />
factory = new Factory();<br />
}<br />
<br />
test "A" {<br />
Object clientA = new Unknown(factory);<br />
}<br />
<br />
test "Other" {<br />
Object otherClients = new Unknown(factory);<br />
}<br />
}<br />
<br />
Processing this file with sam ('''sam factory.sam''') produces this graph showing the limits of how these objects may become connected:<br />
<br />
[[Image:sam-factory.png]]<br />
<br />
This shows that the tasks created by clientA (aggregated as aTask) may get access to and invoke the factory. However, clientA cannot get access to any of the other clients or their tasks.<br />
<br />
[[Category:Formal Reasoning]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Surprise_listSurprise list2011-10-27T11:28:46Z<p>ThomasLeonard: /* Single-letter uriGetters are a special case */</p>
<hr />
<div>Potentially surprising parts of the [[E language]].<br />
<br />
Current as of [http://www.erights.org/download/0-8-29/ E 0.8.33o].<br />
<br />
==For-loop pattern failure is not an error==<br />
<br />
<!-- FIXME: link to erights.org for loop doc --><br />
<br />
If the key or value pattern of a <code>for</code> loop does not match, then the loop simply skips that element of the collection. This can be useful, but is unlike all other non-explicit pattern match operations (<code>def</code> and parameter lists).<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def things := [1, "two", 3]<br />
# value: [1, "two", 3]<br />
<br />
? for x :int in things { <br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# 3<br />
# <br />
<br />
<br />
===Alternative===<br />
<br />
Move the pattern into a <code>def</code>:<br />
<br />
# E sample<br />
<br />
? for thing in things {<br />
> def x :int := thing<br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# <br />
<br />
# problem: &lt;ClassCastException: String doesn't coerce to an int&gt;<br />
<br />
The current developer version also allows strict checking to be turned on with a pragma (experimental):<br />
<br />
# E sample<br />
? pragma.enable("for-must-match")<br />
<br />
? for x :int in things {<br />
> println(x)<br />
> }<br />
# stdout: 1<br />
#<br />
<br />
# problem: <ClassCastException: String doesn't coerce to an int><br />
<br />
==<code>def x</code> doesn't return <var>x</var>==<br />
<br />
The forward declaration expression, <code>def <var>var</var></code>, does not return <var>var</var> but rather the [[Resolver]] for it.<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def x<br />
# value: &lt;Resolver&gt;<br />
<br />
? x<br />
# value: &lt;Promise&gt;<br />
<br />
===Rationale===<br />
<br />
If you want to pass a resolver as an argument, using it as an “out parameter”, this syntax is helpful:<br />
<br />
x.hereIsAResolver(def y)<br />
<var>... use y</var><br />
<br />
===Alternative===<br />
<br />
If you want the actual promise, simply write <code>(def x; x)</code>.<br />
<br />
==Unresolved references do not necessarily behave as their future resolved identity==<br />
<br />
&mdash; messages sent before the reference is resolved may be reacted to however the current holder of the reference &ldquo;arrow-head&rdquo; chooses, which does not necessarily correspond to the reference to which the unresolved reference resolves.<br />
<br />
This has been discussed in [http://www.eros-os.org/pipermail/e-lang/2005-July/010821.html an e-lang thread].<br />
<br />
===Rationale===<br />
<br />
This cannot be fixed without removing [http://www.erights.org/elib/distrib/pipeline.html pipelining], eliminating one of the major benefits of the E reference model.<br />
<br />
===Examples===<br />
<br />
For now, see [http://www.eros-os.org/pipermail/e-lang/2005-July/010827.html this lengthy example by MarkM].<br />
<br />
===Alternative===<br />
<br />
To avoid being vulnerable to this type of misbehavior, do not use a sameness test (<code>==</code>) or Map key lookup in order to decide on the reliability of the response to a ''previously'' sent message. This might involve using a when-catch/whenResolved construct to wait until the reference is resolved.<br />
<br />
==Accumulator operator is lowest-precedence==<br />
<br />
As you can see in the following expansion, the operator following the “_” is always lowest-precedence (as it is the one effectively rewritten into an assignment form):<br />
<br />
? e`pragma.enable("accumulator"); accum 0 while (a) { _ * b + c }`<br />
# value: e`null<br />
...<br />
# accum__1 := accum__1.multiply(b.add(c))<br />
...<br />
<br />
===Rationale===<br />
<br />
None known; this is probably an accident of the definition of the expansion of accumulator syntax.<br />
<br />
===Alternative===<br />
<br />
Avoid accumulator syntax when the accumulation cannot be expressed as a single call.<br />
<br />
<br />
<br />
== Shadowing function arguments ==<br />
<br />
Rebinding a name within a block is an error, e.g.<br />
<br />
def foo() {<br />
def x := 2<br />
def x := 3<br />
}<br />
<br />
("Failed: x already in scope")<br />
<br />
However, rebinding an argument does not issue any warning:<br />
<br />
def foo(x) {<br />
...<br />
def x := 2<br />
...<br />
println(x)<br />
}<br />
<br />
=== Rationale ===<br />
<br />
The already-in-scope error is intended to catch accidentally using the same name twice, not prohibit rebinding. Generally, you can expect it to be supressed anywhere there is visible <code>{...}</code> syntax.<br />
<br />
== Single-letter uriGetters are a special case ==<br />
<br />
It is not possible to refer to a single-letter uriGetter in a URI literal.<br />
<br />
? def <t> := ["foo" => "bar"]<br />
# value: ["foo" => "bar"]<br />
<br />
? interp.setExpand(true)<br />
? <t:foo><br />
# expansion: file__uriGetter.get("t:foo")<br />
<br />
# value: <file:/Users/kpreid/t:foo><br />
<br />
===Rationale===<br />
<br />
This is a feature intended for convenient support for Windows drive letter filenames. {{XXX|Look at whether MarkM agreed to remove it.}}<br />
<br />
===Alternative===<br />
<br />
Use names longer than one letter.<br />
<br />
[[Category:E language]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Surprise_listSurprise list2011-10-27T11:25:47Z<p>ThomasLeonard: for-must-match</p>
<hr />
<div>Potentially surprising parts of the [[E language]].<br />
<br />
Current as of [http://www.erights.org/download/0-8-29/ E 0.8.33o].<br />
<br />
==For-loop pattern failure is not an error==<br />
<br />
<!-- FIXME: link to erights.org for loop doc --><br />
<br />
If the key or value pattern of a <code>for</code> loop does not match, then the loop simply skips that element of the collection. This can be useful, but is unlike all other non-explicit pattern match operations (<code>def</code> and parameter lists).<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def things := [1, "two", 3]<br />
# value: [1, "two", 3]<br />
<br />
? for x :int in things { <br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# 3<br />
# <br />
<br />
<br />
===Alternative===<br />
<br />
Move the pattern into a <code>def</code>:<br />
<br />
# E sample<br />
<br />
? for thing in things {<br />
> def x :int := thing<br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# <br />
<br />
# problem: &lt;ClassCastException: String doesn't coerce to an int&gt;<br />
<br />
The current developer version also allows strict checking to be turned on with a pragma (experimental):<br />
<br />
# E sample<br />
? pragma.enable("for-must-match")<br />
<br />
? for x :int in things {<br />
> println(x)<br />
> }<br />
# stdout: 1<br />
#<br />
<br />
# problem: <ClassCastException: String doesn't coerce to an int><br />
<br />
==<code>def x</code> doesn't return <var>x</var>==<br />
<br />
The forward declaration expression, <code>def <var>var</var></code>, does not return <var>var</var> but rather the [[Resolver]] for it.<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def x<br />
# value: &lt;Resolver&gt;<br />
<br />
? x<br />
# value: &lt;Promise&gt;<br />
<br />
===Rationale===<br />
<br />
If you want to pass a resolver as an argument, using it as an “out parameter”, this syntax is helpful:<br />
<br />
x.hereIsAResolver(def y)<br />
<var>... use y</var><br />
<br />
===Alternative===<br />
<br />
If you want the actual promise, simply write <code>(def x; x)</code>.<br />
<br />
==Unresolved references do not necessarily behave as their future resolved identity==<br />
<br />
&mdash; messages sent before the reference is resolved may be reacted to however the current holder of the reference &ldquo;arrow-head&rdquo; chooses, which does not necessarily correspond to the reference to which the unresolved reference resolves.<br />
<br />
This has been discussed in [http://www.eros-os.org/pipermail/e-lang/2005-July/010821.html an e-lang thread].<br />
<br />
===Rationale===<br />
<br />
This cannot be fixed without removing [http://www.erights.org/elib/distrib/pipeline.html pipelining], eliminating one of the major benefits of the E reference model.<br />
<br />
===Examples===<br />
<br />
For now, see [http://www.eros-os.org/pipermail/e-lang/2005-July/010827.html this lengthy example by MarkM].<br />
<br />
===Alternative===<br />
<br />
To avoid being vulnerable to this type of misbehavior, do not use a sameness test (<code>==</code>) or Map key lookup in order to decide on the reliability of the response to a ''previously'' sent message. This might involve using a when-catch/whenResolved construct to wait until the reference is resolved.<br />
<br />
==Accumulator operator is lowest-precedence==<br />
<br />
As you can see in the following expansion, the operator following the “_” is always lowest-precedence (as it is the one effectively rewritten into an assignment form):<br />
<br />
? e`pragma.enable("accumulator"); accum 0 while (a) { _ * b + c }`<br />
# value: e`null<br />
...<br />
# accum__1 := accum__1.multiply(b.add(c))<br />
...<br />
<br />
===Rationale===<br />
<br />
None known; this is probably an accident of the definition of the expansion of accumulator syntax.<br />
<br />
===Alternative===<br />
<br />
Avoid accumulator syntax when the accumulation cannot be expressed as a single call.<br />
<br />
<br />
<br />
== Shadowing function arguments ==<br />
<br />
Rebinding a name within a block is an error, e.g.<br />
<br />
def foo() {<br />
def x := 2<br />
def x := 3<br />
}<br />
<br />
("Failed: x already in scope")<br />
<br />
However, rebinding an argument does not issue any warning:<br />
<br />
def foo(x) {<br />
...<br />
def x := 2<br />
...<br />
println(x)<br />
}<br />
<br />
=== Rationale ===<br />
<br />
The already-in-scope error is intended to catch accidentally using the same name twice, not prohibit rebinding. Generally, you can expect it to be supressed anywhere there is visible <code>{...}</code> syntax.<br />
<br />
== Single-letter uriGetters are a special case ==<br />
<br />
It is not possible to refer to a single-letter uriGetter in a URI literal.<br />
<br />
? def <t> := ["foo" => "bar"]<br />
# value: ["foo" => "bar"]<br />
<br />
? interp.setExpand(true)<br />
? <t:foo><br />
# expansion: file__uriGetter.get("t:foo")<br />
<br />
# value: <file:/Users/kpreid/t:foo><br />
<br />
===Rationale===<br />
<br />
This is a feature intended for convenient support for Windows drive letter filenames. {{XXX|Look at whether MarkM agreed to remove it.}}<br />
<br />
===Alternative===<br />
<br />
Use names longer than one letter.<br />
<br />
[[Category:E language]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Interfacing_to_JavaWalnut/Ordinary Programming/Interfacing to Java2011-09-12T12:12:46Z<p>ThomasLeonard: /* Arrays and Java types */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Interfacing to Java===<br />
<br />
====Importing classes from the Java API====<br />
<br />
We can import a class from the underlying Java virtual machine with the import statement, and speak to the Java object much as we would speak to an E object: <span class="note" style="color:red">replace vector as example</span><br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#create a single vector with a direct call to Java<br />
def myVector := <unsafe:java.util.makeVector>()<br />
myVector.addElement("abc")<br />
<br />
#create a makeVector function which can be called repeatedly to make more vectors<br />
def makeVector := <unsafe:java.util.makeVector><br />
def vector2 := makeVector()<br />
<br />
# create a shorthand for the java.util package, that gives quick access to all the <br />
# classes in java.util<br />
def <util> := <unsafe:java.util.*><br />
def vector3 := <util:makeVector>()</nowiki><br />
</pre><br />
<br />
In the example, we showed 3 ways of getting a Java object, which are roughly comparable to the different styles of using "import" in Java. If you just want one vector, you can get it by directly calling the vector constructor. If you plan to make many vectors, you can import the class into a variable. And if you plan to use many classes in a particular package, you can create your own representative for the package that you can use instead of "&lt;unsafe&gt;".<br />
<br />
Note that the angle-brackets here are simply syntactic sugar: '''&lt;util&gt;''' is short for '''util__uriGetter''' and '''&lt;util:makeVector&gt;''' is short for '''util__uriGetter.get("makeVector")'''.<br />
<br />
Note also that E prefixes every Java class name with "make". The idea here is to make existing Java classes match the naming conventions of E constructors.<br />
<br />
We have now seen 3 uriGetters, file:, unsafe:, and the programmer-defined util:. Four other uriGetters are also predefined, swing: (for accessing javax.swing) and awt: (for accessing java.awt), resource: (for read-only access to resource files such as images, sounds, and static texts), and import:, described next.<br />
<br />
The import: uriGetter is similar to unsafe:, except it only imports those parts of the Java API that have been audited for capability security and found to convey no authority (see the Appendix for a definition of "authority").<br />
<br />
<font color="#FF0000">Put in link, think of better example. Remove vector from the book. Since the Vector class conveys no authority, you should be able to get a vector with import, but currently you can't.</font><br />
<br />
<pre><br />
def vector4 := <unsafe:java.util.makeVector>()<br />
</pre><br />
<br />
As discussed later with Library Packages and Secure Mobile Code, emakers cannot use unsafe: unless the unsafe__uriGetter is explicitly handed to them. So import: is often useful in these security-aware situations. A complete list of safe versus unsafe classes, and the small percentage of Java API methods which are suppressed for security reasons, are listed in the Appendix.<span class="note">link</span><br />
<br />
&lt;resource&gt; is considered safe, and can therefore be used directly in emakers.<br />
<br />
As noted earlier, <span class="e">''E''</span> does not have an expression to directly represent public static final variables. To use such static finals from a Java class, put parentheses at the end of the variable name, making it syntactically look like a function call, prefix it with "get", uppercase the first letter, and <span class="e">''E''</span> will get the value for you:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
<unsafe:java.util.makeCalendar>.getYEAR()</nowiki><br />
<br />
</pre><br />
<br />
====Speaking to Java objects with superclass/subclass overloaded methods====<br />
<br />
Speaking to Java objects is usually as easy as shown above, where we simply sent myVector an addElement(object) message as if it were an <span class="e">E</span> object. A problem arises with some Java objects if they have overloaded methods for which the only distinguishing mark is the static typing of the parameters in which one of the methods specifies a type that is a superclass of the type in the other method — a rare but not unheard-of situation. {{XXX|coercion causes same problem}} In that case, we need to revert to a more descriptive messaging convention.<br />
<br />
Overloaded methods in Java are presented to E with verbs qualified by the types of the arguments. In this example, we see that the print function for the System.out object is overloaded for both String and Object, with String being a subclass of Object, so the full signature is required:<br />
<br />
<pre><br />
<nowiki>? def out := <unsafe:java.lang.makeSystem>.getOut()<br />
# value: <a PrintStream><br />
<br />
? out.print("abc")<br />
# example problem: <IllegalArgumentException: ...><br />
<br />
? out."print(String)"("abc")</nowiki><br />
</pre><br />
<br />
In general, quotes can be used to name a verb which is not a valid identifier in E syntax. Here, the verb is exactly “<code>print(String)</code>”.<br />
<br />
(Where should the following explanation go?)<br />
To use an example from awt: or swing:, we need our vat to be running with the AWT event loop. Normally this happens by running in a vat spawned to run a "*.e-awt" file. <tt>currentVat.morphInto("awt")</tt> asks the current vat to start executing instead in the awt event loop. It returns a promise which resolves to null or broken once this operation succeeds or fails. <tt>? interp.waitAtTop(p)</tt> pauses our interpreter (E's read-eval-print loop) until p is resolved.<br />
<br />
<pre><br />
? interp.waitAtTop(currentVat.morphInto("awt"))<br />
</pre><br />
<br />
Now that that's done, we can proceed to the next example.<br />
<br />
<pre><br />
<nowiki>? def myLabel := <swing:makeJLabel>."run(String)"("label text")</nowiki><br />
</pre><br />
<br />
If you encounter one of these special cases that requires multiple parameters, the signatures must be laid out with exact spelling and exact spacing, notably with exactly one space between the comma and the next signature:<br />
<br />
<pre><br />
javaObject."method(String, int)"("abc", 23)<br />
</pre><br />
<br />
Accessing functions in the java.lang.Math class are a particularly interesting case. Some of these functions are overloaded on float, double and perhaps int and long. While E does not support float and has a different view of integers, it still sees these functions as overloaded. Accessing the correct function is simple, if verbose:<br />
<br />
<pre><br />
def Math := <unsafe:java.lang.makeMath><br />
def abs(value) {<br />
return Math."abs(double)"(value)<br />
}<br />
</pre><br />
<br />
====Arrays and Java types====<br />
<br />
If you call a Java method which requires an array and you pass in an E list, E will automatically convert it. For example, to create a Java BigInteger from an EList of ints, you can just do:<br />
<br />
? def makeBigInteger := <import:java.math.makeBigInteger><br />
# value: <makeBigInteger><br />
? def x := makeBigInteger([1, 2])<br />
# value: 258<br />
<br />
E automatically converts from its own EList type to the required int[] type in this case.<br />
<br />
However, if the Java method took an Object argument then E would pass it an EList directly. You can use E's conversion features from your own Java code using E.as():<br />
<br />
import org.erights.e.elib.prim.E;<br />
<br />
public class Test {<br />
public Test(Object obj) {<br />
System.out.println("obj = " + obj + ", of type " + obj.getClass());<br />
<br />
String[] list = (String[]) E.as(obj, String[].class);<br />
<br />
System.out.println("list = " + list + ", of type " + list.getClass());<br />
}<br />
}<br />
<br />
When called from E:<br />
<br />
? <unsafe:makeTest>(["foo", "bar"])<br />
obj = ["foo", "bar"], of type class org.erights.e.elib.tables.ConstListImpl<br />
list = [Ljava.lang.String;@39cd2b99, of type class [Ljava.lang.String;<br />
# value: <a Test><br />
<br />
====Promises====<br />
<br />
Internally, an E promise is an object which, when resolved, holds a pointer to its resolution. From E code, a resolved promise is identical to the resolution, but from Java they are separate objects.<br />
<br />
For example (using the Test class above):<br />
<br />
? def listVow <br />
# value: <Resolver><br />
<br />
? bind listVow := ["foo", "bar"]<br />
# value: ["foo", "bar"]<br />
<br />
? <unsafe:makeTest>(listVow)<br />
obj = ["foo", "bar"], of type class org.erights.e.elib.ref.SwitchableRef<br />
list = [Ljava.lang.String;@5fc9d050, of type class [Ljava.lang.String;<br />
# value: <a Test><br />
<br />
Notice that we now get a '''SwitchableRef''' rather than a '''ConstListImpl'''. Using E.as to coerce it to String[] still works, but you can also do it directly using '''Ref.resolution(vow)''' (which would get you the '''ConstListImpl''').<br />
<br />
====Java Adapters and Interfaces====<br />
<br />
As described earlier, you can use the match[verb,args] construct to aid in writing adapters and other objects that must meet a Java interface specification. <span class="e">''E''</span> will automatically manipulate the resulting <span class="e">''E''</span> objects and the java virtual machine so that Java understands that the <span class="e">''E''</span> object meets the interface specification. It is not possible to make subclasses of Java classes in <span class="e">''E''</span>. However, because the developers of the Java API have wisely moved aggressively to make sure that interfaces, rather than subclasses, are core to Java object interoperability, there is virtually no Java interfacing goal that cannot be achieved with this machinery.<br />
<br />
====The Java API versus capability security====<br />
<br />
A final note: almost all of the objects and methods in the Java API are available in <span class="e">''E''</span> for version 1.0 through the unsafe_uriGetter; unfortunately very few have been audited sufficiently to be included with the import__uriGetter. In the future, more of the API will be accessible through the import__uriGetter; however, some parts of the Java API will be altered and/or suppressed even in unsafe__uriGetter to achieve a more secure yet easier to use computing framework. This is discussed further in the chapter on Mobile Code. You can see the list of suppressed methods and unsafe classes [http://www.erights.org/javadoc/index.html in the Javadoc].</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Interfacing_to_JavaWalnut/Ordinary Programming/Interfacing to Java2011-09-12T12:06:06Z<p>ThomasLeonard: /* Arrays and primitive types */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Interfacing to Java===<br />
<br />
====Importing classes from the Java API====<br />
<br />
We can import a class from the underlying Java virtual machine with the import statement, and speak to the Java object much as we would speak to an E object: <span class="note" style="color:red">replace vector as example</span><br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#create a single vector with a direct call to Java<br />
def myVector := <unsafe:java.util.makeVector>()<br />
myVector.addElement("abc")<br />
<br />
#create a makeVector function which can be called repeatedly to make more vectors<br />
def makeVector := <unsafe:java.util.makeVector><br />
def vector2 := makeVector()<br />
<br />
# create a shorthand for the java.util package, that gives quick access to all the <br />
# classes in java.util<br />
def <util> := <unsafe:java.util.*><br />
def vector3 := <util:makeVector>()</nowiki><br />
</pre><br />
<br />
In the example, we showed 3 ways of getting a Java object, which are roughly comparable to the different styles of using "import" in Java. If you just want one vector, you can get it by directly calling the vector constructor. If you plan to make many vectors, you can import the class into a variable. And if you plan to use many classes in a particular package, you can create your own representative for the package that you can use instead of "&lt;unsafe&gt;".<br />
<br />
Note that the angle-brackets here are simply syntactic sugar: '''&lt;util&gt;''' is short for '''util__uriGetter''' and '''&lt;util:makeVector&gt;''' is short for '''util__uriGetter.get("makeVector")'''.<br />
<br />
Note also that E prefixes every Java class name with "make". The idea here is to make existing Java classes match the naming conventions of E constructors.<br />
<br />
We have now seen 3 uriGetters, file:, unsafe:, and the programmer-defined util:. Four other uriGetters are also predefined, swing: (for accessing javax.swing) and awt: (for accessing java.awt), resource: (for read-only access to resource files such as images, sounds, and static texts), and import:, described next.<br />
<br />
The import: uriGetter is similar to unsafe:, except it only imports those parts of the Java API that have been audited for capability security and found to convey no authority (see the Appendix for a definition of "authority").<br />
<br />
<font color="#FF0000">Put in link, think of better example. Remove vector from the book. Since the Vector class conveys no authority, you should be able to get a vector with import, but currently you can't.</font><br />
<br />
<pre><br />
def vector4 := <unsafe:java.util.makeVector>()<br />
</pre><br />
<br />
As discussed later with Library Packages and Secure Mobile Code, emakers cannot use unsafe: unless the unsafe__uriGetter is explicitly handed to them. So import: is often useful in these security-aware situations. A complete list of safe versus unsafe classes, and the small percentage of Java API methods which are suppressed for security reasons, are listed in the Appendix.<span class="note">link</span><br />
<br />
&lt;resource&gt; is considered safe, and can therefore be used directly in emakers.<br />
<br />
As noted earlier, <span class="e">''E''</span> does not have an expression to directly represent public static final variables. To use such static finals from a Java class, put parentheses at the end of the variable name, making it syntactically look like a function call, prefix it with "get", uppercase the first letter, and <span class="e">''E''</span> will get the value for you:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
<unsafe:java.util.makeCalendar>.getYEAR()</nowiki><br />
<br />
</pre><br />
<br />
====Speaking to Java objects with superclass/subclass overloaded methods====<br />
<br />
Speaking to Java objects is usually as easy as shown above, where we simply sent myVector an addElement(object) message as if it were an <span class="e">E</span> object. A problem arises with some Java objects if they have overloaded methods for which the only distinguishing mark is the static typing of the parameters in which one of the methods specifies a type that is a superclass of the type in the other method — a rare but not unheard-of situation. {{XXX|coercion causes same problem}} In that case, we need to revert to a more descriptive messaging convention.<br />
<br />
Overloaded methods in Java are presented to E with verbs qualified by the types of the arguments. In this example, we see that the print function for the System.out object is overloaded for both String and Object, with String being a subclass of Object, so the full signature is required:<br />
<br />
<pre><br />
<nowiki>? def out := <unsafe:java.lang.makeSystem>.getOut()<br />
# value: <a PrintStream><br />
<br />
? out.print("abc")<br />
# example problem: <IllegalArgumentException: ...><br />
<br />
? out."print(String)"("abc")</nowiki><br />
</pre><br />
<br />
In general, quotes can be used to name a verb which is not a valid identifier in E syntax. Here, the verb is exactly “<code>print(String)</code>”.<br />
<br />
(Where should the following explanation go?)<br />
To use an example from awt: or swing:, we need our vat to be running with the AWT event loop. Normally this happens by running in a vat spawned to run a "*.e-awt" file. <tt>currentVat.morphInto("awt")</tt> asks the current vat to start executing instead in the awt event loop. It returns a promise which resolves to null or broken once this operation succeeds or fails. <tt>? interp.waitAtTop(p)</tt> pauses our interpreter (E's read-eval-print loop) until p is resolved.<br />
<br />
<pre><br />
? interp.waitAtTop(currentVat.morphInto("awt"))<br />
</pre><br />
<br />
Now that that's done, we can proceed to the next example.<br />
<br />
<pre><br />
<nowiki>? def myLabel := <swing:makeJLabel>."run(String)"("label text")</nowiki><br />
</pre><br />
<br />
If you encounter one of these special cases that requires multiple parameters, the signatures must be laid out with exact spelling and exact spacing, notably with exactly one space between the comma and the next signature:<br />
<br />
<pre><br />
javaObject."method(String, int)"("abc", 23)<br />
</pre><br />
<br />
Accessing functions in the java.lang.Math class are a particularly interesting case. Some of these functions are overloaded on float, double and perhaps int and long. While E does not support float and has a different view of integers, it still sees these functions as overloaded. Accessing the correct function is simple, if verbose:<br />
<br />
<pre><br />
def Math := <unsafe:java.lang.makeMath><br />
def abs(value) {<br />
return Math."abs(double)"(value)<br />
}<br />
</pre><br />
<br />
====Arrays and Java types====<br />
<br />
If you call a Java method which requires an array and you pass in an E list, E will automatically convert it. For example, to create a Java BigInteger from an EList of ints, you can just do:<br />
<br />
? def makeBigInteger := <import:java.math.makeBigInteger><br />
# value: <makeBigInteger><br />
? def x := makeBigInteger([1, 2])<br />
# value: 258<br />
<br />
E automatically converts from its own EList type to the required int[] type in this case.<br />
<br />
However, if the Java method took an Object argument then E would pass it an EList directly. You can use E's conversion features from your own Java code using E.as():<br />
<br />
import org.erights.e.elib.prim.E;<br />
<br />
public class Test {<br />
public Test(Object obj) {<br />
System.out.println("obj = " + obj + ", of type " + obj.getClass());<br />
<br />
String[] list = (String[]) E.as(obj, String[].class);<br />
<br />
System.out.println("list = " + list + ", of type " + list.getClass());<br />
}<br />
}<br />
<br />
When called from E:<br />
<br />
? <unsafe:makeTest>(["foo", "bar"])<br />
obj = ["foo", "bar"], of type class org.erights.e.elib.tables.ConstListImpl<br />
list = [Ljava.lang.String;@39cd2b99, of type class [Ljava.lang.String;<br />
# value: <a Test><br />
<br />
====Java Adapters and Interfaces====<br />
<br />
As described earlier, you can use the match[verb,args] construct to aid in writing adapters and other objects that must meet a Java interface specification. <span class="e">''E''</span> will automatically manipulate the resulting <span class="e">''E''</span> objects and the java virtual machine so that Java understands that the <span class="e">''E''</span> object meets the interface specification. It is not possible to make subclasses of Java classes in <span class="e">''E''</span>. However, because the developers of the Java API have wisely moved aggressively to make sure that interfaces, rather than subclasses, are core to Java object interoperability, there is virtually no Java interfacing goal that cannot be achieved with this machinery.<br />
<br />
====The Java API versus capability security====<br />
<br />
A final note: almost all of the objects and methods in the Java API are available in <span class="e">''E''</span> for version 1.0 through the unsafe_uriGetter; unfortunately very few have been audited sufficiently to be included with the import__uriGetter. In the future, more of the API will be accessible through the import__uriGetter; however, some parts of the Java API will be altered and/or suppressed even in unsafe__uriGetter to achieve a more secure yet easier to use computing framework. This is discussed further in the chapter on Mobile Code. You can see the list of suppressed methods and unsafe classes [http://www.erights.org/javadoc/index.html in the Javadoc].</div>ThomasLeonardhttp://wiki.erights.org/wiki/EnvEnv2011-08-30T11:22:16Z<p>ThomasLeonard: Clarify Scope/EEnv split</p>
<hr />
<div>Env: what [[Scope]] objects ought to be renamed to.<br />
<br />
The error is long-standing in E's design, but [[User:Markm]] did not not want to use the technically correct “environment” since it was rather lengthy to write in code. [[User:Kevin Reid]] advocates using “Env”, this being both correct and short.<br />
<br />
{{XXX|Expand this with actually explaining the protocol of Env objects. Also see Thomas Leonard's proposal that Scope objects in [[E-on-Java]] remain what they are for implementation efficiency while Envs have the nice user-facing and [[GBA]]-providing protocol.}}<br />
<br />
Here are the patches for splitting Scope into two objects:<br />
<br />
* http://www.eros-os.org/pipermail/e-lang/2010-September/013620.html<br />
<br />
The motivation for this is that we are currently using one type (Scope) for two purposes:<br />
<br />
* as the means to specify the context in which to evaluate an expression (essentially an immutable map of names to Slots), and<br />
* as a mutable internal data structure of the interpreter (holding the current values of local variables, etc).<br />
<br />
The way we currently make the mutable Scope object appear immutable to E code is through taming. This is risky (a flaw in the taming rules once allowed code to replace items in safeScope, for example). It's also confusing, because you can e.g. pass values for locals where it doesn't make sense (e.g. to eExpr.eval) and many Scope methods only make sense in one of the two contexts.<br />
<br />
{{stub}}</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Distributed_ComputingWalnut/Distributed Computing2011-08-03T14:34:41Z<p>ThomasLeonard: waitAtTop</p>
<hr />
<div>[[Category:Walnut|3]]<br />
<br />
==Distributed Computing==<br />
<br />
Multiple threads form the basis of conventional models of concurrent programming. Remarkably, human beings engage in concurrent distributed computing every day even though people are generally single threaded (there are exceptions: Walter Cronkite routinely listened to one broadcast with one ear, a different broadcast with the other, while simultaneously taking notes on another topic and speaking authoritatively to an audience of millions. But most people, including this author, live single-threaded lives).<br />
<br />
How do we simple creatures pull off the feat of distributed computing without multiple threads? Why do we not see groups of people, deadlocked in frozen tableau around the coffepot, one person holding the sugar waiting for milk, the other holding milk waiting for sugar?<br />
<br />
The answer is, we use a sophisticated computational mechanism known as a ''nonblocking promise''.<br />
<br />
Let us look at a conventional human distributed computation. Alice, the CEO of Evernet Computing, needs a new version of the budget including R&D numbers from the VP of Engineering, Bob. Alice calls Bob: "Could you get me those numbers?"<br />
<br />
Bob jots Alice's request on his to-do list. "Sure thing, Alice, I promise I'll get them for you after I solve this engineering problem."<br />
<br />
Bob has handed Alice a promise for the answer. He has ''not '' handed her the answer. But neither Bob nor Alice sits on their hands, blocked, waiting for the resolution.<br />
<br />
Rather, Bob continues to work his current problem. And Alice goes to Carol, the CFO: "Carol, when Bob gets those numbers, plug 'em into the spreadsheet and give me the new budget,okay?"<br />
<br />
Carol: "No problem." Carol writes Alice's request on her own to-do list, but does not put it either first or last in the list. Rather, she puts it in the conditional part of the list, to be done when the condition is met--in this case, when Bob fulfills his promise.<br />
<br />
Conceptually, Alice has handed to Carol a copy of Bob's promise for numbers, and Carol has handed to Alice a promise for a new integrated spreadsheet. Once again, no one waits around, blocked. Carol ambles down the hall for a contract negotiation, Alice goes back to preparing for the IPO.<br />
<br />
When Bob finishes his calculations, he signals that his promise has been fulfilled; when Carol receives the signal, she uses Bob's fulfilled promise to fulfill her own promise; when Carol fulfills her promise, Alice gets her spreadsheet. A sophisticated distributed computation has been completed so simply that no one realizes an advanced degree in computer science should have been required.<br />
<br />
In this simple example, we see why human beings never get trapped in the thread-based deadlock situations described endlessly in books on concurrent programming. People don't deadlock because they live in a concurrent world managed with a promise-based architecture. And so it is with <span class="e">''E''</span>.<br />
<br />
This chapter on distributed computing is the longest and most challenging part of the book. The Promise Architecture of <span class="e">''E''</span> is very different from the threads, synchronized methods, guarded objects, and RMI of Java. One might expect the Security chapter and its Capability paradigm to be equally new and challenging. But in fact, the implementation of security is embedded so deeply in E's infrastructure that much of the effort merely involves realizing the power inherent in constructs we have already learned. Security with <span class="e">''E''</span> is more a matter of architecture than of coding.<br />
<br />
Distributed computation, however, still requires gritty effort. We start simply, with the eventually operator.<br />
<br />
{{:Walnut/Distributed Computing/Eventually Operator}}<br />
{{:Walnut/Distributed Computing/Promises}}<br />
{{:Walnut/Distributed Computing/Multiway when-catch}}<br />
{{:Walnut/Distributed Computing/Partial Ordering Of Sent Messages}}<br />
{{:Walnut/Distributed Computing/Naming conventions}}<br />
{{:Walnut/Distributed Computing/Testing for Equality in a Distributed System}}<br />
<br />
===Letting When-Catch make a Promise For You===<br />
<br />
As noted in chapter 1 under the Secret Lives of Flow Control Structures, control structures return values. When used as described up to this point, the return value of the when--catch expression has been ignored. In fact, the when-catch expression returns a promise for the last value that the executed clause (the body or catch block) will return.<br />
<br />
Rewriting the calcMilesBeforeEmptyVow using this feature, we get:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def calcMilesBeforeEmptyVow(carRcvr) { <br />
def fuelRemainingVow := carRcvr <- getFuelRemaining() <br />
def mpgVow := carRcvr <- getEfficiency() <br />
return when (fuelRemainingVow, mpgVow) -> { <br />
mpgVow * fuelRemainingVow <br />
}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here the when-catch creates the promise which is returned by the function, and resolution is automatic at the end of the when-catch execution. <br />
So when the promise that the when-catch depends on is resolved the promise it returned will be resolved to the result of the last seqExp in the when clause (i.e. the "mpgVow * fuelRemainingVow" expression).<br />
<br />
Note that we don't need a catch block here. The default behaviour if the promise that the when-catch depends on is smashed is to smash the promise of the when--catch block, which will trigger the catch block in the main program. Normally, you should either report an error or propagate it, so that every error gets reported exactly once.<br />
<br />
Whatever happens, the finally clause has no effect on the resolution of the promise returned by when-catch.<br />
<br />
Warning: A common mistake is to put the "return" statement inside the when block. This will lead to the confusing error message "Ejector must be enabled" (return is a type of "ejector", which causes a function to return a value, but by the time the when block executes, the original function call has already returned).<br />
<br />
===Broken Promise Contagion===<br />
<br />
When chaining promises, what happens if one of the promises in the middle or the far end breaks? The problem that breaks the far promise is propagated down all the promises dependent on it. As a consequence, broken promises work their way through the system in a similar way to exceptions being caught in try/catch blocks.<br />
<br />
===State Transitions for References===<br />
<br />
Having worked our way through near, far, broken, and promised references, let us put all the transitions among these together in a single place. The following diagram shows all the kinds of references <span class="e">''E''</span> distinguishes between, and it shows the two possible transitions:<br />
<br />
<font color="rgb(255, 0, 0)"> [[Image:ref-mech-0.gif|state transition diagram]]</font><br />
<br />
The 2 transitions are:<br />
<br />
* A promise may transition (resolve) into a resolved reference, which can be near or far or broken..<br />
* A far ref may transition to a broken ref.<br />
<br />
That is the complete collection of transitions.<br />
<br />
===Guards for distributed systems===<br />
<br />
Very early in the book, we presented a list of <span class="e">''E''</span> types, including any, integer, float64, etc. In that list were "rcvr", "vow", "pbc" and "near". "pbc" means that the type of the value is required to be "pass by construction". Transparent immutables are generally pbc, and can be passed through this type declaration. Strings, integers, floats, booleans, ConstMaps and ConstLists are all pbc. Objects that are pbc are copied when they are sent, so that even if the object originated on a remote computer, when you get it you can use immediate calls on it. Also, since pbc objects do not embody any code, pbc objects passed across a trust boundary can be used with far fewer security concerns: the pbc object may contain bad data, but it cannot play any tricky games in its execution.<br />
<br />
"Near" means that the value must be local. Promises and far references will not pass the near guard. Anything that passes a near guard can be sent messages with immediate calls.<br />
<br />
At this time, "rcvr" and "vow" have the same algorithmic meaning as "any", but can be used as hints to the programmer about how to interact with the object (a vow should be referenced only eventually until it is resolved; a rcvr should always be referenced only eventually).<br />
<br />
===Nested When-Catch constructs===<br />
<br />
As discussed earlier, we can guarantee the ordering of messages sent from one object to another object. But when a program sends messages to several objects, on different machines, the order in which answers will be received cannot be predicted. Suppose you need to perform a computation involving two far answers, and the algorithm depends on the result from the first answer. You can nest when-catch clauses to await the outcome of the dependency:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def fileRcvr := fileCacheRcvr <- getFile()<br />
when (def exists := fileRcvr <- exists()) -> {<br />
if (exists) {<br />
when (def text := fileRcvr <- getText()) -> {<br />
println(`File has text: $text`)<br />
} catch p2 {println(`Problem with existing file: $p2`)}<br />
} else {println("File does not exist")}<br />
} catch prob {println(`Problem reaching file: $prob`)}<br />
</nowiki><br />
<br />
</pre><br />
<br />
Here, we want to print the text of a farFile, but we want to be sure the file exists first. So we ask the file if it exists, and only after we determine that it does indeed exist do we proceed to get the text.<br />
<br />
===Live Refs, Sturdy Refs, and URIs===<br />
<br />
Up to this point we have carefully dodged a critical question. How does a program acquire its very first reference to an object on a different computer? In all our examples up to this point, we have always started out with a reference to at least one remote object, and we retrieved other remote objects by asking that object for other objects: for example, we asked a remote carMakerRcvr for a new (remote) carRcvr, and were able to immediately work with the car just like any other remote object. How did we get the reference to the carMakerRcvr in the first place?<br />
<br />
In <span class="e">''E''</span>, the reference to an object can be encoded as a Universal Resource Identifier string, known as a ''uri'' (the familiar url of the Web is a type of uri). This uri string can be passed around in many fashions; one good secure way of passing a uri is to save it as a text file, encrypt and sign it with PGP, and send it in email. If you wish to run a seriously secure distributed <span class="e">''E''</span> system, encrypting the uris is crucial: indeed, the passing of the uris from machine to machine is the main security issue that <span class="e">''E''</span> cannot address for you (and is a problem shared by all security systems, a problem that will diminish with time as secure systems like PGP email are deployed). Other ways uris have been passed in operational <span class="e">''E''</span> systems have been to send the uri over an ssh connection, and (less securely) by reading the uri off over a telephone! If you are using <span class="e">''E''</span> on a local area network and have no security concerns, but are using <span class="e">''E''</span> simply because it is simpler, safer, and more maintainable for distributed computing, the uris can be stored in files on a shared file system and read directly by the programs on different computers as they start up.<br />
<br />
The functions makeURI(object) and objFromURI(uri) detailed in the <span class="e">''E''</span> Quick Reference Card perform the basic transformations you need to hook up objects on multiple computers. These routines use sturdy refs and liverefs in their computations. A sturdyRef is an object that contains an enduring description of where an object can be found; sturdyRefs and URIs are simple transformations of one another. LiveRefs are actual connections to objects that disappear any time a connection goes down. LiveRefs carry the actual traffic in <span class="e">''E''</span> communication. When you request a remote object from another remote object (as in farCarMaker <- ("mercedes")), what you actually get is a liveRef. If you want to continue to connect with that particular car across multiple sessions, you will need to explicitly get a sturdyRef from the car (and the car will have to have an explicit method for granting the sturdyRef. The sturdyref function is an important capability, not one handed out by default).<br />
<br />
Each program that expects to work with remote objects needs to invoke the command<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
introducer.onTheAir() </nowiki><br />
<br />
</pre><br />
<br />
before starting any remote connections, including the making or using of uris. An example of these functions working together can be found in eChat.<br />
<br />
===blockAtTop, continueAtTop, waitAtTop===<br />
<br />
E programs never block. They never just sit and wait around for results. However, most programs will toss out some windows, or set up some services, and then desire to wait for someone or some thing to use them. Often, the first version of a program written by a new <span class="e">''E''</span> programmer will set everything up, execute the last line of the program, and then shut down. It is quite disconcerting to watch your windows briefly light up and then disappear, along with the java virtual machine underlying the entire program.<br />
<br />
The command<br />
<br />
<pre><br />
<br />
interp.blockAtTop()<br />
<br />
</pre><br />
<br />
causes the <span class="e">''E''</span> interpreter to wait for requests to come in. The command<br />
<br />
<pre><br />
<br />
interp.continueAtTop()<br />
<br />
</pre><br />
<br />
causes the <span class="e">''E''</span> interpreter to stop waiting. These commands are used in the eChat sample at the end of this chapter: the last line of the program initiates blockAtTop, and continueAtTop is invoked when the user closes his chat window.<br />
<br />
An alternative is to use:<br />
<br />
<pre><br />
interp.waitAtTop(promise)<br />
</pre><br />
<br />
This is similar to blockAtTop, but continues automatically when the promise resolves.<br />
<br />
===A bit of Philosophy when using Promises for the first time===<br />
<br />
If a method accepts a promise or far reference as a parameter, the returned value almost certainly cannot be a local object. Why is this? If the computation of the returned object depends on something eventual, the computation will have to wait for an answer, which means the best the object can do for immediately returning something is to return a promise. So a method like getCar(licensePlateVow) has almost certainly violated the naming convention, one way or the other.<br />
<br />
As a consequence of this and other characteristics of promises, beginning E programmers often experience a moment of breathlessness soon after they first try to use them. This moment occurs when the programmer erroneously concludes that, once you let a promise into your system, the program has tumbled down a slippery slope from which there is no recovery. It feels as if you will never be able to have a real value in your hands again; you'll spend the rest of your life making eventual sends, coupled with endless when-catch constructs just to get to the next step.<br />
<br />
The breathlessness can metastasize into a feeling of having lost control of the software: everything is off computing somewhere else and all you have is a bunch of promises. Since <span class="e">''E''</span> never (really, never!) blocks, you can never tell things, "just stop for a moment while I catch my breath and gather up all the values" :-)<br />
<br />
In fact, there are several patterns and tools for getting control of things again. The basic multi-promise when-catch, and the promiseAllResolved and Summoner patterns at the end of this chapter are just a few examples of structures specifically designed to reduce the frequency with which you need when-catch. They allow you to get quickly back into local computation after a distributed action. You really can catch your breath.<br />
<br />
And once the moment of breathlessness passes, you will feel freedom, for you will never have to deal with thread synchronization again; you will never lie awake at night wondering if an unexplored race condition will cause deadlock a few days after the production load level hits your system. <font color="#ff0000">How early can I put this paragraph easily? AHK proposes right after Promises.</font><br />
<br />
===Additional Promise-Related Operations===<br />
<br />
* whenBroken<br />
* E isBroken<br />
* whenResolved Use this when your action will be the same once the promise resolves, regardless of whether it resolves broken or not.<br />
* E isResolved<br />
* E send(object,verb,arguments) This function is identical to the E call() function described earlier, but does an eventual send rather than an immediate call.<br />
* E sendOnly<br />
* E join(a,b) Guarantees sends to result of join are delivered only after messages to a and b have been delivered, sort of a test for equality on-the-fly<br />
<br />
===Under the Covers: Vats and Game Turns===<br />
<br />
<font color="#ff0000">Each vat has a separate event loop, each game turn corresponds to the processing of a single event to conclusion with no interruptions. There are frontend vats, which all share the swing event queue for queuing messages to their event loops, and there are backend queues, each of which has its own separate event queue and runs on a separate thread. Frontend vats have the advantage that they can interact directly with user interface widgets. The initial vat created by default at the start of an E program is a frontend vat. You might want multiple frontend vats if you want to shut down whole subsystems in one fell swoop: you can tell a vat to shut down, and it will terminate all its connections to the outside world, making it available for garbage collection. Have markm review this and tell me what is wrong with this description.</font><br />
<br />
<font color="#ff0000">creating a second frontend vat on a single jvm. creating a backend vat on a jvm</font><br />
<br />
===Example: Alice, Bob, and Carol as Code===<br />
<br />
We started this chapter with a description of a human interaction, with Alice as the CEO of Evernet Computing in search of a new spreadsheet for her IPO preparation. What would that distributed problem look like in code? Though we present only a skeleton of this human operation here, it is perhaps nonetheless informative. It might also be informative, after one has read how to do the example in <span class="e">''E''</span>, to think about how it would be done with threads, in Java or C++. That, however, is left as an exercise for the reader.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#---- Bob Code<br />
<br />
def bobRcvr {<br />
to handleExplosionInNetworkServerRoom() {<br />
# handle the explosion<br />
}<br />
to getCostNumbers() :pbc {<br />
return ["R&D" => 10000]<br />
}<br />
}<br />
<br />
#------------ Carol Code<br />
<br />
def carolRcvr {<br />
to attendMeeting(room, time) {<br />
# attend the meeting<br />
}<br />
to integrateSpreadsheetVow(RDNumbersVow) {<br />
def sheetVow := when (RDNumbersVow) -> {<br />
["Marketing" => 50000] | RDNumbersVow<br />
} catch prob {<br />
println("No numbers!")<br />
prob<br />
}<br />
return sheetVow<br />
}<br />
}<br />
<br />
#--------- Alice Code<br />
<br />
def aliceRcvr {<br />
to prepareIPOVow() {<br />
def RDNumbersVow := bobRcvr <- getCostNumbers()<br />
def spreadsheet := carolRcvr <- integrateSpreadsheetVow(RDNumbersVow)<br />
return when (spreadsheet) -> {<br />
println(`Appendix: Budget Spreadsheet: $\n$spreadsheet`)<br />
} catch prob {<br />
aliceRcvr <- fireSomebody([bobRcvr, carolRcvr])<br />
}<br />
# do other IPO preparations<br />
}<br />
to fireSomebody(candidateRcvrs) {<br />
# get rid of culprit<br />
}<br />
}<br />
<br />
bobRcvr <- handleExplosionInNetworkServerRoom()<br />
carolRcvr <- attendMeeting(1,2)<br />
aliceRcvr <- prepareIPOVow()</nowiki><br />
<br />
</pre><br />
<br />
===Example: minChat version 1===<br />
<br />
In order to focus on the distributed computation features of this chat tool, we have gone to extreme lengths to make the user interface machinery a very short piece of code. Hence, this should properly be called "minChat", because the user interface is so brutally minimal. Even with such minimization, however, the user interface still requires more lines of code than the actual distributed computation!<br />
<br />
The chatController at the bottom of the example is the heart and soul of the computation.<br />
<br />
<code><br />
<br />
<br />
#?? in new vat minChatVat.e-swt<br />
## E sample<br />
#!/usr/bin/env rune<br />
#eChat with minimalist user interface<br />
pragma.syntax("0.9")<br />
def <widget> := <swt:widgets.*><br />
def SWT := <swt:SWT><br />
introducer.onTheAir()<br />
# return the object represented by the URI<br />
def getObjectFromURI(uri) {return introducer.sturdyFromURI(uri).getRcvr()}<br />
<br />
def makeURIFromObject(obj) :String {<br />
# This implementation assumes a non-persistent single incarnation<br />
def [sr, _, _] := identityMgr.makeKnown(obj)<br />
<span style="color:#FF0000">#XXX not a uri if bracketed, bug, markm?</span><br />
def bracketed := introducer.sturdyToURI(sr)<br />
if (bracketed =~ `<@uri>`) {return uri}<br />
return bracketed<br />
}<br />
<br />
def chatController<br />
def chatArea<br />
def chatUI {<br />
to show() {<br />
def frame := <widget:Shell>(currentDisplay)<br />
frame.setText("eChat"); frame.setBounds(30, 30, 600, 300)<br />
def winDisposeListener {to widgetDisposed(event) {interp.continueAtTop()}} <br />
frame.addDisposeListener(winDisposeListener)<br />
bind chatArea := <widget:Text>(frame, <br />
(SWT.getMULTI() | SWT.getWRAP()) | (SWT.getBORDER() | SWT.getV_SCROLL()))<br />
def commandLine := <widget:Text>(frame, SWT.getSINGLE() | SWT.getBORDER())<br />
def enterKeyListener {<br />
to keyPressed (event) {<br />
if (event.getKeyCode() == 27) {<br />
if (commandLine.getText() =~ `@command @argument`) {<br />
commandLine.setText("")<br />
switch (command) {<br />
match == "save" {chatController.save(<file: argument>)}<br />
match == "load" {chatController.load(<file: argument>)}<br />
match == "send" {chatController.send(argument)}<br />
match _ {commandLine.setText("Error. Try save load, or send")}<br />
}<br />
} else {commandLine.setText("Error. Try save, load, or send")}<br />
}<br />
}<br />
match [verb, args] {}<br />
}<br />
commandLine.addKeyListener(enterKeyListener) <br />
def label := <widget:Label>(frame, SWT.getLEFT())<br />
label.setText("save, load, send. No quotes for path. Use Escape to start operation. ")<br />
swtGrid`$frame: $chatArea.X.Y<br />
$label.X<br />
$commandLine.X`<br />
frame.open()<br />
}<br />
to showMessage(initiator, text) {chatArea.append(`$initiator: $text $\n`)}<br />
}<br />
<br />
def friend<br />
bind chatController {<br />
to send(message) {<br />
when (friend<-receive(message)) -> {<br />
chatUI.showMessage("self", message)<br />
} catch prob {chatUI.showMessage("system", "connection lost")}<br />
}<br />
to receive(message) {chatUI.showMessage("friend", message)}<br />
to receiveFriend(friendRcvr) {<br />
bind friend := friendRcvr <br />
chatUI.showMessage("system", "friend has arrived")<br />
}<br />
to save(file) {file.setText(makeURIFromObject(chatController))}<br />
to load(file) {<br />
bind friend := getObjectFromURI(file.getText())<br />
friend <- receiveFriend(chatController)<br />
}<br />
}<br />
chatUI.show()<br />
# In actual code, the following line would not be commented out<br />
# interp.blockAtTop()</nowiki><br />
<br />
</code><br />
<br />
There are only 5 methods in making chat happen: sending a message to the friend, receiving a message from the friend, being informed that the friend has found you (the ''receivedFriend ''method), saving the URI where your friend can find you, and loading the URI that describes where you can find your friend.<br />
<br />
A quick run through can be done by putting the source in a file (file extension ".e-swt", this example uses SWT for user interface) and launching the file twice to get 2 chat windows. In one window, type "save ~/me.minchat" and press the Escape key. This creates a file (in your home directory) that contains a cap: URI describing where your chat session can be found (a chat session that can only be found by someone to whom this file has been given--the location cannot be found or guessed by anyone else). In the other window, type "load ~/me.minchat" and press Escape. In the first window you should see a message pop up that the "friend has arrived". Now in either window type "send hi y'all", and you will see the message appear in both windows.<br />
<br />
In minChat , every time you start up the program, it comes to life with a new uri that must be sent to the friend with whom you wish to chat; the old uri from the previous session is useless. MinChat would be far more useful if you could create a minChat session with Bob, and continue that session even after you have rebooted your computer. We look at building such a persistent chat in the chapter on Persistent Secure Distributed Computing--after first looking at minChat here through the eyes of a security reviewer (or a cybercracker) in the chapter on Secure Distributed Computing.<br />
<br />
===Patterns of Promises===<br />
<br />
====resolveAllVow====<br />
<br />
Note: this is available as '''<import:com.skyhunter.e.net.resolveAllVow>'''<br />
<br />
Suppose you have a computation that cannot be performed until you have received answers from multiple remote objects. Your first thought would be to use a multi-vow when-catch. But further suppose you do not know beforehand how many vows there are (i.e., suppose you have an arbitrary list of promises). In this case neither the multi-vow when-catch construct nor the nested when-catch pattern will work. For this situation, you can use the resolveAllVow utility described here.<br />
<br />
The resolveAllVow utility has another distinction compared to a multi-vow when-catch: whereas the multi-vow activates the catch clause as soon as it hits a broken promise, resolveAllVow sends no resolution until everything in the list is resolved one way or the other. So, even if several of the promises were broken, with resolveAllVow you can be sure that the rest have been fulfilled when the catch clause is activated.<br />
<br />
In this example, we use resolveAllVow to sum a list of contributions. We do not know beforehand how many contributions there are (perhaps thousands), and we want to sum them up even if some of the requests for donations return broken promises.<br />
<br />
E isBroken(obj) does not work. what does?<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Given a List of promises, when all the promises have been resolved,<br />
# resolve the returned vow, either fulfilling it with the list of fulfillments (if<br />
# all the promises were fulfilled) or by smashing the returned promise<br />
# with one of the broken promises (if at least one promise was broken). <br />
def resolveAllVow(promises) {<br />
def [resultVow, resolver] := Ref.promise()<br />
var count := promises.size()<br />
var resolution := promises<br />
var noneBroken := true<br />
if (count == 0) {resolver.resolve(promises)}<br />
for promise in promises {<br />
when (promise) -> {<br />
# success processed in finally clause<br />
} catch prob {<br />
resolution := prob<br />
noneBroken := false<br />
} finally {<br />
count -= 1<br />
if (count == 0) {<br />
if (noneBroken) {<br />
resolver.resolve(resolution)<br />
} else {resolver.smash(resolution)}<br />
}<br />
}<br />
}<br />
return resultVow<br />
}<br />
#now use the promiseAllResolved to sum contributions, where the<br />
#number of contributions is unknown prior to execution<br />
def printTotalContributions(amountsList) {<br />
var total := 0<br />
for each in amountsList {<br />
if (!(Ref.isBroken(each))) {total += each}<br />
}<br />
println(`Total contributions are: $total`)<br />
}<br />
# scaffold contributors: real contributors would be remote Rcvrs<br />
def makeContributer(donation) {<br />
return def contributor { to getDonation() :int {return donation} }<br />
}<br />
def contributorRcvrsList := [makeContributer(5), makeContributer(6)]<br />
def amountsVows := [].diverge()<br />
for each in contributorRcvrsList {<br />
amountsVows.push(each <- getDonation())<br />
}<br />
when (def amounts := resolveAllVow(amountsVows)) -> { <br />
printTotalContributions(amounts)<br />
} catch prob {<br />
#due to the nature of resolveAllVows, in this catch clause<br />
#we are guaranteed everything in amountsVows is resolved to <br />
#either an amount or a broken reference<br />
printTotalContributions(amountsVows)<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The basic behavior of resolveAllVow is this: when initiated, the function takes a count of how many promises there are, then immediately spins off when-catches for all of them. Each time a promise resolves, the count of outstanding promises is decremented. When the counter drops to zero, implying all the promises have been resolved, the single promise initially returned by resolveAllVow is finally resolved.<br />
<br />
====dialogVowMaker====<br />
<br />
Java's standard dialog boxes, found in JOptionPane, are seriously flawed for use in a distributed <span class="e">''E''</span> system: those convenience dialogs are fully blocking. As a consequence, if your computer is part of a distributed computation, and you go home for the night, if a Java dialog box pops up, your machine is effectively offline until you return in the morning. Included in the <span class="e">''E''</span> distribution is a dialog box tool, the dialogVowMaker:<br />
<br />
<font color="#ff0000">code here</font><br />
<br />
====Recursion for send sequencing====<br />
<br />
As discussed earlier, putting a when-catch inside a for loop does not give you any guarantees on which when-catch will activate first: it only guarantees which message is sent first, which is mostly uninteresting. For general-purpose ensured sequencing of resolution, you must use recursion.<br />
<br />
Earlier, we had an example in which we told a list of cars to moveTo the same location. Suppose we wished to ensure that the cars arrived in the order in which they appear in the list:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def moveAllCarsInSequence(carRcvrs,toX,toY) {<br />
var carI := 0<br />
def moveRemainingCars() {<br />
if (carI < carRcvrs.size()) {<br />
def nextCarRcvr := carRcvrs[carI]<br />
carI += 1<br />
def nameVow := nextCarRcvr <- getName()<br />
when (nameVow,nextCarRcvr <- moveTo(toX,toY)) -> {<br />
println(nameVow + " arrived, next car about to start moving")<br />
} catch e {<br />
println(`car died: $e`)<br />
} finally {moveRemainingCars()}<br />
}<br />
}<br />
moveRemainingCars()<br />
}<br />
# scaffold carmaker<br />
def makeCarRcvr(name) {<br />
def carRcvr {<br />
to getName() :String {return name}<br />
to moveTo(x, y) {<br />
#move the car<br />
}<br />
}<br />
return carRcvr<br />
}<br />
<br />
moveAllCarsInSequence([makeCarRcvr("car1"),makeCarRcvr("car2")],3,4) </nowiki><br />
<br />
</pre><br />
<br />
Inside the moveAllCarsInSequence function, we declare the recursive moveRemainingCars function, then simply invoke moveRemainingCars. The function moveRemainingCars tells the next car to move; once that movement has resolved, moveRemainingCars invokes itself once again.<br />
<br />
In this version of moveAllCarsInSequence, if a car is lost (i.e., its promise to move is broken), the recursion continues. If we wanted to abort after a problem occurred, we would simply delete the call to moveRemainingCars() from the finally clause, and place it in the when clause.<br />
<br />
====sendValve====<br />
<br />
As we have seen, it is possible to spin off large numbers of eventual sends in the blink of an eye. In fact, tossing off vast numbers of such sends can sometimes consume a lot of resources for no good purpose. In the eDesk program at the end of the book, it is possible for the user to request the transfer of whole directories full of files. It would be possible for eDesk to initiate transfer of all of those files simultaneously. But the processing bottleneck is probably bandwidth, so initiating them all at once won't get the whole transfer done any faster, and meanwhile each individual file transfer consumes buffer space once initiated. Starting all the transfers at once could actually slow down the transfer if enough buffers thrash virtual memory.<br />
<br />
What you want is a ''valve'', which can be opened and closed depending on the situation. The program can still set up all the operations in a single swoop, but the valve will constrain the number of such operations that are actually active at a given moment. The sendValve below performs this function.<br />
<br />
<pre><br />
<br />
<nowiki>#sendValve. If you have numerous eventual sends to initiate,<br />
# but initiating them all at once would consume vast resources<br />
# and/or would actually slow down processing, queue the actions <br />
# through a valve.<br />
#An ActionTrio is the list of [obj,"verb",[arguments]]<br />
# that can be used in an E send()<br />
#The actions are guaranteed to be initiated in the sequence in<br />
# which they are placed in the valve, though of course there is<br />
# no guarantee as to which will terminate first (unless you have<br />
# special knowledge of such sequencing outside the valve).<br />
#The numSimultaneousAllowed is the number of actions that can<br />
# be run concurrently through this valve.<br />
<br />
# E sample<br />
def makeSendValve (numSimultaneousAllowed) {<br />
var actionQueue := []<br />
var numRunning := 0<br />
def startNext() {<br />
if (!(actionQueue.size()==0)) {<br />
def [actionTrio, resolver] := actionQueue[0]<br />
actionQueue := actionQueue(1, actionQueue.size())<br />
numRunning += 1<br />
def completeVow := E.send(actionTrio[0],actionTrio[1],actionTrio[2])<br />
resolver.resolve(completeVow)<br />
when (completeVow) -> {<br />
} catch prob {<br />
} finally { <br />
numRunning -= 1 <br />
startNext()<br />
}<br />
}<br />
}<br />
def valve {<br />
to makeActionVow(actionTrio) {<br />
def [completeVow, resolver] := Ref.promise()<br />
actionQueue := actionQueue.with([actionTrio, resolver])<br />
if (numRunning < numSimultaneousAllowed) {<br />
startNext()<br />
}<br />
return completeVow<br />
}<br />
}<br />
return valve<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The sendValve utility, if used with numSimultaneousAllowed==1, can also perform the send sequencing function described earlier. However, the earlier general send sequencing pattern is still useful. For example, if the moveAllCarsInSequence operation should abort upon a encountering a broken resolution, this version of sendValve would not give the correct result.<br />
<br />
====Summoning====<br />
<br />
====Transparent forwarder====<br />
<br />
It is possible to have a network of machines in which the machines do not all have direct access to one another. Suppose in the network with machine A, B, and C, A and C cannot form a direct connection because of network topology, but B can reach everything. If A needs a capability on C, we can put a transparent forwarder on B such that A sends its messages to the forwarder on B:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeTransparentForwarder(representedRcvr) {<br />
def forwarder {<br />
match [verb,args] {E.send(representedRcvr,verb,args)}<br />
}<br />
return forwarder<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Create the forwarder on B, and hand the reference to the forwarder to the appropriate object on A. An example can be found in the eDesk example at the end of the book, in which a forwarder is used if the system detects that two of the file servers are unable to directly connect. Note that the "delegate" keyword does not quite work here: delegate generates immediate calls, not eventual sends. So we had to revert to the more general purpose matching process.<br />
<br />
====acceptOnlyMoreRecentVow====<br />
<br />
Suppose you are periodically requesting a particular piece of information from a far object. Suppose the far object cannot supply the answer in a single game turn, i.e., it must ask other objects for information to get the answer, and so it sends you a promise rather than a result. It is possible for the resolutions of these promises to occur out-of-order, i.e., the resolution on the second request could get to you after the resolution of the third request has already occurred. In this situation, it will appear that the answer to the second request is newer and more up-to-date than the third request.<br />
<br />
<font color="#000000">In this situation, to ensure you are getting only new information, not stale information, use the acceptOnlyMoreRecentVow utility.</font><br />
<br />
<pre><br />
<br />
def acceptOnlyMoreRecentVow<br />
<br />
</pre><br />
<br />
<font color="#ff0000">code here</font><br />
<br />
This situation, while rare, actually arises in the Marketplace example in the Secure Distributed Computing chapter.<br />
<br />
<font color="#ff0000">something about time, the race construct, timeout construct</font><br />
<br />
====eDesk overwrite copy jewel====<br />
<br />
The following is not really a pattern so much as it is an example of all the more novel (i.e., not-like-Java) elements of <span class="e">''E''</span> playing together. The problem, taken from the eDesk program in the Examples at the end of the book, is this:<br />
<br />
example<br />
<br />
===Data Lock===<br />
<br />
Though <span class="e">''E''</span> is safe from deadlock, in which several objects compete for acquisition to a set of resources, there is a related dilemma that <span class="e">''E''</span> programs can encounter. If two or more "when" clauses wait for each other to resolve before they can resolve themselves, this causes ''data lock''. A complete discussion of data lock and why it is far less of a risk than deadlock is beyond the scope of this book. Briefly, both theory and current experience suggest that data locks are more difficult to create in the wild than deadlocks. Furthermore, when datalocks do occur, they are less likely to freeze up important subsystems on a grand scale: unlike the deadlock, they only choke a few "when" clauses, not a set of "critical sections" which have been named "critical" in thread programming for good reasons. And lastly, datalocks are consistent, reproducible, and therefore fixable, unlike the deadlocks that appear mysteriously when some incredibly arcane race condition occurs.<br />
<br />
Here is a simple though foolish example of datalock. It is the E implementation of the English sentence, "This sentence is false."<br />
<br />
<pre><br />
<br />
def sentence := sentence <- not()<br />
<br />
</pre><br />
<br />
In this construction, the sentence will forever be an unresolved promise. As noted above, the failure of this to resolve will not impede the progress of the rest of the program in the least. And it is very reliable: the unresolvability of the promise will appear the first time you run the program, and the second, and in every debugging pass thereafter.<br />
<br />
At the time of this writing, data lock has been seen only once in the wild. In that instance, a widely used object (call it WUO),contained one piece of mutable state and one piece of immutable state. The object that computed new versions of WUO's mutable state needed the immutable part of the state, and requested the current version of WUO from the owner of the object. Unfortunately, the owner knew that a new version was under construction, and was only sending out promises for WUO until the update was resolved. The solution in this case was to refactor WUO. This resulted in an architecture that was cleaner even by normal object design criteria, without regard to the distributed usage behavior. Insufficient data is yet available to assess how commonly this type of solution will suffice.<br />
<br />
<br />
Next Section: [[Walnut/Secure_Distributed_Computing|Secure Distributed Computing]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Distributed_ComputingWalnut/Distributed Computing2011-08-03T14:14:12Z<p>ThomasLeonard: Removed out-of-date comment done functions</p>
<hr />
<div>[[Category:Walnut|3]]<br />
<br />
==Distributed Computing==<br />
<br />
Multiple threads form the basis of conventional models of concurrent programming. Remarkably, human beings engage in concurrent distributed computing every day even though people are generally single threaded (there are exceptions: Walter Cronkite routinely listened to one broadcast with one ear, a different broadcast with the other, while simultaneously taking notes on another topic and speaking authoritatively to an audience of millions. But most people, including this author, live single-threaded lives).<br />
<br />
How do we simple creatures pull off the feat of distributed computing without multiple threads? Why do we not see groups of people, deadlocked in frozen tableau around the coffepot, one person holding the sugar waiting for milk, the other holding milk waiting for sugar?<br />
<br />
The answer is, we use a sophisticated computational mechanism known as a ''nonblocking promise''.<br />
<br />
Let us look at a conventional human distributed computation. Alice, the CEO of Evernet Computing, needs a new version of the budget including R&D numbers from the VP of Engineering, Bob. Alice calls Bob: "Could you get me those numbers?"<br />
<br />
Bob jots Alice's request on his to-do list. "Sure thing, Alice, I promise I'll get them for you after I solve this engineering problem."<br />
<br />
Bob has handed Alice a promise for the answer. He has ''not '' handed her the answer. But neither Bob nor Alice sits on their hands, blocked, waiting for the resolution.<br />
<br />
Rather, Bob continues to work his current problem. And Alice goes to Carol, the CFO: "Carol, when Bob gets those numbers, plug 'em into the spreadsheet and give me the new budget,okay?"<br />
<br />
Carol: "No problem." Carol writes Alice's request on her own to-do list, but does not put it either first or last in the list. Rather, she puts it in the conditional part of the list, to be done when the condition is met--in this case, when Bob fulfills his promise.<br />
<br />
Conceptually, Alice has handed to Carol a copy of Bob's promise for numbers, and Carol has handed to Alice a promise for a new integrated spreadsheet. Once again, no one waits around, blocked. Carol ambles down the hall for a contract negotiation, Alice goes back to preparing for the IPO.<br />
<br />
When Bob finishes his calculations, he signals that his promise has been fulfilled; when Carol receives the signal, she uses Bob's fulfilled promise to fulfill her own promise; when Carol fulfills her promise, Alice gets her spreadsheet. A sophisticated distributed computation has been completed so simply that no one realizes an advanced degree in computer science should have been required.<br />
<br />
In this simple example, we see why human beings never get trapped in the thread-based deadlock situations described endlessly in books on concurrent programming. People don't deadlock because they live in a concurrent world managed with a promise-based architecture. And so it is with <span class="e">''E''</span>.<br />
<br />
This chapter on distributed computing is the longest and most challenging part of the book. The Promise Architecture of <span class="e">''E''</span> is very different from the threads, synchronized methods, guarded objects, and RMI of Java. One might expect the Security chapter and its Capability paradigm to be equally new and challenging. But in fact, the implementation of security is embedded so deeply in E's infrastructure that much of the effort merely involves realizing the power inherent in constructs we have already learned. Security with <span class="e">''E''</span> is more a matter of architecture than of coding.<br />
<br />
Distributed computation, however, still requires gritty effort. We start simply, with the eventually operator.<br />
<br />
{{:Walnut/Distributed Computing/Eventually Operator}}<br />
{{:Walnut/Distributed Computing/Promises}}<br />
{{:Walnut/Distributed Computing/Multiway when-catch}}<br />
{{:Walnut/Distributed Computing/Partial Ordering Of Sent Messages}}<br />
{{:Walnut/Distributed Computing/Naming conventions}}<br />
{{:Walnut/Distributed Computing/Testing for Equality in a Distributed System}}<br />
<br />
===Letting When-Catch make a Promise For You===<br />
<br />
As noted in chapter 1 under the Secret Lives of Flow Control Structures, control structures return values. When used as described up to this point, the return value of the when--catch expression has been ignored. In fact, the when-catch expression returns a promise for the last value that the executed clause (the body or catch block) will return.<br />
<br />
Rewriting the calcMilesBeforeEmptyVow using this feature, we get:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def calcMilesBeforeEmptyVow(carRcvr) { <br />
def fuelRemainingVow := carRcvr <- getFuelRemaining() <br />
def mpgVow := carRcvr <- getEfficiency() <br />
return when (fuelRemainingVow, mpgVow) -> { <br />
mpgVow * fuelRemainingVow <br />
}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here the when-catch creates the promise which is returned by the function, and resolution is automatic at the end of the when-catch execution. <br />
So when the promise that the when-catch depends on is resolved the promise it returned will be resolved to the result of the last seqExp in the when clause (i.e. the "mpgVow * fuelRemainingVow" expression).<br />
<br />
Note that we don't need a catch block here. The default behaviour if the promise that the when-catch depends on is smashed is to smash the promise of the when--catch block, which will trigger the catch block in the main program. Normally, you should either report an error or propagate it, so that every error gets reported exactly once.<br />
<br />
Whatever happens, the finally clause has no effect on the resolution of the promise returned by when-catch.<br />
<br />
Warning: A common mistake is to put the "return" statement inside the when block. This will lead to the confusing error message "Ejector must be enabled" (return is a type of "ejector", which causes a function to return a value, but by the time the when block executes, the original function call has already returned).<br />
<br />
===Broken Promise Contagion===<br />
<br />
When chaining promises, what happens if one of the promises in the middle or the far end breaks? The problem that breaks the far promise is propagated down all the promises dependent on it. As a consequence, broken promises work their way through the system in a similar way to exceptions being caught in try/catch blocks.<br />
<br />
===State Transitions for References===<br />
<br />
Having worked our way through near, far, broken, and promised references, let us put all the transitions among these together in a single place. The following diagram shows all the kinds of references <span class="e">''E''</span> distinguishes between, and it shows the two possible transitions:<br />
<br />
<font color="rgb(255, 0, 0)"> [[Image:ref-mech-0.gif|state transition diagram]]</font><br />
<br />
The 2 transitions are:<br />
<br />
* A promise may transition (resolve) into a resolved reference, which can be near or far or broken..<br />
* A far ref may transition to a broken ref.<br />
<br />
That is the complete collection of transitions.<br />
<br />
===Guards for distributed systems===<br />
<br />
Very early in the book, we presented a list of <span class="e">''E''</span> types, including any, integer, float64, etc. In that list were "rcvr", "vow", "pbc" and "near". "pbc" means that the type of the value is required to be "pass by construction". Transparent immutables are generally pbc, and can be passed through this type declaration. Strings, integers, floats, booleans, ConstMaps and ConstLists are all pbc. Objects that are pbc are copied when they are sent, so that even if the object originated on a remote computer, when you get it you can use immediate calls on it. Also, since pbc objects do not embody any code, pbc objects passed across a trust boundary can be used with far fewer security concerns: the pbc object may contain bad data, but it cannot play any tricky games in its execution.<br />
<br />
"Near" means that the value must be local. Promises and far references will not pass the near guard. Anything that passes a near guard can be sent messages with immediate calls.<br />
<br />
At this time, "rcvr" and "vow" have the same algorithmic meaning as "any", but can be used as hints to the programmer about how to interact with the object (a vow should be referenced only eventually until it is resolved; a rcvr should always be referenced only eventually).<br />
<br />
===Nested When-Catch constructs===<br />
<br />
As discussed earlier, we can guarantee the ordering of messages sent from one object to another object. But when a program sends messages to several objects, on different machines, the order in which answers will be received cannot be predicted. Suppose you need to perform a computation involving two far answers, and the algorithm depends on the result from the first answer. You can nest when-catch clauses to await the outcome of the dependency:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def fileRcvr := fileCacheRcvr <- getFile()<br />
when (def exists := fileRcvr <- exists()) -> {<br />
if (exists) {<br />
when (def text := fileRcvr <- getText()) -> {<br />
println(`File has text: $text`)<br />
} catch p2 {println(`Problem with existing file: $p2`)}<br />
} else {println("File does not exist")}<br />
} catch prob {println(`Problem reaching file: $prob`)}<br />
</nowiki><br />
<br />
</pre><br />
<br />
Here, we want to print the text of a farFile, but we want to be sure the file exists first. So we ask the file if it exists, and only after we determine that it does indeed exist do we proceed to get the text.<br />
<br />
===Live Refs, Sturdy Refs, and URIs===<br />
<br />
Up to this point we have carefully dodged a critical question. How does a program acquire its very first reference to an object on a different computer? In all our examples up to this point, we have always started out with a reference to at least one remote object, and we retrieved other remote objects by asking that object for other objects: for example, we asked a remote carMakerRcvr for a new (remote) carRcvr, and were able to immediately work with the car just like any other remote object. How did we get the reference to the carMakerRcvr in the first place?<br />
<br />
In <span class="e">''E''</span>, the reference to an object can be encoded as a Universal Resource Identifier string, known as a ''uri'' (the familiar url of the Web is a type of uri). This uri string can be passed around in many fashions; one good secure way of passing a uri is to save it as a text file, encrypt and sign it with PGP, and send it in email. If you wish to run a seriously secure distributed <span class="e">''E''</span> system, encrypting the uris is crucial: indeed, the passing of the uris from machine to machine is the main security issue that <span class="e">''E''</span> cannot address for you (and is a problem shared by all security systems, a problem that will diminish with time as secure systems like PGP email are deployed). Other ways uris have been passed in operational <span class="e">''E''</span> systems have been to send the uri over an ssh connection, and (less securely) by reading the uri off over a telephone! If you are using <span class="e">''E''</span> on a local area network and have no security concerns, but are using <span class="e">''E''</span> simply because it is simpler, safer, and more maintainable for distributed computing, the uris can be stored in files on a shared file system and read directly by the programs on different computers as they start up.<br />
<br />
The functions makeURI(object) and objFromURI(uri) detailed in the <span class="e">''E''</span> Quick Reference Card perform the basic transformations you need to hook up objects on multiple computers. These routines use sturdy refs and liverefs in their computations. A sturdyRef is an object that contains an enduring description of where an object can be found; sturdyRefs and URIs are simple transformations of one another. LiveRefs are actual connections to objects that disappear any time a connection goes down. LiveRefs carry the actual traffic in <span class="e">''E''</span> communication. When you request a remote object from another remote object (as in farCarMaker <- ("mercedes")), what you actually get is a liveRef. If you want to continue to connect with that particular car across multiple sessions, you will need to explicitly get a sturdyRef from the car (and the car will have to have an explicit method for granting the sturdyRef. The sturdyref function is an important capability, not one handed out by default).<br />
<br />
Each program that expects to work with remote objects needs to invoke the command<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
introducer.onTheAir() </nowiki><br />
<br />
</pre><br />
<br />
before starting any remote connections, including the making or using of uris. An example of these functions working together can be found in eChat.<br />
<br />
===blockAtTop and continueAtTop===<br />
<br />
E programs never block. They never just sit and wait around for results. However, most programs will toss out some windows, or set up some services, and then desire to wait for someone or some thing to use them. Often, the first version of a program written by a new <span class="e">''E''</span> programmer will set everything up, execute the last line of the program, and then shut down. It is quite disconcerting to watch your windows briefly light up and then disappear, along with the java virtual machine underlying the entire program.<br />
<br />
The command<br />
<br />
<pre><br />
<br />
interp.blockAtTop()<br />
<br />
</pre><br />
<br />
causes the <span class="e">''E''</span> interpreter to wait for requests to come in. The command<br />
<br />
<pre><br />
<br />
interp.continueAtTop()<br />
<br />
</pre><br />
<br />
causes the <span class="e">''E''</span> interpreter to stop waiting. These commands are used in the eChat sample at the end of this chapter: the last line of the program initiates blockAtTop, and continueAtTop is invoked when the user closes his chat window.<br />
<br />
===A bit of Philosophy when using Promises for the first time===<br />
<br />
If a method accepts a promise or far reference as a parameter, the returned value almost certainly cannot be a local object. Why is this? If the computation of the returned object depends on something eventual, the computation will have to wait for an answer, which means the best the object can do for immediately returning something is to return a promise. So a method like getCar(licensePlateVow) has almost certainly violated the naming convention, one way or the other.<br />
<br />
As a consequence of this and other characteristics of promises, beginning E programmers often experience a moment of breathlessness soon after they first try to use them. This moment occurs when the programmer erroneously concludes that, once you let a promise into your system, the program has tumbled down a slippery slope from which there is no recovery. It feels as if you will never be able to have a real value in your hands again; you'll spend the rest of your life making eventual sends, coupled with endless when-catch constructs just to get to the next step.<br />
<br />
The breathlessness can metastasize into a feeling of having lost control of the software: everything is off computing somewhere else and all you have is a bunch of promises. Since <span class="e">''E''</span> never (really, never!) blocks, you can never tell things, "just stop for a moment while I catch my breath and gather up all the values" :-)<br />
<br />
In fact, there are several patterns and tools for getting control of things again. The basic multi-promise when-catch, and the promiseAllResolved and Summoner patterns at the end of this chapter are just a few examples of structures specifically designed to reduce the frequency with which you need when-catch. They allow you to get quickly back into local computation after a distributed action. You really can catch your breath.<br />
<br />
And once the moment of breathlessness passes, you will feel freedom, for you will never have to deal with thread synchronization again; you will never lie awake at night wondering if an unexplored race condition will cause deadlock a few days after the production load level hits your system. <font color="#ff0000">How early can I put this paragraph easily? AHK proposes right after Promises.</font><br />
<br />
===Additional Promise-Related Operations===<br />
<br />
* whenBroken<br />
* E isBroken<br />
* whenResolved Use this when your action will be the same once the promise resolves, regardless of whether it resolves broken or not.<br />
* E isResolved<br />
* E send(object,verb,arguments) This function is identical to the E call() function described earlier, but does an eventual send rather than an immediate call.<br />
* E sendOnly<br />
* E join(a,b) Guarantees sends to result of join are delivered only after messages to a and b have been delivered, sort of a test for equality on-the-fly<br />
<br />
===Under the Covers: Vats and Game Turns===<br />
<br />
<font color="#ff0000">Each vat has a separate event loop, each game turn corresponds to the processing of a single event to conclusion with no interruptions. There are frontend vats, which all share the swing event queue for queuing messages to their event loops, and there are backend queues, each of which has its own separate event queue and runs on a separate thread. Frontend vats have the advantage that they can interact directly with user interface widgets. The initial vat created by default at the start of an E program is a frontend vat. You might want multiple frontend vats if you want to shut down whole subsystems in one fell swoop: you can tell a vat to shut down, and it will terminate all its connections to the outside world, making it available for garbage collection. Have markm review this and tell me what is wrong with this description.</font><br />
<br />
<font color="#ff0000">creating a second frontend vat on a single jvm. creating a backend vat on a jvm</font><br />
<br />
===Example: Alice, Bob, and Carol as Code===<br />
<br />
We started this chapter with a description of a human interaction, with Alice as the CEO of Evernet Computing in search of a new spreadsheet for her IPO preparation. What would that distributed problem look like in code? Though we present only a skeleton of this human operation here, it is perhaps nonetheless informative. It might also be informative, after one has read how to do the example in <span class="e">''E''</span>, to think about how it would be done with threads, in Java or C++. That, however, is left as an exercise for the reader.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#---- Bob Code<br />
<br />
def bobRcvr {<br />
to handleExplosionInNetworkServerRoom() {<br />
# handle the explosion<br />
}<br />
to getCostNumbers() :pbc {<br />
return ["R&D" => 10000]<br />
}<br />
}<br />
<br />
#------------ Carol Code<br />
<br />
def carolRcvr {<br />
to attendMeeting(room, time) {<br />
# attend the meeting<br />
}<br />
to integrateSpreadsheetVow(RDNumbersVow) {<br />
def sheetVow := when (RDNumbersVow) -> {<br />
["Marketing" => 50000] | RDNumbersVow<br />
} catch prob {<br />
println("No numbers!")<br />
prob<br />
}<br />
return sheetVow<br />
}<br />
}<br />
<br />
#--------- Alice Code<br />
<br />
def aliceRcvr {<br />
to prepareIPOVow() {<br />
def RDNumbersVow := bobRcvr <- getCostNumbers()<br />
def spreadsheet := carolRcvr <- integrateSpreadsheetVow(RDNumbersVow)<br />
return when (spreadsheet) -> {<br />
println(`Appendix: Budget Spreadsheet: $\n$spreadsheet`)<br />
} catch prob {<br />
aliceRcvr <- fireSomebody([bobRcvr, carolRcvr])<br />
}<br />
# do other IPO preparations<br />
}<br />
to fireSomebody(candidateRcvrs) {<br />
# get rid of culprit<br />
}<br />
}<br />
<br />
bobRcvr <- handleExplosionInNetworkServerRoom()<br />
carolRcvr <- attendMeeting(1,2)<br />
aliceRcvr <- prepareIPOVow()</nowiki><br />
<br />
</pre><br />
<br />
===Example: minChat version 1===<br />
<br />
In order to focus on the distributed computation features of this chat tool, we have gone to extreme lengths to make the user interface machinery a very short piece of code. Hence, this should properly be called "minChat", because the user interface is so brutally minimal. Even with such minimization, however, the user interface still requires more lines of code than the actual distributed computation!<br />
<br />
The chatController at the bottom of the example is the heart and soul of the computation.<br />
<br />
<code><br />
<br />
<br />
#?? in new vat minChatVat.e-swt<br />
## E sample<br />
#!/usr/bin/env rune<br />
#eChat with minimalist user interface<br />
pragma.syntax("0.9")<br />
def <widget> := <swt:widgets.*><br />
def SWT := <swt:SWT><br />
introducer.onTheAir()<br />
# return the object represented by the URI<br />
def getObjectFromURI(uri) {return introducer.sturdyFromURI(uri).getRcvr()}<br />
<br />
def makeURIFromObject(obj) :String {<br />
# This implementation assumes a non-persistent single incarnation<br />
def [sr, _, _] := identityMgr.makeKnown(obj)<br />
<span style="color:#FF0000">#XXX not a uri if bracketed, bug, markm?</span><br />
def bracketed := introducer.sturdyToURI(sr)<br />
if (bracketed =~ `<@uri>`) {return uri}<br />
return bracketed<br />
}<br />
<br />
def chatController<br />
def chatArea<br />
def chatUI {<br />
to show() {<br />
def frame := <widget:Shell>(currentDisplay)<br />
frame.setText("eChat"); frame.setBounds(30, 30, 600, 300)<br />
def winDisposeListener {to widgetDisposed(event) {interp.continueAtTop()}} <br />
frame.addDisposeListener(winDisposeListener)<br />
bind chatArea := <widget:Text>(frame, <br />
(SWT.getMULTI() | SWT.getWRAP()) | (SWT.getBORDER() | SWT.getV_SCROLL()))<br />
def commandLine := <widget:Text>(frame, SWT.getSINGLE() | SWT.getBORDER())<br />
def enterKeyListener {<br />
to keyPressed (event) {<br />
if (event.getKeyCode() == 27) {<br />
if (commandLine.getText() =~ `@command @argument`) {<br />
commandLine.setText("")<br />
switch (command) {<br />
match == "save" {chatController.save(<file: argument>)}<br />
match == "load" {chatController.load(<file: argument>)}<br />
match == "send" {chatController.send(argument)}<br />
match _ {commandLine.setText("Error. Try save load, or send")}<br />
}<br />
} else {commandLine.setText("Error. Try save, load, or send")}<br />
}<br />
}<br />
match [verb, args] {}<br />
}<br />
commandLine.addKeyListener(enterKeyListener) <br />
def label := <widget:Label>(frame, SWT.getLEFT())<br />
label.setText("save, load, send. No quotes for path. Use Escape to start operation. ")<br />
swtGrid`$frame: $chatArea.X.Y<br />
$label.X<br />
$commandLine.X`<br />
frame.open()<br />
}<br />
to showMessage(initiator, text) {chatArea.append(`$initiator: $text $\n`)}<br />
}<br />
<br />
def friend<br />
bind chatController {<br />
to send(message) {<br />
when (friend<-receive(message)) -> {<br />
chatUI.showMessage("self", message)<br />
} catch prob {chatUI.showMessage("system", "connection lost")}<br />
}<br />
to receive(message) {chatUI.showMessage("friend", message)}<br />
to receiveFriend(friendRcvr) {<br />
bind friend := friendRcvr <br />
chatUI.showMessage("system", "friend has arrived")<br />
}<br />
to save(file) {file.setText(makeURIFromObject(chatController))}<br />
to load(file) {<br />
bind friend := getObjectFromURI(file.getText())<br />
friend <- receiveFriend(chatController)<br />
}<br />
}<br />
chatUI.show()<br />
# In actual code, the following line would not be commented out<br />
# interp.blockAtTop()</nowiki><br />
<br />
</code><br />
<br />
There are only 5 methods in making chat happen: sending a message to the friend, receiving a message from the friend, being informed that the friend has found you (the ''receivedFriend ''method), saving the URI where your friend can find you, and loading the URI that describes where you can find your friend.<br />
<br />
A quick run through can be done by putting the source in a file (file extension ".e-swt", this example uses SWT for user interface) and launching the file twice to get 2 chat windows. In one window, type "save ~/me.minchat" and press the Escape key. This creates a file (in your home directory) that contains a cap: URI describing where your chat session can be found (a chat session that can only be found by someone to whom this file has been given--the location cannot be found or guessed by anyone else). In the other window, type "load ~/me.minchat" and press Escape. In the first window you should see a message pop up that the "friend has arrived". Now in either window type "send hi y'all", and you will see the message appear in both windows.<br />
<br />
In minChat , every time you start up the program, it comes to life with a new uri that must be sent to the friend with whom you wish to chat; the old uri from the previous session is useless. MinChat would be far more useful if you could create a minChat session with Bob, and continue that session even after you have rebooted your computer. We look at building such a persistent chat in the chapter on Persistent Secure Distributed Computing--after first looking at minChat here through the eyes of a security reviewer (or a cybercracker) in the chapter on Secure Distributed Computing.<br />
<br />
===Patterns of Promises===<br />
<br />
====resolveAllVow====<br />
<br />
Note: this is available as '''<import:com.skyhunter.e.net.resolveAllVow>'''<br />
<br />
Suppose you have a computation that cannot be performed until you have received answers from multiple remote objects. Your first thought would be to use a multi-vow when-catch. But further suppose you do not know beforehand how many vows there are (i.e., suppose you have an arbitrary list of promises). In this case neither the multi-vow when-catch construct nor the nested when-catch pattern will work. For this situation, you can use the resolveAllVow utility described here.<br />
<br />
The resolveAllVow utility has another distinction compared to a multi-vow when-catch: whereas the multi-vow activates the catch clause as soon as it hits a broken promise, resolveAllVow sends no resolution until everything in the list is resolved one way or the other. So, even if several of the promises were broken, with resolveAllVow you can be sure that the rest have been fulfilled when the catch clause is activated.<br />
<br />
In this example, we use resolveAllVow to sum a list of contributions. We do not know beforehand how many contributions there are (perhaps thousands), and we want to sum them up even if some of the requests for donations return broken promises.<br />
<br />
E isBroken(obj) does not work. what does?<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Given a List of promises, when all the promises have been resolved,<br />
# resolve the returned vow, either fulfilling it with the list of fulfillments (if<br />
# all the promises were fulfilled) or by smashing the returned promise<br />
# with one of the broken promises (if at least one promise was broken). <br />
def resolveAllVow(promises) {<br />
def [resultVow, resolver] := Ref.promise()<br />
var count := promises.size()<br />
var resolution := promises<br />
var noneBroken := true<br />
if (count == 0) {resolver.resolve(promises)}<br />
for promise in promises {<br />
when (promise) -> {<br />
# success processed in finally clause<br />
} catch prob {<br />
resolution := prob<br />
noneBroken := false<br />
} finally {<br />
count -= 1<br />
if (count == 0) {<br />
if (noneBroken) {<br />
resolver.resolve(resolution)<br />
} else {resolver.smash(resolution)}<br />
}<br />
}<br />
}<br />
return resultVow<br />
}<br />
#now use the promiseAllResolved to sum contributions, where the<br />
#number of contributions is unknown prior to execution<br />
def printTotalContributions(amountsList) {<br />
var total := 0<br />
for each in amountsList {<br />
if (!(Ref.isBroken(each))) {total += each}<br />
}<br />
println(`Total contributions are: $total`)<br />
}<br />
# scaffold contributors: real contributors would be remote Rcvrs<br />
def makeContributer(donation) {<br />
return def contributor { to getDonation() :int {return donation} }<br />
}<br />
def contributorRcvrsList := [makeContributer(5), makeContributer(6)]<br />
def amountsVows := [].diverge()<br />
for each in contributorRcvrsList {<br />
amountsVows.push(each <- getDonation())<br />
}<br />
when (def amounts := resolveAllVow(amountsVows)) -> { <br />
printTotalContributions(amounts)<br />
} catch prob {<br />
#due to the nature of resolveAllVows, in this catch clause<br />
#we are guaranteed everything in amountsVows is resolved to <br />
#either an amount or a broken reference<br />
printTotalContributions(amountsVows)<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The basic behavior of resolveAllVow is this: when initiated, the function takes a count of how many promises there are, then immediately spins off when-catches for all of them. Each time a promise resolves, the count of outstanding promises is decremented. When the counter drops to zero, implying all the promises have been resolved, the single promise initially returned by resolveAllVow is finally resolved.<br />
<br />
====dialogVowMaker====<br />
<br />
Java's standard dialog boxes, found in JOptionPane, are seriously flawed for use in a distributed <span class="e">''E''</span> system: those convenience dialogs are fully blocking. As a consequence, if your computer is part of a distributed computation, and you go home for the night, if a Java dialog box pops up, your machine is effectively offline until you return in the morning. Included in the <span class="e">''E''</span> distribution is a dialog box tool, the dialogVowMaker:<br />
<br />
<font color="#ff0000">code here</font><br />
<br />
====Recursion for send sequencing====<br />
<br />
As discussed earlier, putting a when-catch inside a for loop does not give you any guarantees on which when-catch will activate first: it only guarantees which message is sent first, which is mostly uninteresting. For general-purpose ensured sequencing of resolution, you must use recursion.<br />
<br />
Earlier, we had an example in which we told a list of cars to moveTo the same location. Suppose we wished to ensure that the cars arrived in the order in which they appear in the list:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def moveAllCarsInSequence(carRcvrs,toX,toY) {<br />
var carI := 0<br />
def moveRemainingCars() {<br />
if (carI < carRcvrs.size()) {<br />
def nextCarRcvr := carRcvrs[carI]<br />
carI += 1<br />
def nameVow := nextCarRcvr <- getName()<br />
when (nameVow,nextCarRcvr <- moveTo(toX,toY)) -> {<br />
println(nameVow + " arrived, next car about to start moving")<br />
} catch e {<br />
println(`car died: $e`)<br />
} finally {moveRemainingCars()}<br />
}<br />
}<br />
moveRemainingCars()<br />
}<br />
# scaffold carmaker<br />
def makeCarRcvr(name) {<br />
def carRcvr {<br />
to getName() :String {return name}<br />
to moveTo(x, y) {<br />
#move the car<br />
}<br />
}<br />
return carRcvr<br />
}<br />
<br />
moveAllCarsInSequence([makeCarRcvr("car1"),makeCarRcvr("car2")],3,4) </nowiki><br />
<br />
</pre><br />
<br />
Inside the moveAllCarsInSequence function, we declare the recursive moveRemainingCars function, then simply invoke moveRemainingCars. The function moveRemainingCars tells the next car to move; once that movement has resolved, moveRemainingCars invokes itself once again.<br />
<br />
In this version of moveAllCarsInSequence, if a car is lost (i.e., its promise to move is broken), the recursion continues. If we wanted to abort after a problem occurred, we would simply delete the call to moveRemainingCars() from the finally clause, and place it in the when clause.<br />
<br />
====sendValve====<br />
<br />
As we have seen, it is possible to spin off large numbers of eventual sends in the blink of an eye. In fact, tossing off vast numbers of such sends can sometimes consume a lot of resources for no good purpose. In the eDesk program at the end of the book, it is possible for the user to request the transfer of whole directories full of files. It would be possible for eDesk to initiate transfer of all of those files simultaneously. But the processing bottleneck is probably bandwidth, so initiating them all at once won't get the whole transfer done any faster, and meanwhile each individual file transfer consumes buffer space once initiated. Starting all the transfers at once could actually slow down the transfer if enough buffers thrash virtual memory.<br />
<br />
What you want is a ''valve'', which can be opened and closed depending on the situation. The program can still set up all the operations in a single swoop, but the valve will constrain the number of such operations that are actually active at a given moment. The sendValve below performs this function.<br />
<br />
<pre><br />
<br />
<nowiki>#sendValve. If you have numerous eventual sends to initiate,<br />
# but initiating them all at once would consume vast resources<br />
# and/or would actually slow down processing, queue the actions <br />
# through a valve.<br />
#An ActionTrio is the list of [obj,"verb",[arguments]]<br />
# that can be used in an E send()<br />
#The actions are guaranteed to be initiated in the sequence in<br />
# which they are placed in the valve, though of course there is<br />
# no guarantee as to which will terminate first (unless you have<br />
# special knowledge of such sequencing outside the valve).<br />
#The numSimultaneousAllowed is the number of actions that can<br />
# be run concurrently through this valve.<br />
<br />
# E sample<br />
def makeSendValve (numSimultaneousAllowed) {<br />
var actionQueue := []<br />
var numRunning := 0<br />
def startNext() {<br />
if (!(actionQueue.size()==0)) {<br />
def [actionTrio, resolver] := actionQueue[0]<br />
actionQueue := actionQueue(1, actionQueue.size())<br />
numRunning += 1<br />
def completeVow := E.send(actionTrio[0],actionTrio[1],actionTrio[2])<br />
resolver.resolve(completeVow)<br />
when (completeVow) -> {<br />
} catch prob {<br />
} finally { <br />
numRunning -= 1 <br />
startNext()<br />
}<br />
}<br />
}<br />
def valve {<br />
to makeActionVow(actionTrio) {<br />
def [completeVow, resolver] := Ref.promise()<br />
actionQueue := actionQueue.with([actionTrio, resolver])<br />
if (numRunning < numSimultaneousAllowed) {<br />
startNext()<br />
}<br />
return completeVow<br />
}<br />
}<br />
return valve<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The sendValve utility, if used with numSimultaneousAllowed==1, can also perform the send sequencing function described earlier. However, the earlier general send sequencing pattern is still useful. For example, if the moveAllCarsInSequence operation should abort upon a encountering a broken resolution, this version of sendValve would not give the correct result.<br />
<br />
====Summoning====<br />
<br />
====Transparent forwarder====<br />
<br />
It is possible to have a network of machines in which the machines do not all have direct access to one another. Suppose in the network with machine A, B, and C, A and C cannot form a direct connection because of network topology, but B can reach everything. If A needs a capability on C, we can put a transparent forwarder on B such that A sends its messages to the forwarder on B:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeTransparentForwarder(representedRcvr) {<br />
def forwarder {<br />
match [verb,args] {E.send(representedRcvr,verb,args)}<br />
}<br />
return forwarder<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Create the forwarder on B, and hand the reference to the forwarder to the appropriate object on A. An example can be found in the eDesk example at the end of the book, in which a forwarder is used if the system detects that two of the file servers are unable to directly connect. Note that the "delegate" keyword does not quite work here: delegate generates immediate calls, not eventual sends. So we had to revert to the more general purpose matching process.<br />
<br />
====acceptOnlyMoreRecentVow====<br />
<br />
Suppose you are periodically requesting a particular piece of information from a far object. Suppose the far object cannot supply the answer in a single game turn, i.e., it must ask other objects for information to get the answer, and so it sends you a promise rather than a result. It is possible for the resolutions of these promises to occur out-of-order, i.e., the resolution on the second request could get to you after the resolution of the third request has already occurred. In this situation, it will appear that the answer to the second request is newer and more up-to-date than the third request.<br />
<br />
<font color="#000000">In this situation, to ensure you are getting only new information, not stale information, use the acceptOnlyMoreRecentVow utility.</font><br />
<br />
<pre><br />
<br />
def acceptOnlyMoreRecentVow<br />
<br />
</pre><br />
<br />
<font color="#ff0000">code here</font><br />
<br />
This situation, while rare, actually arises in the Marketplace example in the Secure Distributed Computing chapter.<br />
<br />
<font color="#ff0000">something about time, the race construct, timeout construct</font><br />
<br />
====eDesk overwrite copy jewel====<br />
<br />
The following is not really a pattern so much as it is an example of all the more novel (i.e., not-like-Java) elements of <span class="e">''E''</span> playing together. The problem, taken from the eDesk program in the Examples at the end of the book, is this:<br />
<br />
example<br />
<br />
===Data Lock===<br />
<br />
Though <span class="e">''E''</span> is safe from deadlock, in which several objects compete for acquisition to a set of resources, there is a related dilemma that <span class="e">''E''</span> programs can encounter. If two or more "when" clauses wait for each other to resolve before they can resolve themselves, this causes ''data lock''. A complete discussion of data lock and why it is far less of a risk than deadlock is beyond the scope of this book. Briefly, both theory and current experience suggest that data locks are more difficult to create in the wild than deadlocks. Furthermore, when datalocks do occur, they are less likely to freeze up important subsystems on a grand scale: unlike the deadlock, they only choke a few "when" clauses, not a set of "critical sections" which have been named "critical" in thread programming for good reasons. And lastly, datalocks are consistent, reproducible, and therefore fixable, unlike the deadlocks that appear mysteriously when some incredibly arcane race condition occurs.<br />
<br />
Here is a simple though foolish example of datalock. It is the E implementation of the English sentence, "This sentence is false."<br />
<br />
<pre><br />
<br />
def sentence := sentence <- not()<br />
<br />
</pre><br />
<br />
In this construction, the sentence will forever be an unresolved promise. As noted above, the failure of this to resolve will not impede the progress of the rest of the program in the least. And it is very reliable: the unresolvability of the promise will appear the first time you run the program, and the second, and in every debugging pass thereafter.<br />
<br />
At the time of this writing, data lock has been seen only once in the wild. In that instance, a widely used object (call it WUO),contained one piece of mutable state and one piece of immutable state. The object that computed new versions of WUO's mutable state needed the immutable part of the state, and requested the current version of WUO from the owner of the object. Unfortunately, the owner knew that a new version was under construction, and was only sending out promises for WUO until the update was resolved. The solution in this case was to refactor WUO. This resulted in an architecture that was cleaner even by normal object design criteria, without regard to the distributed usage behavior. Insufficient data is yet available to assess how commonly this type of solution will suffice.<br />
<br />
<br />
Next Section: [[Walnut/Secure_Distributed_Computing|Secure Distributed Computing]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Distributed_ComputingWalnut/Distributed Computing2011-08-03T14:11:14Z<p>ThomasLeonard: Fixed example</p>
<hr />
<div>[[Category:Walnut|3]]<br />
<br />
==Distributed Computing==<br />
<br />
Multiple threads form the basis of conventional models of concurrent programming. Remarkably, human beings engage in concurrent distributed computing every day even though people are generally single threaded (there are exceptions: Walter Cronkite routinely listened to one broadcast with one ear, a different broadcast with the other, while simultaneously taking notes on another topic and speaking authoritatively to an audience of millions. But most people, including this author, live single-threaded lives).<br />
<br />
How do we simple creatures pull off the feat of distributed computing without multiple threads? Why do we not see groups of people, deadlocked in frozen tableau around the coffepot, one person holding the sugar waiting for milk, the other holding milk waiting for sugar?<br />
<br />
The answer is, we use a sophisticated computational mechanism known as a ''nonblocking promise''.<br />
<br />
Let us look at a conventional human distributed computation. Alice, the CEO of Evernet Computing, needs a new version of the budget including R&D numbers from the VP of Engineering, Bob. Alice calls Bob: "Could you get me those numbers?"<br />
<br />
Bob jots Alice's request on his to-do list. "Sure thing, Alice, I promise I'll get them for you after I solve this engineering problem."<br />
<br />
Bob has handed Alice a promise for the answer. He has ''not '' handed her the answer. But neither Bob nor Alice sits on their hands, blocked, waiting for the resolution.<br />
<br />
Rather, Bob continues to work his current problem. And Alice goes to Carol, the CFO: "Carol, when Bob gets those numbers, plug 'em into the spreadsheet and give me the new budget,okay?"<br />
<br />
Carol: "No problem." Carol writes Alice's request on her own to-do list, but does not put it either first or last in the list. Rather, she puts it in the conditional part of the list, to be done when the condition is met--in this case, when Bob fulfills his promise.<br />
<br />
Conceptually, Alice has handed to Carol a copy of Bob's promise for numbers, and Carol has handed to Alice a promise for a new integrated spreadsheet. Once again, no one waits around, blocked. Carol ambles down the hall for a contract negotiation, Alice goes back to preparing for the IPO.<br />
<br />
When Bob finishes his calculations, he signals that his promise has been fulfilled; when Carol receives the signal, she uses Bob's fulfilled promise to fulfill her own promise; when Carol fulfills her promise, Alice gets her spreadsheet. A sophisticated distributed computation has been completed so simply that no one realizes an advanced degree in computer science should have been required.<br />
<br />
In this simple example, we see why human beings never get trapped in the thread-based deadlock situations described endlessly in books on concurrent programming. People don't deadlock because they live in a concurrent world managed with a promise-based architecture. And so it is with <span class="e">''E''</span>.<br />
<br />
This chapter on distributed computing is the longest and most challenging part of the book. The Promise Architecture of <span class="e">''E''</span> is very different from the threads, synchronized methods, guarded objects, and RMI of Java. One might expect the Security chapter and its Capability paradigm to be equally new and challenging. But in fact, the implementation of security is embedded so deeply in E's infrastructure that much of the effort merely involves realizing the power inherent in constructs we have already learned. Security with <span class="e">''E''</span> is more a matter of architecture than of coding.<br />
<br />
Distributed computation, however, still requires gritty effort. We start simply, with the eventually operator.<br />
<br />
{{:Walnut/Distributed Computing/Eventually Operator}}<br />
{{:Walnut/Distributed Computing/Promises}}<br />
{{:Walnut/Distributed Computing/Multiway when-catch}}<br />
{{:Walnut/Distributed Computing/Partial Ordering Of Sent Messages}}<br />
{{:Walnut/Distributed Computing/Naming conventions}}<br />
{{:Walnut/Distributed Computing/Testing for Equality in a Distributed System}}<br />
<br />
===Letting When-Catch make a Promise For You===<br />
<br />
As noted in chapter 1 under the Secret Lives of Flow Control Structures, control structures return values. When used as described up to this point, the return value of the when--catch expression has been ignored. In fact, the when-catch expression returns a promise for the last value that the executed clause (the body or catch block) will return.<br />
<br />
Rewriting the calcMilesBeforeEmptyVow using this feature, we get:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def calcMilesBeforeEmptyVow(carRcvr) { <br />
def fuelRemainingVow := carRcvr <- getFuelRemaining() <br />
def mpgVow := carRcvr <- getEfficiency() <br />
return when (fuelRemainingVow, mpgVow) -> { <br />
mpgVow * fuelRemainingVow <br />
}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here the when-catch creates the promise which is returned by the function, and resolution is automatic at the end of the when-catch execution. <br />
So when the promise that the when-catch depends on is resolved the promise it returned will be resolved to the result of the last seqExp in the when clause (i.e. the "mpgVow * fuelRemainingVow" expression).<br />
<br />
Note that we don't need a catch block here. The default behaviour if the promise that the when-catch depends on is smashed is to smash the promise of the when--catch block, which will trigger the catch block in the main program. Normally, you should either report an error or propagate it, so that every error gets reported exactly once.<br />
<br />
Whatever happens, the finally clause has no effect on the resolution of the promise returned by when-catch.<br />
<br />
Warning: A common mistake is to put the "return" statement inside the when block. This will lead to the confusing error message "Ejector must be enabled" (return is a type of "ejector", which causes a function to return a value, but by the time the when block executes, the original function call has already returned).<br />
<br />
===Broken Promise Contagion===<br />
<br />
When chaining promises, what happens if one of the promises in the middle or the far end breaks? The problem that breaks the far promise is propagated down all the promises dependent on it. As a consequence, broken promises work their way through the system in a similar way to exceptions being caught in try/catch blocks.<br />
<br />
===State Transitions for References===<br />
<br />
Having worked our way through near, far, broken, and promised references, let us put all the transitions among these together in a single place. The following diagram shows all the kinds of references <span class="e">''E''</span> distinguishes between, and it shows the two possible transitions:<br />
<br />
<font color="rgb(255, 0, 0)"> [[Image:ref-mech-0.gif|state transition diagram]]</font><br />
<br />
The 2 transitions are:<br />
<br />
* A promise may transition (resolve) into a resolved reference, which can be near or far or broken..<br />
* A far ref may transition to a broken ref.<br />
<br />
That is the complete collection of transitions.<br />
<br />
===Guards for distributed systems===<br />
<br />
Very early in the book, we presented a list of <span class="e">''E''</span> types, including any, integer, float64, etc. In that list were "rcvr", "vow", "pbc" and "near". "pbc" means that the type of the value is required to be "pass by construction". Transparent immutables are generally pbc, and can be passed through this type declaration. Strings, integers, floats, booleans, ConstMaps and ConstLists are all pbc. Objects that are pbc are copied when they are sent, so that even if the object originated on a remote computer, when you get it you can use immediate calls on it. Also, since pbc objects do not embody any code, pbc objects passed across a trust boundary can be used with far fewer security concerns: the pbc object may contain bad data, but it cannot play any tricky games in its execution.<br />
<br />
"Near" means that the value must be local. Promises and far references will not pass the near guard. Anything that passes a near guard can be sent messages with immediate calls.<br />
<br />
At this time, "rcvr" and "vow" have the same algorithmic meaning as "any", but can be used as hints to the programmer about how to interact with the object (a vow should be referenced only eventually until it is resolved; a rcvr should always be referenced only eventually).<br />
<br />
===Nested When-Catch constructs===<br />
<br />
As discussed earlier, we can guarantee the ordering of messages sent from one object to another object. But when a program sends messages to several objects, on different machines, the order in which answers will be received cannot be predicted. Suppose you need to perform a computation involving two far answers, and the algorithm depends on the result from the first answer. You can nest when-catch clauses to await the outcome of the dependency:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def fileRcvr := fileCacheRcvr <- getFile()<br />
when (def exists := fileRcvr <- exists()) -> {<br />
if (exists) {<br />
when (def text := fileRcvr <- getText()) -> {<br />
println(`File has text: $text`)<br />
} catch p2 {println(`Problem with existing file: $p2`)}<br />
} else {println("File does not exist")}<br />
} catch prob {println(`Problem reaching file: $prob`)}<br />
</nowiki><br />
<br />
</pre><br />
<br />
Here, we want to print the text of a farFile, but we want to be sure the file exists first. So we ask the file if it exists, and only after we determine that it does indeed exist do we proceed to get the text.<br />
<br />
As noted earlier, <font color="#FF0000">the "done(variable)" clause </font>of the when-catch construct is actually the declaration of a function and a series of parameters. The reasons for this are beyond the scope of this book, but the operational consequence is that you must use different function names if you have multiple when-catch clauses in the same scope.<br />
<br />
Nested when-catch clauses put the "done" functions into the same scope. In the example here, we gave the inner when-catch "done" function the name "done2" to prevent name collision. We also gave the error-containing variables in the catch clauses different names, e and e2.<br />
<br />
===Live Refs, Sturdy Refs, and URIs===<br />
<br />
Up to this point we have carefully dodged a critical question. How does a program acquire its very first reference to an object on a different computer? In all our examples up to this point, we have always started out with a reference to at least one remote object, and we retrieved other remote objects by asking that object for other objects: for example, we asked a remote carMakerRcvr for a new (remote) carRcvr, and were able to immediately work with the car just like any other remote object. How did we get the reference to the carMakerRcvr in the first place?<br />
<br />
In <span class="e">''E''</span>, the reference to an object can be encoded as a Universal Resource Identifier string, known as a ''uri'' (the familiar url of the Web is a type of uri). This uri string can be passed around in many fashions; one good secure way of passing a uri is to save it as a text file, encrypt and sign it with PGP, and send it in email. If you wish to run a seriously secure distributed <span class="e">''E''</span> system, encrypting the uris is crucial: indeed, the passing of the uris from machine to machine is the main security issue that <span class="e">''E''</span> cannot address for you (and is a problem shared by all security systems, a problem that will diminish with time as secure systems like PGP email are deployed). Other ways uris have been passed in operational <span class="e">''E''</span> systems have been to send the uri over an ssh connection, and (less securely) by reading the uri off over a telephone! If you are using <span class="e">''E''</span> on a local area network and have no security concerns, but are using <span class="e">''E''</span> simply because it is simpler, safer, and more maintainable for distributed computing, the uris can be stored in files on a shared file system and read directly by the programs on different computers as they start up.<br />
<br />
The functions makeURI(object) and objFromURI(uri) detailed in the <span class="e">''E''</span> Quick Reference Card perform the basic transformations you need to hook up objects on multiple computers. These routines use sturdy refs and liverefs in their computations. A sturdyRef is an object that contains an enduring description of where an object can be found; sturdyRefs and URIs are simple transformations of one another. LiveRefs are actual connections to objects that disappear any time a connection goes down. LiveRefs carry the actual traffic in <span class="e">''E''</span> communication. When you request a remote object from another remote object (as in farCarMaker <- ("mercedes")), what you actually get is a liveRef. If you want to continue to connect with that particular car across multiple sessions, you will need to explicitly get a sturdyRef from the car (and the car will have to have an explicit method for granting the sturdyRef. The sturdyref function is an important capability, not one handed out by default).<br />
<br />
Each program that expects to work with remote objects needs to invoke the command<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
introducer.onTheAir() </nowiki><br />
<br />
</pre><br />
<br />
before starting any remote connections, including the making or using of uris. An example of these functions working together can be found in eChat.<br />
<br />
===blockAtTop and continueAtTop===<br />
<br />
E programs never block. They never just sit and wait around for results. However, most programs will toss out some windows, or set up some services, and then desire to wait for someone or some thing to use them. Often, the first version of a program written by a new <span class="e">''E''</span> programmer will set everything up, execute the last line of the program, and then shut down. It is quite disconcerting to watch your windows briefly light up and then disappear, along with the java virtual machine underlying the entire program.<br />
<br />
The command<br />
<br />
<pre><br />
<br />
interp.blockAtTop()<br />
<br />
</pre><br />
<br />
causes the <span class="e">''E''</span> interpreter to wait for requests to come in. The command<br />
<br />
<pre><br />
<br />
interp.continueAtTop()<br />
<br />
</pre><br />
<br />
causes the <span class="e">''E''</span> interpreter to stop waiting. These commands are used in the eChat sample at the end of this chapter: the last line of the program initiates blockAtTop, and continueAtTop is invoked when the user closes his chat window.<br />
<br />
===A bit of Philosophy when using Promises for the first time===<br />
<br />
If a method accepts a promise or far reference as a parameter, the returned value almost certainly cannot be a local object. Why is this? If the computation of the returned object depends on something eventual, the computation will have to wait for an answer, which means the best the object can do for immediately returning something is to return a promise. So a method like getCar(licensePlateVow) has almost certainly violated the naming convention, one way or the other.<br />
<br />
As a consequence of this and other characteristics of promises, beginning E programmers often experience a moment of breathlessness soon after they first try to use them. This moment occurs when the programmer erroneously concludes that, once you let a promise into your system, the program has tumbled down a slippery slope from which there is no recovery. It feels as if you will never be able to have a real value in your hands again; you'll spend the rest of your life making eventual sends, coupled with endless when-catch constructs just to get to the next step.<br />
<br />
The breathlessness can metastasize into a feeling of having lost control of the software: everything is off computing somewhere else and all you have is a bunch of promises. Since <span class="e">''E''</span> never (really, never!) blocks, you can never tell things, "just stop for a moment while I catch my breath and gather up all the values" :-)<br />
<br />
In fact, there are several patterns and tools for getting control of things again. The basic multi-promise when-catch, and the promiseAllResolved and Summoner patterns at the end of this chapter are just a few examples of structures specifically designed to reduce the frequency with which you need when-catch. They allow you to get quickly back into local computation after a distributed action. You really can catch your breath.<br />
<br />
And once the moment of breathlessness passes, you will feel freedom, for you will never have to deal with thread synchronization again; you will never lie awake at night wondering if an unexplored race condition will cause deadlock a few days after the production load level hits your system. <font color="#ff0000">How early can I put this paragraph easily? AHK proposes right after Promises.</font><br />
<br />
===Additional Promise-Related Operations===<br />
<br />
* whenBroken<br />
* E isBroken<br />
* whenResolved Use this when your action will be the same once the promise resolves, regardless of whether it resolves broken or not.<br />
* E isResolved<br />
* E send(object,verb,arguments) This function is identical to the E call() function described earlier, but does an eventual send rather than an immediate call.<br />
* E sendOnly<br />
* E join(a,b) Guarantees sends to result of join are delivered only after messages to a and b have been delivered, sort of a test for equality on-the-fly<br />
<br />
===Under the Covers: Vats and Game Turns===<br />
<br />
<font color="#ff0000">Each vat has a separate event loop, each game turn corresponds to the processing of a single event to conclusion with no interruptions. There are frontend vats, which all share the swing event queue for queuing messages to their event loops, and there are backend queues, each of which has its own separate event queue and runs on a separate thread. Frontend vats have the advantage that they can interact directly with user interface widgets. The initial vat created by default at the start of an E program is a frontend vat. You might want multiple frontend vats if you want to shut down whole subsystems in one fell swoop: you can tell a vat to shut down, and it will terminate all its connections to the outside world, making it available for garbage collection. Have markm review this and tell me what is wrong with this description.</font><br />
<br />
<font color="#ff0000">creating a second frontend vat on a single jvm. creating a backend vat on a jvm</font><br />
<br />
===Example: Alice, Bob, and Carol as Code===<br />
<br />
We started this chapter with a description of a human interaction, with Alice as the CEO of Evernet Computing in search of a new spreadsheet for her IPO preparation. What would that distributed problem look like in code? Though we present only a skeleton of this human operation here, it is perhaps nonetheless informative. It might also be informative, after one has read how to do the example in <span class="e">''E''</span>, to think about how it would be done with threads, in Java or C++. That, however, is left as an exercise for the reader.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#---- Bob Code<br />
<br />
def bobRcvr {<br />
to handleExplosionInNetworkServerRoom() {<br />
# handle the explosion<br />
}<br />
to getCostNumbers() :pbc {<br />
return ["R&D" => 10000]<br />
}<br />
}<br />
<br />
#------------ Carol Code<br />
<br />
def carolRcvr {<br />
to attendMeeting(room, time) {<br />
# attend the meeting<br />
}<br />
to integrateSpreadsheetVow(RDNumbersVow) {<br />
def sheetVow := when (RDNumbersVow) -> {<br />
["Marketing" => 50000] | RDNumbersVow<br />
} catch prob {<br />
println("No numbers!")<br />
prob<br />
}<br />
return sheetVow<br />
}<br />
}<br />
<br />
#--------- Alice Code<br />
<br />
def aliceRcvr {<br />
to prepareIPOVow() {<br />
def RDNumbersVow := bobRcvr <- getCostNumbers()<br />
def spreadsheet := carolRcvr <- integrateSpreadsheetVow(RDNumbersVow)<br />
return when (spreadsheet) -> {<br />
println(`Appendix: Budget Spreadsheet: $\n$spreadsheet`)<br />
} catch prob {<br />
aliceRcvr <- fireSomebody([bobRcvr, carolRcvr])<br />
}<br />
# do other IPO preparations<br />
}<br />
to fireSomebody(candidateRcvrs) {<br />
# get rid of culprit<br />
}<br />
}<br />
<br />
bobRcvr <- handleExplosionInNetworkServerRoom()<br />
carolRcvr <- attendMeeting(1,2)<br />
aliceRcvr <- prepareIPOVow()</nowiki><br />
<br />
</pre><br />
<br />
===Example: minChat version 1===<br />
<br />
In order to focus on the distributed computation features of this chat tool, we have gone to extreme lengths to make the user interface machinery a very short piece of code. Hence, this should properly be called "minChat", because the user interface is so brutally minimal. Even with such minimization, however, the user interface still requires more lines of code than the actual distributed computation!<br />
<br />
The chatController at the bottom of the example is the heart and soul of the computation.<br />
<br />
<code><br />
<br />
<br />
#?? in new vat minChatVat.e-swt<br />
## E sample<br />
#!/usr/bin/env rune<br />
#eChat with minimalist user interface<br />
pragma.syntax("0.9")<br />
def <widget> := <swt:widgets.*><br />
def SWT := <swt:SWT><br />
introducer.onTheAir()<br />
# return the object represented by the URI<br />
def getObjectFromURI(uri) {return introducer.sturdyFromURI(uri).getRcvr()}<br />
<br />
def makeURIFromObject(obj) :String {<br />
# This implementation assumes a non-persistent single incarnation<br />
def [sr, _, _] := identityMgr.makeKnown(obj)<br />
<span style="color:#FF0000">#XXX not a uri if bracketed, bug, markm?</span><br />
def bracketed := introducer.sturdyToURI(sr)<br />
if (bracketed =~ `<@uri>`) {return uri}<br />
return bracketed<br />
}<br />
<br />
def chatController<br />
def chatArea<br />
def chatUI {<br />
to show() {<br />
def frame := <widget:Shell>(currentDisplay)<br />
frame.setText("eChat"); frame.setBounds(30, 30, 600, 300)<br />
def winDisposeListener {to widgetDisposed(event) {interp.continueAtTop()}} <br />
frame.addDisposeListener(winDisposeListener)<br />
bind chatArea := <widget:Text>(frame, <br />
(SWT.getMULTI() | SWT.getWRAP()) | (SWT.getBORDER() | SWT.getV_SCROLL()))<br />
def commandLine := <widget:Text>(frame, SWT.getSINGLE() | SWT.getBORDER())<br />
def enterKeyListener {<br />
to keyPressed (event) {<br />
if (event.getKeyCode() == 27) {<br />
if (commandLine.getText() =~ `@command @argument`) {<br />
commandLine.setText("")<br />
switch (command) {<br />
match == "save" {chatController.save(<file: argument>)}<br />
match == "load" {chatController.load(<file: argument>)}<br />
match == "send" {chatController.send(argument)}<br />
match _ {commandLine.setText("Error. Try save load, or send")}<br />
}<br />
} else {commandLine.setText("Error. Try save, load, or send")}<br />
}<br />
}<br />
match [verb, args] {}<br />
}<br />
commandLine.addKeyListener(enterKeyListener) <br />
def label := <widget:Label>(frame, SWT.getLEFT())<br />
label.setText("save, load, send. No quotes for path. Use Escape to start operation. ")<br />
swtGrid`$frame: $chatArea.X.Y<br />
$label.X<br />
$commandLine.X`<br />
frame.open()<br />
}<br />
to showMessage(initiator, text) {chatArea.append(`$initiator: $text $\n`)}<br />
}<br />
<br />
def friend<br />
bind chatController {<br />
to send(message) {<br />
when (friend<-receive(message)) -> {<br />
chatUI.showMessage("self", message)<br />
} catch prob {chatUI.showMessage("system", "connection lost")}<br />
}<br />
to receive(message) {chatUI.showMessage("friend", message)}<br />
to receiveFriend(friendRcvr) {<br />
bind friend := friendRcvr <br />
chatUI.showMessage("system", "friend has arrived")<br />
}<br />
to save(file) {file.setText(makeURIFromObject(chatController))}<br />
to load(file) {<br />
bind friend := getObjectFromURI(file.getText())<br />
friend <- receiveFriend(chatController)<br />
}<br />
}<br />
chatUI.show()<br />
# In actual code, the following line would not be commented out<br />
# interp.blockAtTop()</nowiki><br />
<br />
</code><br />
<br />
There are only 5 methods in making chat happen: sending a message to the friend, receiving a message from the friend, being informed that the friend has found you (the ''receivedFriend ''method), saving the URI where your friend can find you, and loading the URI that describes where you can find your friend.<br />
<br />
A quick run through can be done by putting the source in a file (file extension ".e-swt", this example uses SWT for user interface) and launching the file twice to get 2 chat windows. In one window, type "save ~/me.minchat" and press the Escape key. This creates a file (in your home directory) that contains a cap: URI describing where your chat session can be found (a chat session that can only be found by someone to whom this file has been given--the location cannot be found or guessed by anyone else). In the other window, type "load ~/me.minchat" and press Escape. In the first window you should see a message pop up that the "friend has arrived". Now in either window type "send hi y'all", and you will see the message appear in both windows.<br />
<br />
In minChat , every time you start up the program, it comes to life with a new uri that must be sent to the friend with whom you wish to chat; the old uri from the previous session is useless. MinChat would be far more useful if you could create a minChat session with Bob, and continue that session even after you have rebooted your computer. We look at building such a persistent chat in the chapter on Persistent Secure Distributed Computing--after first looking at minChat here through the eyes of a security reviewer (or a cybercracker) in the chapter on Secure Distributed Computing.<br />
<br />
===Patterns of Promises===<br />
<br />
====resolveAllVow====<br />
<br />
Note: this is available as '''<import:com.skyhunter.e.net.resolveAllVow>'''<br />
<br />
Suppose you have a computation that cannot be performed until you have received answers from multiple remote objects. Your first thought would be to use a multi-vow when-catch. But further suppose you do not know beforehand how many vows there are (i.e., suppose you have an arbitrary list of promises). In this case neither the multi-vow when-catch construct nor the nested when-catch pattern will work. For this situation, you can use the resolveAllVow utility described here.<br />
<br />
The resolveAllVow utility has another distinction compared to a multi-vow when-catch: whereas the multi-vow activates the catch clause as soon as it hits a broken promise, resolveAllVow sends no resolution until everything in the list is resolved one way or the other. So, even if several of the promises were broken, with resolveAllVow you can be sure that the rest have been fulfilled when the catch clause is activated.<br />
<br />
In this example, we use resolveAllVow to sum a list of contributions. We do not know beforehand how many contributions there are (perhaps thousands), and we want to sum them up even if some of the requests for donations return broken promises.<br />
<br />
E isBroken(obj) does not work. what does?<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Given a List of promises, when all the promises have been resolved,<br />
# resolve the returned vow, either fulfilling it with the list of fulfillments (if<br />
# all the promises were fulfilled) or by smashing the returned promise<br />
# with one of the broken promises (if at least one promise was broken). <br />
def resolveAllVow(promises) {<br />
def [resultVow, resolver] := Ref.promise()<br />
var count := promises.size()<br />
var resolution := promises<br />
var noneBroken := true<br />
if (count == 0) {resolver.resolve(promises)}<br />
for promise in promises {<br />
when (promise) -> {<br />
# success processed in finally clause<br />
} catch prob {<br />
resolution := prob<br />
noneBroken := false<br />
} finally {<br />
count -= 1<br />
if (count == 0) {<br />
if (noneBroken) {<br />
resolver.resolve(resolution)<br />
} else {resolver.smash(resolution)}<br />
}<br />
}<br />
}<br />
return resultVow<br />
}<br />
#now use the promiseAllResolved to sum contributions, where the<br />
#number of contributions is unknown prior to execution<br />
def printTotalContributions(amountsList) {<br />
var total := 0<br />
for each in amountsList {<br />
if (!(Ref.isBroken(each))) {total += each}<br />
}<br />
println(`Total contributions are: $total`)<br />
}<br />
# scaffold contributors: real contributors would be remote Rcvrs<br />
def makeContributer(donation) {<br />
return def contributor { to getDonation() :int {return donation} }<br />
}<br />
def contributorRcvrsList := [makeContributer(5), makeContributer(6)]<br />
def amountsVows := [].diverge()<br />
for each in contributorRcvrsList {<br />
amountsVows.push(each <- getDonation())<br />
}<br />
when (def amounts := resolveAllVow(amountsVows)) -> { <br />
printTotalContributions(amounts)<br />
} catch prob {<br />
#due to the nature of resolveAllVows, in this catch clause<br />
#we are guaranteed everything in amountsVows is resolved to <br />
#either an amount or a broken reference<br />
printTotalContributions(amountsVows)<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The basic behavior of resolveAllVow is this: when initiated, the function takes a count of how many promises there are, then immediately spins off when-catches for all of them. Each time a promise resolves, the count of outstanding promises is decremented. When the counter drops to zero, implying all the promises have been resolved, the single promise initially returned by resolveAllVow is finally resolved.<br />
<br />
====dialogVowMaker====<br />
<br />
Java's standard dialog boxes, found in JOptionPane, are seriously flawed for use in a distributed <span class="e">''E''</span> system: those convenience dialogs are fully blocking. As a consequence, if your computer is part of a distributed computation, and you go home for the night, if a Java dialog box pops up, your machine is effectively offline until you return in the morning. Included in the <span class="e">''E''</span> distribution is a dialog box tool, the dialogVowMaker:<br />
<br />
<font color="#ff0000">code here</font><br />
<br />
====Recursion for send sequencing====<br />
<br />
As discussed earlier, putting a when-catch inside a for loop does not give you any guarantees on which when-catch will activate first: it only guarantees which message is sent first, which is mostly uninteresting. For general-purpose ensured sequencing of resolution, you must use recursion.<br />
<br />
Earlier, we had an example in which we told a list of cars to moveTo the same location. Suppose we wished to ensure that the cars arrived in the order in which they appear in the list:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def moveAllCarsInSequence(carRcvrs,toX,toY) {<br />
var carI := 0<br />
def moveRemainingCars() {<br />
if (carI < carRcvrs.size()) {<br />
def nextCarRcvr := carRcvrs[carI]<br />
carI += 1<br />
def nameVow := nextCarRcvr <- getName()<br />
when (nameVow,nextCarRcvr <- moveTo(toX,toY)) -> {<br />
println(nameVow + " arrived, next car about to start moving")<br />
} catch e {<br />
println(`car died: $e`)<br />
} finally {moveRemainingCars()}<br />
}<br />
}<br />
moveRemainingCars()<br />
}<br />
# scaffold carmaker<br />
def makeCarRcvr(name) {<br />
def carRcvr {<br />
to getName() :String {return name}<br />
to moveTo(x, y) {<br />
#move the car<br />
}<br />
}<br />
return carRcvr<br />
}<br />
<br />
moveAllCarsInSequence([makeCarRcvr("car1"),makeCarRcvr("car2")],3,4) </nowiki><br />
<br />
</pre><br />
<br />
Inside the moveAllCarsInSequence function, we declare the recursive moveRemainingCars function, then simply invoke moveRemainingCars. The function moveRemainingCars tells the next car to move; once that movement has resolved, moveRemainingCars invokes itself once again.<br />
<br />
In this version of moveAllCarsInSequence, if a car is lost (i.e., its promise to move is broken), the recursion continues. If we wanted to abort after a problem occurred, we would simply delete the call to moveRemainingCars() from the finally clause, and place it in the when clause.<br />
<br />
====sendValve====<br />
<br />
As we have seen, it is possible to spin off large numbers of eventual sends in the blink of an eye. In fact, tossing off vast numbers of such sends can sometimes consume a lot of resources for no good purpose. In the eDesk program at the end of the book, it is possible for the user to request the transfer of whole directories full of files. It would be possible for eDesk to initiate transfer of all of those files simultaneously. But the processing bottleneck is probably bandwidth, so initiating them all at once won't get the whole transfer done any faster, and meanwhile each individual file transfer consumes buffer space once initiated. Starting all the transfers at once could actually slow down the transfer if enough buffers thrash virtual memory.<br />
<br />
What you want is a ''valve'', which can be opened and closed depending on the situation. The program can still set up all the operations in a single swoop, but the valve will constrain the number of such operations that are actually active at a given moment. The sendValve below performs this function.<br />
<br />
<pre><br />
<br />
<nowiki>#sendValve. If you have numerous eventual sends to initiate,<br />
# but initiating them all at once would consume vast resources<br />
# and/or would actually slow down processing, queue the actions <br />
# through a valve.<br />
#An ActionTrio is the list of [obj,"verb",[arguments]]<br />
# that can be used in an E send()<br />
#The actions are guaranteed to be initiated in the sequence in<br />
# which they are placed in the valve, though of course there is<br />
# no guarantee as to which will terminate first (unless you have<br />
# special knowledge of such sequencing outside the valve).<br />
#The numSimultaneousAllowed is the number of actions that can<br />
# be run concurrently through this valve.<br />
<br />
# E sample<br />
def makeSendValve (numSimultaneousAllowed) {<br />
var actionQueue := []<br />
var numRunning := 0<br />
def startNext() {<br />
if (!(actionQueue.size()==0)) {<br />
def [actionTrio, resolver] := actionQueue[0]<br />
actionQueue := actionQueue(1, actionQueue.size())<br />
numRunning += 1<br />
def completeVow := E.send(actionTrio[0],actionTrio[1],actionTrio[2])<br />
resolver.resolve(completeVow)<br />
when (completeVow) -> {<br />
} catch prob {<br />
} finally { <br />
numRunning -= 1 <br />
startNext()<br />
}<br />
}<br />
}<br />
def valve {<br />
to makeActionVow(actionTrio) {<br />
def [completeVow, resolver] := Ref.promise()<br />
actionQueue := actionQueue.with([actionTrio, resolver])<br />
if (numRunning < numSimultaneousAllowed) {<br />
startNext()<br />
}<br />
return completeVow<br />
}<br />
}<br />
return valve<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The sendValve utility, if used with numSimultaneousAllowed==1, can also perform the send sequencing function described earlier. However, the earlier general send sequencing pattern is still useful. For example, if the moveAllCarsInSequence operation should abort upon a encountering a broken resolution, this version of sendValve would not give the correct result.<br />
<br />
====Summoning====<br />
<br />
====Transparent forwarder====<br />
<br />
It is possible to have a network of machines in which the machines do not all have direct access to one another. Suppose in the network with machine A, B, and C, A and C cannot form a direct connection because of network topology, but B can reach everything. If A needs a capability on C, we can put a transparent forwarder on B such that A sends its messages to the forwarder on B:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeTransparentForwarder(representedRcvr) {<br />
def forwarder {<br />
match [verb,args] {E.send(representedRcvr,verb,args)}<br />
}<br />
return forwarder<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Create the forwarder on B, and hand the reference to the forwarder to the appropriate object on A. An example can be found in the eDesk example at the end of the book, in which a forwarder is used if the system detects that two of the file servers are unable to directly connect. Note that the "delegate" keyword does not quite work here: delegate generates immediate calls, not eventual sends. So we had to revert to the more general purpose matching process.<br />
<br />
====acceptOnlyMoreRecentVow====<br />
<br />
Suppose you are periodically requesting a particular piece of information from a far object. Suppose the far object cannot supply the answer in a single game turn, i.e., it must ask other objects for information to get the answer, and so it sends you a promise rather than a result. It is possible for the resolutions of these promises to occur out-of-order, i.e., the resolution on the second request could get to you after the resolution of the third request has already occurred. In this situation, it will appear that the answer to the second request is newer and more up-to-date than the third request.<br />
<br />
<font color="#000000">In this situation, to ensure you are getting only new information, not stale information, use the acceptOnlyMoreRecentVow utility.</font><br />
<br />
<pre><br />
<br />
def acceptOnlyMoreRecentVow<br />
<br />
</pre><br />
<br />
<font color="#ff0000">code here</font><br />
<br />
This situation, while rare, actually arises in the Marketplace example in the Secure Distributed Computing chapter.<br />
<br />
<font color="#ff0000">something about time, the race construct, timeout construct</font><br />
<br />
====eDesk overwrite copy jewel====<br />
<br />
The following is not really a pattern so much as it is an example of all the more novel (i.e., not-like-Java) elements of <span class="e">''E''</span> playing together. The problem, taken from the eDesk program in the Examples at the end of the book, is this:<br />
<br />
example<br />
<br />
===Data Lock===<br />
<br />
Though <span class="e">''E''</span> is safe from deadlock, in which several objects compete for acquisition to a set of resources, there is a related dilemma that <span class="e">''E''</span> programs can encounter. If two or more "when" clauses wait for each other to resolve before they can resolve themselves, this causes ''data lock''. A complete discussion of data lock and why it is far less of a risk than deadlock is beyond the scope of this book. Briefly, both theory and current experience suggest that data locks are more difficult to create in the wild than deadlocks. Furthermore, when datalocks do occur, they are less likely to freeze up important subsystems on a grand scale: unlike the deadlock, they only choke a few "when" clauses, not a set of "critical sections" which have been named "critical" in thread programming for good reasons. And lastly, datalocks are consistent, reproducible, and therefore fixable, unlike the deadlocks that appear mysteriously when some incredibly arcane race condition occurs.<br />
<br />
Here is a simple though foolish example of datalock. It is the E implementation of the English sentence, "This sentence is false."<br />
<br />
<pre><br />
<br />
def sentence := sentence <- not()<br />
<br />
</pre><br />
<br />
In this construction, the sentence will forever be an unresolved promise. As noted above, the failure of this to resolve will not impede the progress of the rest of the program in the least. And it is very reliable: the unresolvability of the promise will appear the first time you run the program, and the second, and in every debugging pass thereafter.<br />
<br />
At the time of this writing, data lock has been seen only once in the wild. In that instance, a widely used object (call it WUO),contained one piece of mutable state and one piece of immutable state. The object that computed new versions of WUO's mutable state needed the immutable part of the state, and requested the current version of WUO from the owner of the object. Unfortunately, the owner knew that a new version was under construction, and was only sending out promises for WUO until the update was resolved. The solution in this case was to refactor WUO. This resulted in an architecture that was cleaner even by normal object design criteria, without regard to the distributed usage behavior. Insufficient data is yet available to assess how commonly this type of solution will suffice.<br />
<br />
<br />
Next Section: [[Walnut/Secure_Distributed_Computing|Secure Distributed Computing]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Quasi-Literals_and_Quasi-ParsersWalnut/Ordinary Programming/Quasi-Literals and Quasi-Parsers2011-08-03T11:17:28Z<p>ThomasLeonard: Removed out-of-date comment about bare strings</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Quasi-Literals and Quasi-Parsers===<br />
<br />
E supports ''quasi-parsers''. A quasi-parser allows one to compress large numbers of operations into a succinct notation (a ''quasi-literal'') in a specific problem domain. Writing your own quasi-parsers (which can be done in <span class="e">''E''</span> itself, as the JPanel quasiparser described below was written) is beyond the scope of this book. However, <span class="e">''E''</span> comes with several quasi-parsers built in: a simple quasi-parser, a regular expression quasi-parser, a JPanel quasi-parser for Swing, and a swtGrid quasi-parser for SWT.<br />
<br />
====Simple quasi-parser====<br />
<br />
The default quasi-parser is a text manipulating parser capable of extracting data from strings and constructing new strings. In its simplest form, it is a clean and simple way of constructing strings for printing:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def a := 3<br />
def answerString := `The value a is $a, and a times two is ${2 * a}.`<br />
println(answerString)</nowiki><br />
<br />
</pre><br />
<br />
Here we use a simple quasi-parser to build an output string in a fashion similar to the printf statement in C. Quasi literals are enclosed in back-ticks. A dollar sign denotes the beginning of a description of a value to be inserted at the dollar sign location. If the dollar sign is immediately followed by a variable name, the value of that variable is used. If the dollar sign is followed by an open brace, everything up to the close brace is evaluated to compute the value to be substituted (so you could put "$" inside the braces to put a dollar sign in the string, as well as doing arithmetic as in the above example). Quasi-literals can span multiple lines, in which case the carriage return is part of the structure.<br />
<br />
A more sophisticated use of simple quasi-literals is for pattern matching. Here we parse a sentence:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def line := "By the rude bridge that arched the flood"<br />
if (line =~ `@word1 @{word2} rude @remainder`) {<br />
println(`text matches, word1 = $word1`)<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The string on the left of =~ is compared to the quasi literal on the right, evaluating true if the string can be parsed in conformance with the quasi literal. The "@" asserts that any text can match this part of the string, and the variable declared after the "@" contains that text at the end of the evaluation. The variable "word2" is enclosed in braces to offset it from the word "rude" immediately following it, which would look like part of the variable name without the offset.<br />
<br />
In this example, the minimal string that can get a match would be space-space-"rude ", in which case the data extracted for variables word1, word2, and remainder would all be zero-length strings. As it is, at the end of the evaluation, word1=="By", word2=="the", and remainder == "bridge that arched the flood".<br />
<br />
A single quasi-literal can contain dollar signs as well as "@"'s, in which case the results of the dollar sign evaluations will be included in the matching conditions.<br />
<br />
The '''int''' guard will not convert strings to ints, so to extract an integer from a string, use something like this:<br />
<br />
def line := "The number 5"<br />
def `The number @xString` := line<br />
def x := __makeInt(xString)<br />
# value: 5<br />
<br />
For floating-point numbers, you can use '''<import:java.lang.makeDouble>.parseDouble(...)'''.<br />
<br />
====Regular expression quasi parser====<br />
<br />
The regular expression quasi-parser gives <span class="e">''E''</span> much of the CGI scripting power that Perl and Python share. Since <span class="e">''E''</span> runs on top of a jvm with all the startup time such jvms entail, using <span class="e">''E''</span> for CGI scripts ''per se'' is not recommended. However, if one uses the distributed computing power of <span class="e">''E''</span> to run CGI-like <span class="e">''E''</span> programs as services for a Web server, one can achieve the same effect, and receive a number of bonuses unavailable in Perl and Python. The example Web server written in <span class="e">''E''</span>, shown at the end of the book, was designed with just this thought in mind.<br />
<br />
====JPanel====<br />
<br />
The JPanel quasi-parser processes visually understandable strings into complex window panel layouts for gui applications. It is a most remarkable and useful example of quasi-parsers in action, giving the developer a rather WYSIWYG presentation of his windows. Thus the <span class="e">''E''</span> programmer has no need to resort to the typical inflexible IDE-specific drawing tools that produce code no one can read and absolutely no one can edit. Under the covers, the JPanel uses the GridBagLayout manager to compose the panel, giving it a flexibility comparable to the TK layout system from TCL (which actually inspired the JPanel). Unlike the typical visual layout editors in Java IDEs, the JPanel system is able to define a broad range of ''resizable'' windows simply and intuitively.<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
# define the panels explanation,label, field, okButton, cancelButton, logo<br />
# pad1, pad2, which are label fields before <br />
# this example begins<br />
def composedPanel := <br />
JPanel`$explanation.Y > ><br />
$label $field ><br />
$okButton $cancelButton $pad1.X<br />
V $pad2 $logo`</nowiki><br />
<br />
</pre><br />
<br />
In this layout, the explanation (presumably a textArea) is at the top of the composedPanel, with the label and field left-to-right underneath, and the okButton to the left of the cancelButton/logo area arranged top-to-bottom. This is a layout for a 3-wide, 4-high grid of cells, though some the panes fill multiple cells, and the rules for which cells grow are sophisticated, as described next:<br />
<br />
The ".Y" says that the explanation should soak up any extra vertical space. The ".X" says the field should soak up any extra horizontal space. The two ">" symbols say that the explanation should span all three of the columns of this pane. The field fills two horizontal cells as denoted by the ">" which follows it. The "V" in the lower lefthand corner says that the okButton should fill two vertical cells.<br />
<br />
When this pane is part of a resizable window, enlarging vertically makes the explanation larger. Enlarging the window horizontally enlarges the field but not the label. Both the cancel button and the okButton should remain the same size regardless of resizing since the extra space is being soaked up elsewhere.<br />
<br />
If several elements have ".Y", the extra vertical space is divided evenly among them; similarly fields with ".X" share extra horizontal space.<br />
<br />
The space characters used to separate the elements of this layout have no meaning to the quasi-parser; we have used the space to create a visual representation of the layout that makes it easy to see the layout even though this is just code.<br />
<br />
It is not possible to lay out all possible compositions with a single JPanel, but JPanels can dramatically reduce the nesting of panels compared to Java applications, while making the layout visually clear in the code itself. And of course, you can always place JPanel-laid-out panels inside of other JPanel layouts. The result is tremendously more compact, easier to understand, and easier to maintain than the result of nesting large numbers of Swing Box layouts.<br />
<br />
A similar quasi-parser, the swtGrid, is included for layout of SWT panels. The main difference, as shown in later example code, is that the swtGrid requires a first entry that is the parent panel for the laid out components, e.g.<br />
<br />
def label := <widget:makeLabel>(frame, SWT.getLEFT())<br />
swtGrid`$frame: $chatArea.X.Y<br />
$label.X<br />
$commandLine.X`<br />
<br />
<span class="note" style="color:red">Improve this discussion</span><br />
<br />
====SQL====<br />
<br />
The SQL quasi-parser can be used to execute SQL statements and queries. Many languages use simple string substitution to build SQL queries, but this opens the risk of SQL injection attacks, where the user (attacker) supplies input to a query that is misinterpreted as part of the SQL statement. Using a quasi-parser, E prevents this possibility. For example, we don't have to worry about the quote character in this user's name:<br />
<br />
def name := "O'No! $@?"<br />
sql`INSERT INTO users (userName, karma) VALUES ($name, 0)`<br />
<br />
For details, see the [[SQL]] page.</div>ThomasLeonardhttp://wiki.erights.org/wiki/User:ThomasLeonardUser:ThomasLeonard2011-06-29T08:11:47Z<p>ThomasLeonard: SAM</p>
<hr />
<div>I'm using E for two separate projects:<br />
<br />
* At [http://www.it-innovation.soton.ac.uk/ IT Innovation], for some of our experimental work on service oriented architectures.<br />
* At [http://0install.net/ebox.html 0install.net], as a demonstrator showing how to use 0install to run sandboxed applications with distributed dependencies.<br />
<br />
I've also made [[SAM]] - a tool for modelling the way capabilities can propagate in capability systems.<br />
<br />
== Branches ==<br />
<br />
I publish my patches to [http://gitorious.org/~tal-itinnov/repo-roscidus/it-innovation my E Git repository]. The '''next''' branch generally contains things I consider ready for merging into the E svn repository.<br />
<br />
Other patches/branches:<br />
<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-October/013648.html Make CapTP shutdown when its vat is shutdown] (on next).<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-September/013620.html Split Scope] into Scope (internal data structure for the E interpreter, including local variables, etc) and EEnv (simpler structure exposed to E code, replacing safeScope, etc). This avoids the need to tame access to these objects and hopefully makes the code easier to read.<br />
* Various possible optimisations are on the '''compiler''' branch (these mostly have only a small benefit or don't work fully; otherwise I push them to next). These optimisations work for both the current E interpreter and for a possible future E compiler. There is also a very old wip-compiler branch that actually does compile E to JVM bytecode. However, it turned out that the major performance problems were elsewhere.</div>ThomasLeonardhttp://wiki.erights.org/wiki/SAMSAM2011-06-15T08:40:02Z<p>ThomasLeonard: </p>
<hr />
<div>The [http://serscis.eu/sam/ SERSCIS Access Modeller] (SAM) takes a model of a system (e.g. a set of objects within a computer program or a set of machines on a network) and attempts to verify certain security properties about the system, by exploring all the ways access can propagate through the system. For example, it could prove that a web-server's logs can never be deleted except by the logging system or the administrator.<br />
<br />
It is designed to handle dynamic systems (e.g. systems containing factories which may create new objects at runtime) and systems where behaviour of some of the objects is unknown or not trusted.<br />
<br />
It is greatly inspired by [[Scollar]], but extends it by:<br />
<br />
* Using a Java-like syntax for expressing behaviour, which is hopefully more natural for programmers.<br />
* Considering multiple contexts (e.g. so that objects created by a factory for client A can be kept separate from objects created by the same factory for client B).<br />
<br />
SAM is Open Source.<br />
<br />
== Example ==<br />
<br />
This factory.sam file defines known/trusted behaviour for a Factory and then sets up a scenario where the factory has two clients (objects with references to the factory). The clients and the Task objects created by the factory all have unknown behaviour, but are assumed to be running on a capability platform (and therefore confined):<br />
<br />
/* Behaviour */<br />
<br />
class Factory {<br />
public Task newInstance() {<br />
Task task = new Task();<br />
return task;<br />
}<br />
}<br />
<br />
/* Config */<br />
<br />
initialObject("clientA", "Client").<br />
initialObject("otherClients", "Client").<br />
initialObject("factory", "Factory").<br />
<br />
field("clientA", "ref", "factory").<br />
field("otherClients", "ref", "factory").<br />
<br />
initialInvocation("clientA", "a").<br />
initialInvocation("otherClients", "other").<br />
<br />
Processing this file with sam ('''sam factory.sam''') produces this graph showing the limits of how these objects may become connected:<br />
<br />
[[Image:sam-factory.png]]<br />
<br />
This shows that the tasks created by clientA (aggregated as aTask) may get access to and invoke the factory. However, clientA cannot get access to any of the other clients or their tasks.<br />
<br />
[[Category:Formal Reasoning]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/SAMSAM2011-06-15T08:39:20Z<p>ThomasLeonard: /* Example */</p>
<hr />
<div>The [http://serscis.eu/sam/ SERSCIS Access Modeller] (SAM) takes a model of a system (e.g. a set of objects within a computer program or a set of machines on a network) and attempts to verify certain security properties about the system, by exploring all the ways access can propagate through the system. For example, it could prove that a web-server's logs can never be deleted except by the logging system or the administrator.<br />
<br />
It is designed to handle dynamic systems (e.g. systems containing factories which may create new objects at runtime) and systems where behaviour of some of the objects is unknown or not trusted.<br />
<br />
It is greatly inspired by [[Scollar]], but extends it by:<br />
<br />
* Using a Java-like syntax for expressing behaviour, which is hopefully more natural for programmers.<br />
* Considering multiple contexts (e.g. so that objects created by a factory for client A can be kept separate from objects created by the same factory for client B).<br />
<br />
SAM is Open Source.<br />
<br />
== Example ==<br />
<br />
This factory.sam file defines known/trusted behaviour for a Factory and then sets up a scenario where the factory has two clients (objects with references to the factory). The clients and the Task objects created by the factory all have unknown behaviour, but are assumed to be running on a capability platform (and therefore confined):<br />
<br />
/* Behaviour */<br />
<br />
class Factory {<br />
public Task newInstance() {<br />
Task task = new Task();<br />
return task;<br />
}<br />
}<br />
<br />
/* Config */<br />
<br />
initialObject("clientA", "Client").<br />
initialObject("otherClients", "Client").<br />
initialObject("factory", "Factory").<br />
<br />
field("clientA", "ref", "factory").<br />
field("otherClients", "ref", "factory").<br />
<br />
initialInvocation("clientA", "a").<br />
initialInvocation("otherClients", "other").<br />
<br />
Processing this file with sam ('''sam factory.sam''') produces this graph showing the limits of how these objects may become connected:<br />
<br />
[[Image:sam-factory.png]]<br />
<br />
This shows that the tasks created by clientA (aggregated as aTask) may get access to and invoke the factory. However, clientA cannot get access to any of the other clients or their tasks.</div>ThomasLeonardhttp://wiki.erights.org/wiki/File:Sam-factory.pngFile:Sam-factory.png2011-06-15T08:37:53Z<p>ThomasLeonard: </p>
<hr />
<div></div>ThomasLeonardhttp://wiki.erights.org/wiki/SAMSAM2011-06-15T08:36:52Z<p>ThomasLeonard: </p>
<hr />
<div>The [http://serscis.eu/sam/ SERSCIS Access Modeller] (SAM) takes a model of a system (e.g. a set of objects within a computer program or a set of machines on a network) and attempts to verify certain security properties about the system, by exploring all the ways access can propagate through the system. For example, it could prove that a web-server's logs can never be deleted except by the logging system or the administrator.<br />
<br />
It is designed to handle dynamic systems (e.g. systems containing factories which may create new objects at runtime) and systems where behaviour of some of the objects is unknown or not trusted.<br />
<br />
It is greatly inspired by [[Scollar]], but extends it by:<br />
<br />
* Using a Java-like syntax for expressing behaviour, which is hopefully more natural for programmers.<br />
* Considering multiple contexts (e.g. so that objects created by a factory for client A can be kept separate from objects created by the same factory for client B).<br />
<br />
SAM is Open Source.<br />
<br />
== Example ==<br />
<br />
This factory.sam file defines known/trusted behaviour for a Factory and then sets up a scenario where the factory has two clients (objects with references to the factory). The clients and the Task objects created by the factory all have unknown behaviour, but are assumed to be running on a capability platform (and therefore confined):<br />
<br />
/* Behaviour */<br />
<br />
class Factory {<br />
public Task newInstance() {<br />
Task task = new Task();<br />
return task;<br />
}<br />
}<br />
<br />
/* Config */<br />
<br />
initialObject("clientA", "Unknown").<br />
initialObject("otherClients", "Unknown").<br />
initialObject("factory", "Factory").<br />
<br />
field("clientA", "ref", "factory").<br />
field("otherClients", "ref", "factory").<br />
<br />
initialInvocation("clientA", "a").<br />
initialInvocation("otherClients", "other").<br />
<br />
Processing this file with sam ('''sam factory.sam''') produces this graph showing the limits of how these objects may become connected:<br />
<br />
[[Image:sam-factory.png]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/SAMSAM2011-06-15T08:32:24Z<p>ThomasLeonard: </p>
<hr />
<div>The [http://serscis.eu/sam/ SERSCIS Access Modeller] (SAM) takes a model of a system (e.g. a set of objects within a computer program or a set of machines on a network) and attempts to verify certain security properties about the system, by exploring all the ways access can propagate through the system. For example, it could prove that a web-server's logs can never be deleted except by the logging system or the administrator.<br />
<br />
It is designed to handle dynamic systems (e.g. systems containing factories which may create new objects at runtime) and systems where behaviour of some of the objects is unknown or not trusted.<br />
<br />
It is greatly inspired by [[Scollar]], but extends it by:<br />
<br />
* Using a Java-like syntax for expressing behaviour, which is hopefully more natural for programmers.<br />
* Considering multiple contexts (e.g. so that objects created by a factory for client A can be kept separate from objects created by the same factory for client B).<br />
<br />
SAM is Open Source.</div>ThomasLeonardhttp://wiki.erights.org/wiki/ELoaderELoader2011-04-11T09:49:39Z<p>ThomasLeonard: /* Using multiple modules */</p>
<hr />
<div>When you run a .e or (.updoc) file, it is given a loader called '''<this>''' which can be used to import .emaker files from the same directory (or from a sub-directory).<br />
<br />
For example, create a new directory and add two files. main.e is the main program:<br />
<br />
# main.e<br />
def makeMyObject := <this:makeMyObject><br />
def obj := makeMyObject()<br />
...<br />
<br />
makeMyObject.emaker is a support file:<br />
<br />
# makeMyObject.emaker<br />
def makeMyObject() {<br />
...<br />
}<br />
<br />
Files imported using '''<this>''' also have the loader in their environment, and can import further files using it.<br />
<br />
An ELoader also allows access to the raw files (use '''<this>.getRoot()''' to get a read-only directory object). This is useful for accessing icons, documentation, etc.<br />
<br />
= Using multiple modules =<br />
<br />
If a program is made up of multiple modules, a separate loader can be created for each one. Each module is given its own loader as '''<this>''', as well as loaders for its dependencies. For example, here we have two modules. "prog" is a program that depends on a library called "libfoo".<br />
<br />
def makeTraceln := <unsafe:org.erights.e.elib.debug.makeTraceln><br />
def makeELoader := <elang:interp.ELoaderAuthor>(makeTraceln)<br />
<br />
def <libfoo> := makeELoader(<file:.../libfoo>, ["this__uriGetter" => <libfoo>], "libfoo$")<br />
def <prog> := makeELoader(<file:.../prog>, ["this__uriGetter" => <prog>, => <libfoo>], "prog$")<br />
<br />
def app := <prog:makeApplication>(...)<br />
<br />
* Within libfoo, the library can load other emakers from itself using e.g. '''<this:somefile>'''.<br />
* Within prog, a file can load other emakers from prog using e.g. '''<this:somefile>''', or from libfoo using '''<libfoo:somefile>'''.<br />
<br />
You could also wrap the '''<libfoo>''' given to prog to only expose its public API.<br />
<br />
This avoids the need to set classpath and avoids conflicts between different packages. For example, you could depend on two libraries which, internally, require different versions of libfoo. Each library would see the correct version of libfoo as '''<libfoo>'''.<br />
<br />
In future, it is expected that a separate ''injector'' library will take care of selecting and downloading modules and wiring them together.<br />
<br />
See [http://0install.net/ebox.html 0install.net's EBox demo] for a working example.<br />
<br />
= See also =<br />
<br />
* http://switchb.org/darcs/e-modules/<br />
* http://www.eros-os.org/pipermail/e-lang/2010-February/013416.html -- original discussion</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Objects_and_FunctionsWalnut/Ordinary Programming/Objects and Functions2011-02-22T14:35:16Z<p>ThomasLeonard: Slots</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Objects and Functions===<br />
<br />
As noted earlier, if the file is to use the Swing gui toolkit, it must have a suffix of ".e-awt". If the file is to use the SWT gui toolkit, it must have a suffix of ".e-swt". If the file will run headless, it should be placed in a file with suffix ".e".<br />
<br />
But first, we need to declare what version of E we're using here.<br />
<pre><br />
? pragma.syntax("0.9")<br />
</pre><br />
<br />
====Functions====<br />
<br />
A basic function looks like this:<br />
<br />
<pre># E sample<br />
def addNumbers(a,b) {<br />
return a + b<br />
}<br />
# Now use the function<br />
def answer := addNumbers(3,4)<br />
</pre><br />
<br />
You can nest the definitions of functions and objects inside other functions and objects, giving you functionality comparable to that of inner classes in Java. Nested functions and objects play a crucial role in <span class="e">''E''</span>, notably in the construction of objects as described shortly.<br />
<br />
A parameterless function must still have an open/close paren pair. Calls to parameterless functions must also include the parens.<br />
<br />
Functions can of course call themselves recursively, as in<br />
<br />
<pre># E sample<br />
def factorial(n) {<br />
if (n == 0) {<br />
return 1<br />
} else {<br />
return n * factorial(n-1)<br />
}<br />
}<br />
</pre><br />
<br />
====Dynamic "type checking" and Guards====<br />
<br />
<span class="e">''E''</span> guards perform many of the functions usually thought of as type checking, though they are so flexible, they also work as concise assertions. Guards can be placed on variables, parameters, and return values.<br />
<br />
Guards are not checked during compilation. They are checked during execution, and will throw exceptions if the value cannot be coerced to pass the guard. Guards play a key role in protecting the security properties when working with untrusted code, as discussed in Secure Distributed Computing.<br />
<br />
The available guards include the items below. Some of them are typical types (String, int). Others are used most often in distributed programming, and are explained later in the book. A detailed explanation of all the things you can do with guards is postponed to the [[Walnut/Additional_Features|Additional Features]] chapter.<br />
<br />
* int<br />
* char<br />
* float64<br />
* boolean<br />
* String<br />
* void<br />
* notNull<br />
* nullOk<br />
* near<br />
* vow<br />
* rcvr<br />
* pbc<br />
* Data<br />
* Java classes<br />
* <span class="e">''E''</span> interfaces<br />
* subranges and more complex expressions<br />
<br />
Here are some quick examples of guards being declared:<br />
<br />
<pre># E sample<br />
# guarding a variable<br />
def title :String := "abc"<br />
# guarding a parameter, and a return value. Note the guard on the <br />
# return value is part of the def line for the function.<br />
def reciprocal(x :float64) :float64 {<br />
return 1 / x<br />
}<br />
</pre><br />
<br />
Different people use different strategies about how much type checking/guard information to include in their programs. In this book, the general style is to use guards sparingly, as might be typical in a rapid prototyping environment. One place where guards must be used with rigor is in the objects on the boundaries between trust realms, in security aware applications; see the Powerbox pattern in the [[Walnut/Secure_Distributed_Computing|Secure Distributed Programming section]] for an important example.<br />
<br />
====Objects====<br />
<br />
Objects, and object constructors, look considerably different in <span class="e">''E''</span> than in Java or C++. We will start our exploration of objects with a simple singleton object.<br />
<br />
=====A Singleton Object=====<br />
<br />
Objects, functions, and variables are defined with the keyword "def"; all of these can be passed as arguments in parameter lists. Methods on an object, in contrast, are defined with the keyword "to":<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def origin {<br />
to getX() {return 0}<br />
to getY() {return 0}<br />
}<br />
# Now invoke the methods<br />
def myY := origin.getY()<br />
</nowiki><br />
<br />
</pre><br />
<br />
Like functions, methods require a parenthesis pair even if there are no arguments. ''(But, Python programmers beware, methods are not functions. Methods are just the public hooks to the object that receive messages; functions are standalone objects)''.<br />
<br />
When invoking the method, the object name and the method called are separated by a dot.<br />
<br />
=====Stateful objects and object constructors=====<br />
<br />
The "class" concept in Java is used to achieve multiple goals. In <span class="e">''E''</span>, these goals are factored out in a different way. For example, Java classes supply a place to put constructors, which have a special syntax unique to constructors. In <span class="e">''E''</span>, objects are constructed by ordinary functions.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Point constructor<br />
def makePoint(x,y) {<br />
def point {<br />
to getX() {return x}<br />
to getY() {return y}<br />
to makeOffsetPoint(offsetX, offsetY) {<br />
return makePoint(x + offsetX, y + offsetY)<br />
}<br />
to makeOffsetPoint(offset) {<br />
return makePoint(x + offset, y + offset)<br />
}<br />
} <br />
return point<br />
}<br />
# Create a point<br />
def origin := makePoint(0,0)<br />
# get the y value of the origin<br />
def y := origin.getY()</nowiki><br />
<br />
</pre><br />
<br />
Inside the function makePoint, we define a point and return it. As demonstrated by the makeOffsetPoint method, the function (makePoint) can be referenced from within its own body. Also note that you can overload method names (two versions of makeOffsetPoint) as long as they can be distinguished by the number of parameters they take.<br />
<br />
The (x, y) passed into the function are not ephemeral parameters that go out of existence when the function exits. Rather, they are true variables (implicitly declared with "def" ), and they persist as long as any of the objects that use them persist. Since the point uses these variables, x and y will exist as long as the point exists. This saves us the often tedious business in Java of copying the arguments from the parameter list into instance variables: x and y already are instance variables.<br />
<br />
We refer to an object-making function such as makePoint as a "Maker". Let us look at a more serious example, with additional instance variables:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(var name) {<br />
var x := 0<br />
var y := 0<br />
def car {<br />
to moveTo(newX,newY) {<br />
x := newX<br />
y := newY<br />
}<br />
to getX() {return x}<br />
to getY() {return y}<br />
to setName(newName) {name := newName}<br />
to getName() {return name}<br />
} <br />
return car<br />
}<br />
# Now use the makeCar function to make a car, which we will move and print<br />
def sportsCar := makeCar("Ferrari")<br />
sportsCar.moveTo(10,20)<br />
println(`The car ${sportsCar.getName()} is at X location ${sportsCar.getX()}`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
Inside the Maker, we create the instance variables for the object being made (x and y in this example), then we create the object (car). Note that the variable "name", passed into the function, is explicitly declared with "var", so that it can be altered later; in this case, it is reassigned in the setName() method.<br />
<br />
=====Self-referencing objects=====<br />
<br />
Sometimes in the body of an object you wish to refer to the object itself. A keyword like "this" is not required. The name given to the object is in scope in the body of the object, so just use it:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
var x := 0<br />
var y := 0<br />
def </nowiki>car {<br />
to moveDistance(newX,newY) {car.moveTo(x + newX, y + newY)}<br />
# ....define other methods including moveTo as above ....<br />
}<br />
return car<br />
}<br />
<br />
</pre><br />
<br />
What if you need to reference the object during the object's construction, i.e., during the creation of the instance variables that precedes the definition of the object itself? In the below example, we give the car a weatherReportRadio that is supposed to alert the car to changing weather conditions. This radio requires, as a parameter during its construction, the car it will be alerting. So the radio needs the car during radio construction, and the car needs the radio during car construction.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeRadio(car) {<br />
# define radios<br />
}<br />
def makeCar(name) { <br />
var x := 0 <br />
var y := 0<br />
# using def with no assignment<br />
def car<br />
def myWeatherRadio := makeRadio(car)<br />
bind car {<br />
to receiveWeatherAlert() {<br />
# ....process the weather report....<br />
# myWeatherRadio.foo(...)<br />
} <br />
to getX() {return x} <br />
to getY() {return y}<br />
# ....list the rest of the car methods....<br />
}<br />
return car<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here, we do a "def" of the car with no assignment, then we use the car, then we do a "bind" of the car which binds a value to the car. This looks and behaves like a "forward reference" from C. Under the covers, the statement "def car" creates a ''promise'' for the car, and the ''bind'' statement ''fulfills'' the promise. We discuss promises in greater depth in the [[Walnut/Distributed_Computing|Distributed Computing]] chapter, where they play a key role.<br />
<br />
=====Secret Life of Functions, Multiple Constructors and "Static Methods"=====<br />
<br />
Before we can talk about multiple constructors and the static-method-like behavior in <span class="e">''E''</span>, it is time to reveal the truth about <span class="e">''E''</span> functions. They are in fact simple objects with a single method, the "run" method, that is invoked by default if no other method is explicitly designated. For example, the following square function<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square(x) {return x*x}</nowiki><br />
<br />
</pre><br />
<br />
is really syntactic shorthand for<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square {<br />
to run(x) {return x*x}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
In the second one, the run() method is explicitly defined. Using this explicit form in a Maker function, you can define multiple constructors, discriminated by the number of parameters they receive. Similarly, by adding methods to the Maker other than "run" methods, you get other "static methods". In the example below, we have a queue Maker with 2 constructors and a non-constructor method. The one-argument constructor requires an initial capacity; the no-argument constructor supplies an initial capacity of 10.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeQueue {<br />
to run(initialCapacity) {<br />
# ....create a queue object with the specified initial capacity....<br />
}<br />
to run() {return makeQueue(makeQueue.getDEFAULT_CAPACITY())}<br />
to getDEFAULT_CAPACITY() {return 10}<br />
}<br />
# Now use both constructors<br />
def queue1 := makeQueue(100)<br />
def queue2 := makeQueue()<br />
println(`default capacity is: ${makeQueue.getDEFAULT_CAPACITY()}`)</nowiki><br />
<br />
</pre><br />
<br />
Note also that one can use methods such as getDEFAULT_CAPACITY() to achieve the same effect as Java achieves with public static final variables.<br />
<br />
====Polymorphism====<br />
<br />
<span class="e">''E''</span> enables polymorphism through method name matching. In this example, we move both a car and an airplane to a new location using a single common piece of code:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
def car {<br />
to moveTo(x, y) {<br />
# move the car<br />
}<br />
# other methods<br />
}<br />
return car<br />
}<br />
def makeJet(name) {<br />
def jet { <br />
to moveTo(x, y) { <br />
# move the jet, very different code from the code for car <br />
} <br />
# other methods <br />
} <br />
return jet<br />
}<br />
def vehicles := [makeCar("car"), makeJet("jet")]<br />
for each in vehicles {<br />
each.moveTo(3,4)<br />
} </nowiki><br />
<br />
</pre><br />
<br />
====Extends and Delegation====<br />
<br />
An object can refer calls to itself to another object (a "super-object", built by the "super-constructor", faintly similar to the way one uses superclasses in Java) using the ''extends'' keyword: <span class="note" style="color:red">think of better example</span><br />
<br />
<pre><br />
<br />
<nowiki>? def makePoint(x, y) { <br />
> def point { <br />
> to getX() {return x} <br />
> to getY() {return y}<br />
> to getMagnitude() {return (x*x + y*y)**0.5} <br />
> }<br />
> return point<br />
> } <br />
# value: <makePoint> <br />
<br />
? def makePoint3D(x,y,z) { <br />
> def point3D extends makePoint(x,y) { <br />
> to getZ() {return z} <br />
> to getMagnitude() {<br />
> def xy := super.getMagnitude()<br />
> return (z*z + xy*xy)**0.5<br />
> } <br />
> }<br />
> return point3D <br />
> } <br />
# value: <makePoint3D><br />
<br />
? def place := makePoint3D(1,2,3)<br />
# value: <point3D><br />
<br />
? def x := place.getX()<br />
# value: 1<br />
<br />
? def z := place.getZ()<br />
# value: 3</nowiki><br />
<br />
</pre><br />
<br />
Here makePoint3D acts as an extension of makePoint. Inside the ''extends'' clause, we run the makePoint constructor to create the Point upon which the Point3D will be built. This specially constructed point is referred to in the point3D definition as "super"; you can see super being used in the getMagnitude method.<br />
<br />
Using ''extends'' as described above follows the ''delegation'' pattern. Delegation is a simple pattern of object composition in which an object says, "if another object calls me with a method that I don't have defined here, just route the message to this other object, and send the result back to the caller." Delegation is similar to inheritance, but it is conceptually simpler.<br />
<br />
====Extends and Full Inheritance====<br />
<br />
Some experts consider inheritance to be a dangerous feature. A discussion of the pros and cons of inheritance is beyond the scope of this book. However, none of the full-blown examples in this book actually use full inheritance. Delegation, via the simple ''extends'' keyword plus polymorphism serve most of the purposes for which inheritance was intended, and is used everywhere here.<br />
<br />
Having said that, there are times and places where full inheritance is the right answer. The ''extends'' keyword is also used, with one additional convention, to support such full inheritance. In inheritance, the "self" to which a super-object refers is the sub-object of which it is a part, so that the super-object can use methods in the sub-object:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def makeVehicle(self) {<br />
def vehicle {<br />
to milesTillEmpty() {<br />
return self.milesPerGallon() * self.getFuelRemaining()<br />
}<br />
}<br />
return vehicle<br />
}<br />
<br />
def makeCar() {<br />
var fuelRemaining := 20<br />
def car extends makeVehicle(car) {<br />
to milesPerGallon() {return 19}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return car<br />
}<br />
<br />
def makeJet() {<br />
var fuelRemaining := 2000<br />
def jet extends makeVehicle(jet) {<br />
to milesPerGallon() {return 2}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return jet<br />
}<br />
<br />
def car := makeCar()<br />
println(`The car can go ${car.milesTillEmpty()} miles.`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
As seen in the example, the super-object constructor specifies a parameter, "self", which can be used to refer to the sub-object. The sub-object includes itself in the the call to the super-object constructor, thus becoming "self".<br />
<br />
====E Interfaces====<br />
<br />
You can define an interface like this:<br />
<br />
interface Foo {<br />
}<br />
<br />
def foo implements Foo {<br />
}<br />
<br />
foo :Foo<br />
<br />
The interface body can contain method signatures (without bodies).<br />
<br />
When an object is declared as "implements Foo", Foo acts as a "rubber-stamping" auditor, which marks the object as implementing the interface (whether or not it implements any of the methods defined in the interface). When Foo is used as a guard, it checks that the object was stamped by the auditor.<br />
<br />
This allows your module to give out objects and recognise them when they are given back later. However, this cannot be used for security purposes because the interface (Foo) cannot be kept secret. This is because when a non-Foo object is checked with the Foo guard, object.__conformTo(Foo) is called. <br />
<br />
The two functions of Foo (guard and auditor) may be split up using this syntax:<br />
<br />
interface FooGuard guards FooAuditor { }<br />
<br />
def foo implements FooAuditor { ... }<br />
<br />
foo :FooGuard<br />
<br />
This allows the guard to be given out freely while the auditor is closely held, preventing others from creating fake Foo objects but allowing anyone to check that a given object is a genuine Foo.<br />
<br />
Presumably, you could also implement a public auditor that actually performed some kind of check on an object, and then used the rubber-stamping auditor to stamp it if it passed the checks [how?].<br />
<br />
The interface construct is likely to change in future[http://www.eros-os.org/pipermail/e-lang/2010-February/013432.html].<br />
<br />
====General method name matching and E.call()====<br />
<br />
Delegation with extends does a straight pass-through of the method call. It is possible to intercept collections of calls before delegating them, using ''match''. In this example, we count the number of calls made to a car:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCalledCountCar(name) {<br />
def myCar := makeCar(name) <br />
var myCallCount := 0<br />
def car {<br />
to getCallCount() {return myCallCount}<br />
match [verb,args] {<br />
myCallCount += 1<br />
E.call(myCar,verb,args)<br />
}<br />
}<br />
return car<br />
} </nowiki><br />
<br />
</pre><br />
<br />
In "match[verb,args]", the verb is a string specifying the name of the method being called, and the args is a list of arguments. If the car is called with a method that is not defined in a "to" statement, the name of the method and the arguments are bound to the variables inside the square brackets. We then increment the call count, and finally forward the message using the E.call function. E.call(...) takes as arguments the target object for the action, the name of the method to call, and the list of arguments for the method to invoke. You can manually use E.call() like this:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def car := makeCar("mercedes")<br />
E.call(car, "moveTo", [3,4])<br />
# which is equivalent to<br />
car.moveTo(3,4)</nowiki><br />
<br />
</pre><br />
<br />
In this example, the elements for the argument list are placed in square brackets to form an <span class="e">''E''</span> ConstList, described later in this chapter.<br />
<br />
The match construct is useful for making "adapters" when interfacing to Java. Here we build a singleton object that can be used anywhere a java.awt.event.MouseListener would be used; the match clause is used to absorb and discard events in which we are not interested:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def mouseListener {<br />
to mouseClicked(event) {<br />
# process the event<br />
}<br />
match [verb,args] {}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
This general purpose matching is also useful in security applications when building facets and revocable capabilities, as described in the chapter on Secure Distributed Computing.<br />
<br />
====Edoc, the <span class="e">''E''</span> equivalent of JavaDoc====<br />
<br />
E supports the construction of javadoc-style comments that can be postprocessed into HTML documentation. For this purpose, the "/** ... */" comment format has been specially reserved; comments of this style can only appear in front of a function/object definition (a "def" statement), or in front of an object method definition (a "to" statement):<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
/**<br />
* Add 2 numbers together.<br />
* <p><br />
* Currently works with any objects that support the "plus" method<br />
*<br />
* @param a the first number. <br />
* @param b the second number<br />
* @return the result of adding. <br />
*/<br />
def adder(a, b) {return a + b}</nowiki><br />
<br />
</pre><br />
<br />
For more information on how to generate Edoc HTML from your <span class="e">''E''</span> programs, see the [[Walnut/Additional_Features|Additional Features]].<br />
<br />
====Under the covers: Everything is an Object====<br />
<br />
We have already discussed the fact that functions are really objects with a single method, "run". Functions-as-objects have one practical consequence that would be surprising in the absence of understanding. You cannot create two functions with different numbers of parameters and have them overloaded:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def times2(a) {return a * 2}<br />
def compute(a,b) {<br />
def times2(c,d) {return (c + d) * 2}<br />
# ....do computation...<br />
# The following line will throw an exception<br />
def answer := times2(a)<br />
return answer<br />
}</nowiki><br />
<br />
</pre><br />
<br />
<font color="#FF0000">This would throw an exception because the inner definition of the function-like object times2 completely shadows the outer times2.</font><br />
<br />
Not only functions, but also built-in constants like integers and floats, are objects. Operators such as "+" are really shorthands for message passing: 3.add(4) is identical to 3 + 4. This is why the operation<br />
<br />
<pre>"The number is " + 1</pre><br />
<br />
works but<br />
<br />
<pre>1 + " is the number"</pre><br />
<br />
does not. A string knows how to handle a concatenate message with a number as the argument, but an integer is clueless what to do with an add of a string.<br />
<br />
Since "+" is really just shorthand for "add", you can construct objects that work with the "+" operator just by implementing an "add(argument)" method in the object.<br />
<br />
====Under the covers: Miranda Methods====<br />
<br />
There are a number of messages to which all normal objects respond, known as Miranda Methods. One example of such a method is the printOn(textWriter) method, which defines how an object will write itself out as by default. Other Miranda methods will be described in other sections of the book. The full list of Miranda methods can be found in the Appendix. You can also see them in rune by typing help(def obj{}) <span class="note" style="red">duplicate of next section, fix</span><br />
<br />
One important note about Miranda methods: they are not forwarded by the ''extends'' structure, and they are not intercepted by the match[verb,args] structure. They are always directly interpreted by the object that receives them.<br />
<br />
====Under the covers: Kernel-E====<br />
<br />
When you enter a normal E expression, E expands it into a more primitive form called ''Kernel-E''. If you're ever confused about some E syntax, viewing the Kernel-E expansion may help you to understand what it means. To make rune display the Kernel-E:<br />
<br />
<pre>? interp.setExpand(true)</pre><br />
<br />
Then:<br />
<br />
<pre><br />
? 1+1<br />
# expansion: 1.add(1)<br />
<br />
# value: 2<br />
<br />
? <type:java.lang.String><br />
# expansion: type__uriGetter.get("java.lang.String")<br />
<br />
# value: String<br />
</pre><br />
<br />
====Under the covers: Slots====<br />
<br />
In E, names are actually bound to ''Slots''. Evaluating a name as an expression calls the '''get/0''' method on its slot. You can refer to the slot itself by prefixing the name with &amp;:<br />
<br />
<pre><br />
? def x := 4<br />
? x<br />
# value: 4<br />
<br />
? (&x).get()<br />
# value: 4<br />
</pre><br />
<br />
Assigning to a variable calls the '''put/1''' method on its slot. You can define your own slots like this:<br />
<br />
<pre><br />
? def mySlot {<br />
> to get() { return "hello" }<br />
> }<br />
# value: <mySlot><br />
<br />
? def &x := mySlot<br />
? x<br />
# value: "hello"<br />
</pre><br />
<br />
Common uses of slots include:<br />
<br />
* Lazy slots (that evaluate a given function the first time you use them)<br />
* Variables that check the type of each new value you assign (e.g. '''var x :String''')<br />
* As a holder to pass to a function that needs to update a value<br />
<br />
====Getting Help About an Object With Rune====<br />
<br />
Another often convenient way of finding the list of methods associated with an object, be it a Java object or an <span class="e">''E''</span> object or an object delivered as part of the <span class="e">''E''</span> runtime, is to use the help(object) function of <span class="e">''E''</span>, often used in rune.<br />
<br />
<pre><br />
<br />
<nowiki>? def add(a, b) {<br />
> return a + b<br />
> }<br />
# value: <add><br />
<br />
? help(add)<br />
# value: an org.erights.e.elang.evm.EImplByProxy<br />
# interface "__main$add" {<br />
#<br />
# to run(:any, :any) :any<br />
# }<br />
#<br />
?</nowiki><br />
<br />
</pre><br />
<br />
In this very simple example you see the "run" method listed here, which is the implicit method for a function. For a more sophisticated object than a simple add function, each method in the object would be listed as well.<br />
<br />
'''help/1''' doesn't show Miranda methods. To include them, use '''help/2''':<br />
<br />
<pre><br />
? help(add, true)<br />
# value: an org.erights.e.elang.evm.EImplByProxy<br />
# interface "__main$add" {<br />
# <br />
# /** Sugar method*/<br />
# to __conformTo(:nullOk[Guard]) :any<br />
# <br />
# /** Sugar method*/<br />
# to __getAllegedType() :nullOk[TypeDesc]<br />
...<br />
</pre></div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Data_StructuresWalnut/Ordinary Programming/Data Structures2011-02-22T14:08:00Z<p>ThomasLeonard: /* Equality Testing for Structures */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
===Data Structures===<br />
<br />
In the next section, we will learn how to interface to Java, which will allow you to use most of the data structures supplied by the underlying jvm. E does offer a few data structures of its own, however, which are not only convenient, but which have special properties useful in distributed programming.<br />
<br />
====Flex and Const, List, Map and Set====<br />
<br />
There are three built-in data structures in <span class="e">''E''</span>, Lists, Maps, and Sets. Each of these structures comes in two flavors, Flex (editable) and Const (immutable). The ConstList is the simplest:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def list := ["a",2,true]<br />
#This is true: list[0] == "a"<br />
#This is true: list[2] == true<br />
def newList := list + ["last"]<br />
#This is true: newList[3] == "last"<br />
for each in newList {println(`Element: $each`)}<br />
for i => each in newList {println(`Element number $i is $each`)}<br />
def listSize := newList.size()<br />
# get subrange starting at 0, running up to element 2, but not including element 2<br />
def subrange := list(0,2)<br />
#This is true: subrange == ["a",2]</nowiki><br />
<br />
</pre><br />
<br />
Lists are numerically indexed starting from 0, use the "+" operator to create a new list which is the concatenation of lists. Lists work with the for loop. The "size" method returns the number of elements. The <span class="e">''E''</span> String type is a kind of ConstList in which all the elements are characters. So, for example, the mechanism for taking a subrange shown above gives you a substring if the ConstList is a String.<br />
<br />
You can make a FlexList from a ConstList with the ''diverge'' method:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def newList := []<br />
def editable := newList.diverge()<br />
editable.push(100)<br />
if (editable.pop() == 100) {<br />
println("Yeah, push and pop make a list work like a stack")<br />
}<br />
editable[0] := "b"<br />
def frozen := editable.snapshot() </nowiki><br />
<br />
</pre><br />
<br />
Warning: don't try to use the editable.add() method to push an item (as you would do in Java). "add" does the same thing as "+"; it returns a new list while leaving the original unchanged.<br />
<br />
All the methods that work on a ConstList also work on a FlexList. In addition, there are editing operations for FlexLists, including push/pop (which allows the FlexList to behave like a stack) and element replacement that uses Java array-style syntax. You can get a ConstList from a FlexList with the snapshot method. Just as Java Strings are like ConstLists in which all elements are characters, Java StringBuffers are like FlexLists in which all elements are characters.<br />
<br />
Maps are composed of key/value pairs. In the following example, in the ConstMap table, "a" is a key, and 1 is a value:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def table := ["a" => 1, 2 => "b"]<br />
# This is true: table["a"] == 1<br />
# This is true: table[2] == "b"<br />
def emptyTable := [].asMap()<br />
def keyTable := ["a",1,true].asKeys()<br />
# This is true: keyTable[true] == null <br />
# This is true: keyTable.maps("a") == true<br />
for key => value in table {println(`Key: $key Value: $value`)}<br />
for each in table {println(`Value: $each`)}<br />
def mapSize := table.size()</nowiki><br />
<br />
</pre><br />
<br />
Elements in a map are retrieved using an array-like syntax, using the key as the index in the square brackets. <br />
If you're not sure whether the key will be present, you can use the fetch method instead; this takes a function as its second argument and evaluates that if the key isn't present. e.g.<br />
<br />
<pre><br />
def value := table.fetch("key", def ifMissing() { return null })<br />
</pre><br />
<br />
You will often see this shortened further, using the "fn" syntax for anonymous functions:<br />
<br />
<pre><br />
def value := table.fetch("key", fn { null })<br />
</pre><br />
<br />
Maps can be made from lists using asMap and asKeys; when you use asKeys, the values are nulls. The for loop works nicely with the map structures.<br />
<br />
FlexMaps can be made from ConstMaps with the diverge method:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def editableMap := table.diverge()<br />
editableMap["c"] := 3<br />
editableMap["a"] := "replacement"<br />
editableMap.removeKey(2)<br />
def frozenMap := editableMap.snapshot() </nowiki><br />
<br />
</pre><br />
<br />
Values in a FlexMap can be added and replaced with array-like syntax. Key-value pairs can be removed with removeKey(key). The snapshot method creates a ConstMap from a FlexMap.<br />
<br />
Sets are quite similar, with ["a","b"].asSet() producing a ConstSet with 2 elements. Documentation for all the operations on Const and Flex lists, maps, and sets can be reached directly from the [http://www.erights.org/javadoc/index.html Javadoc For <span class="e">''E''</span> index].<br />
<br />
A String is actually a ConstList of characters. You can create a FlexList of elements of a specific type by specifying the type in the diverge/snapshot method:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def aString := [].diverge(char)</nowiki><br />
<br />
</pre><br />
<br />
This aString will not accept elements which are not of type char; the variable aString has many of the characteristics of a StringBuffer from Java.<br />
<br />
One feature of <span class="e">''E''</span> that Java/C programmers will find surprising but useful is the ability to define multiple variables by using a list:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def [a,b] := [2,3] <br />
#a holds the value 2<br />
#b holds the value 3</nowiki><br />
<br />
</pre><br />
<br />
While this is an amusing way to initialize a random bunch of variables at once, the structure is most valuable when creating groups of variables that have no meaning in the absence of one another. The method Ref.promise(), described in Distributed Computing, is an important user of this pattern.<br />
<br />
====Equality Testing for Structures====<br />
<br />
One of the biggest differences between Flex and Const structures is the test for equality. Const structures are compared by value, and as such are considered equal if their contents are identical. The test for equality is, in other words, the same as the test for equality between Java integers.<br />
<br />
Note that, in E, the order of elements in maps and sets is sometimes significant (e.g. when iterating over the elements) and so two sets with the same elements in different orders are not equal according to ==. Use <=>, the "asBigAs" operator, to check that two sets contain the same items.<br />
<br />
Two Flex structures are considered equal if and only if they are the same structure, i.e., both of the variables being tested are references to a single object. This test for equality is, in other words, the same as the test for equality between Java StringBuffers.</div>ThomasLeonardhttp://wiki.erights.org/wiki/Surprise_listSurprise list2011-02-01T14:57:26Z<p>ThomasLeonard: Single-letter uriGetters get overridden by the parser</p>
<hr />
<div>Potentially surprising parts of the [[E language]].<br />
<br />
Current as of [http://www.erights.org/download/0-8-29/ E 0.8.33o].<br />
<br />
==For-loop pattern failure is not an error==<br />
<br />
<!-- FIXME: link to erights.org for loop doc --><br />
<br />
If the key or value pattern of a <code>for</code> loop does not match, then the loop simply skips that element of the collection. This can be useful, but is unlike all other non-explicit pattern match operations (<code>def</code> and parameter lists).<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def things := [1, "two", 3]<br />
# value: [1, "two", 3]<br />
<br />
? for x :int in things { <br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# 3<br />
# <br />
<br />
<br />
===Alternative===<br />
<br />
Move the pattern into a <code>def</code>:<br />
<br />
# E sample<br />
<br />
? for thing in things {<br />
> def x :int := thing<br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# <br />
<br />
# problem: &lt;ClassCastException: String doesn't coerce to an int&gt;<br />
<br />
==<code>def x</code> doesn't return <var>x</var>==<br />
<br />
The forward declaration expression, <code>def <var>var</var></code>, does not return <var>var</var> but rather the [[Resolver]] for it.<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def x<br />
# value: &lt;Resolver&gt;<br />
<br />
? x<br />
# value: &lt;Promise&gt;<br />
<br />
===Reason and Uses===<br />
<br />
If you want to pass a resolver as an argument, this syntax is helpful:<br />
<br />
x.hereIsAResolver(def y)<br />
<var>... use y</var><br />
<br />
===Alternative===<br />
<br />
If you want the actual promise, simply write <code>(def x; x)</code>.<br />
<br />
==Unresolved references do not necessarily behave as their future resolved identity==<br />
<br />
&mdash; messages sent before the reference is resolved may be reacted to however the current holder of the reference &ldquo;arrow-head&rdquo; chooses, which does not necessarily correspond to the reference to which the unresolved reference resolves.<br />
<br />
This has been discussed in [http://www.eros-os.org/pipermail/e-lang/2005-July/010821.html an e-lang thread].<br />
<br />
===Reason and Uses===<br />
<br />
This cannot be fixed without removing [http://www.erights.org/elib/distrib/pipeline.html pipelining], eliminating one of the major benefits of the E reference model.<br />
<br />
===Examples===<br />
<br />
For now, see [http://www.eros-os.org/pipermail/e-lang/2005-July/010827.html this lengthy example by MarkM].<br />
<br />
===Alternative===<br />
<br />
To avoid being vulnerable to this type of misbehavior, do not use a sameness test (<code>==</code>) or Map key lookup in order to decide on the reliability of the response to a ''previously'' sent message. This might involve using a when-catch/whenResolved construct to wait until the reference is resolved.<br />
<br />
==Accumulator operator is lowest-precedence==<br />
<br />
As you can see in the following expansion, the operator following the “_” is always lowest-precedence (as it is the one effectively rewritten into an assignment form):<br />
<br />
? e`pragma.enable("accumulator"); accum 0 while (a) { _ * b + c }`<br />
# value: e`null<br />
...<br />
# accum__1 := accum__1.multiply(b.add(c))<br />
...<br />
<br />
===Reason and Uses===<br />
<br />
None known; this is probably an accident of the definition of the expansion of accumulator syntax.<br />
<br />
===Alternative===<br />
<br />
Avoid accumulator syntax when the accumulation cannot be expressed as a single call.<br />
<br />
<br />
<br />
== Shadowing function arguments ==<br />
<br />
Rebinding a name within a block is an error, e.g.<br />
<br />
def foo() {<br />
def x := 2<br />
def x := 3<br />
}<br />
<br />
("Failed: x already in scope")<br />
<br />
However, rebinding an argument does not issue any warning:<br />
<br />
def foo(x) {<br />
...<br />
def x := 2<br />
...<br />
println(x)<br />
}<br />
<br />
<br />
== Single-letter uriGetters get overridden by the parser ==<br />
<br />
? def <t> := ["foo" => "bar"]<br />
# value: ["foo" => "bar"]<br />
<br />
? <t:foo> == "bar"<br />
# value: false<br />
<br />
If the variable had been called &lt;tt> instead of &lt;t>, the result would have been true.<br />
<br />
[[Category:E language]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Surprise_listSurprise list2011-02-01T14:53:35Z<p>ThomasLeonard: Shadowing function arguments</p>
<hr />
<div>Potentially surprising parts of the [[E language]].<br />
<br />
Current as of [http://www.erights.org/download/0-8-29/ E 0.8.33o].<br />
<br />
==For-loop pattern failure is not an error==<br />
<br />
<!-- FIXME: link to erights.org for loop doc --><br />
<br />
If the key or value pattern of a <code>for</code> loop does not match, then the loop simply skips that element of the collection. This can be useful, but is unlike all other non-explicit pattern match operations (<code>def</code> and parameter lists).<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def things := [1, "two", 3]<br />
# value: [1, "two", 3]<br />
<br />
? for x :int in things { <br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# 3<br />
# <br />
<br />
<br />
===Alternative===<br />
<br />
Move the pattern into a <code>def</code>:<br />
<br />
# E sample<br />
<br />
? for thing in things {<br />
> def x :int := thing<br />
> println(x)<br />
> }<br />
# stdout: 1<br />
# <br />
<br />
# problem: &lt;ClassCastException: String doesn't coerce to an int&gt;<br />
<br />
==<code>def x</code> doesn't return <var>x</var>==<br />
<br />
The forward declaration expression, <code>def <var>var</var></code>, does not return <var>var</var> but rather the [[Resolver]] for it.<br />
<br />
===Examples===<br />
<br />
# E sample<br />
<br />
? def x<br />
# value: &lt;Resolver&gt;<br />
<br />
? x<br />
# value: &lt;Promise&gt;<br />
<br />
===Reason and Uses===<br />
<br />
If you want to pass a resolver as an argument, this syntax is helpful:<br />
<br />
x.hereIsAResolver(def y)<br />
<var>... use y</var><br />
<br />
===Alternative===<br />
<br />
If you want the actual promise, simply write <code>(def x; x)</code>.<br />
<br />
==Unresolved references do not necessarily behave as their future resolved identity==<br />
<br />
&mdash; messages sent before the reference is resolved may be reacted to however the current holder of the reference &ldquo;arrow-head&rdquo; chooses, which does not necessarily correspond to the reference to which the unresolved reference resolves.<br />
<br />
This has been discussed in [http://www.eros-os.org/pipermail/e-lang/2005-July/010821.html an e-lang thread].<br />
<br />
===Reason and Uses===<br />
<br />
This cannot be fixed without removing [http://www.erights.org/elib/distrib/pipeline.html pipelining], eliminating one of the major benefits of the E reference model.<br />
<br />
===Examples===<br />
<br />
For now, see [http://www.eros-os.org/pipermail/e-lang/2005-July/010827.html this lengthy example by MarkM].<br />
<br />
===Alternative===<br />
<br />
To avoid being vulnerable to this type of misbehavior, do not use a sameness test (<code>==</code>) or Map key lookup in order to decide on the reliability of the response to a ''previously'' sent message. This might involve using a when-catch/whenResolved construct to wait until the reference is resolved.<br />
<br />
==Accumulator operator is lowest-precedence==<br />
<br />
As you can see in the following expansion, the operator following the “_” is always lowest-precedence (as it is the one effectively rewritten into an assignment form):<br />
<br />
? e`pragma.enable("accumulator"); accum 0 while (a) { _ * b + c }`<br />
# value: e`null<br />
...<br />
# accum__1 := accum__1.multiply(b.add(c))<br />
...<br />
<br />
===Reason and Uses===<br />
<br />
None known; this is probably an accident of the definition of the expansion of accumulator syntax.<br />
<br />
===Alternative===<br />
<br />
Avoid accumulator syntax when the accumulation cannot be expressed as a single call.<br />
<br />
<br />
<br />
== Shadowing function arguments ==<br />
<br />
Rebinding a name within a block is an error, e.g.<br />
<br />
def foo() {<br />
def x := 2<br />
def x := 3<br />
}<br />
<br />
("Failed: x already in scope")<br />
<br />
However, rebinding an argument does not issue any warning:<br />
<br />
def foo(x) {<br />
...<br />
def x := 2<br />
...<br />
println(x)<br />
}<br />
<br />
<br />
[[Category:E language]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/User:Kevin_Reid/ASTPrint.javaUser:Kevin Reid/ASTPrint.java2010-11-24T09:34:39Z<p>ThomasLeonard: bind-var-to-propName</p>
<hr />
<div>// Minimal Java program attempting to set up an E-on-Java vat and do something in it. Written 2008-10-11. Doesn't work as of 2010-11-22 testing; I don't recall whether I ever finished it. Result is <code>problem: <nowiki><NoSuchMethodException: <an HeadlessRunnerMgr__Maker>.getTHE_ONE/0></nowiki></code><br />
<br />
[ It probably needs a <code>System.setProperty("e.safej.bind-var-to-propName", "true");</code> ]<br />
<br />
import org.erights.e.elang.interp.ScopeSetup;<br />
import org.erights.e.elib.tables.Twine;<br />
import org.erights.e.elib.prim.E;<br />
import org.erights.e.elang.syntax.EParser;<br />
import org.erights.e.elang.evm.ENode;<br />
import org.erights.e.elib.serial.Loader;<br />
import org.erights.e.elib.vat.Vat;<br />
<br />
class ASTPrint {<br />
public static void main(String[] args) {<br />
try {<br />
Vat vat = Vat.make("headless", "start");<br />
Throwable optNoStart = vat.enqueue(new Runnable() {<br />
public void run() {<br />
ENode node = EParser.run(Twine.fromString("aardvarks"));<br />
System.out.print(node);<br />
Loader i = (Loader)(ScopeSetup.safeScope("__main$").get("import__uriGetter"));<br />
Object converter = E.call(i.get("org.erights.e.elang.visitors.makeConvertENode2Term"), "run");<br />
System.out.print(E.call(converter, "run", node));<br />
}<br />
});<br />
if (null != optNoStart) {<br />
throw optNoStart;<br />
}<br />
} catch (Throwable e) {<br />
System.err.print(E.toString(e));<br />
System.err.print(E.call(e, "eStack"));<br />
}<br />
}<br />
}</div>ThomasLeonardhttp://wiki.erights.org/wiki/User:ThomasLeonardUser:ThomasLeonard2010-11-09T12:07:56Z<p>ThomasLeonard: </p>
<hr />
<div>I'm using E for two separate projects:<br />
<br />
* At [http://www.it-innovation.soton.ac.uk/ IT Innovation], for some of our experimental work on service oriented architectures.<br />
* At [http://0install.net/ebox.html 0install.net], as a demonstrator showing how to use 0install to run sandboxed applications with distributed dependencies.<br />
<br />
== Branches ==<br />
<br />
I publish my patches to [http://gitorious.org/~tal-itinnov/repo-roscidus/it-innovation my E Git repository]. The '''next''' branch generally contains things I consider ready for merging into the E svn repository.<br />
<br />
Other patches/branches:<br />
<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-October/013648.html Make CapTP shutdown when its vat is shutdown] (on next).<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-September/013620.html Split Scope] into Scope (internal data structure for the E interpreter, including local variables, etc) and EEnv (simpler structure exposed to E code, replacing safeScope, etc). This avoids the need to tame access to these objects and hopefully makes the code easier to read.<br />
* Various possible optimisations are on the '''compiler''' branch (these mostly have only a small benefit or don't work fully; otherwise I push them to next). These optimisations work for both the current E interpreter and for a possible future E compiler. There is also a very old wip-compiler branch that actually does compile E to JVM bytecode. However, it turned out that the major performance problems were elsewhere.</div>ThomasLeonardhttp://wiki.erights.org/wiki/User:ThomasLeonardUser:ThomasLeonard2010-11-09T12:02:11Z<p>ThomasLeonard: </p>
<hr />
<div>I'm using E for two separate projects:<br />
<br />
* At [http://www.it-innovation.soton.ac.uk/ IT Innovation], for some of our experimental work on service oriented architectures.<br />
* At [http://0install.net/ebox.html 0install.net], as a demonstrator showing how to use 0install to run sandboxed applications with distributed dependency handling.<br />
<br />
== Branches ==<br />
<br />
I publish my patches to [http://gitorious.org/~tal-itinnov/repo-roscidus/it-innovation my E Git repository]. The '''next''' branch generally contains things I consider ready for merging into the E svn repository.<br />
<br />
Other patches/branches:<br />
<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-October/013648.html Make CapTP shutdown when its vat is shutdown] (on next).<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-September/013620.html Split Scope] into Scope (internal data structure for the E interpreter, including local variables, etc) and EEnv (simpler structure exposed to E code, replacing safeScope, etc). This avoids the need to tame access to these objects and hopefully makes the code easier to read.<br />
* Various possible optimisations are on the '''compiler''' branch (these mostly have only a small benefit or don't work fully; otherwise I push them to next). These optimisations work for both the current E interpreter and for a possible future E compiler. There is also a very old wip-compiler branch that actually does compile E to JVM bytecode. However, it turned out that the major performance problems were elsewhere.</div>ThomasLeonardhttp://wiki.erights.org/wiki/User:ThomasLeonardUser:ThomasLeonard2010-11-09T11:57:40Z<p>ThomasLeonard: </p>
<hr />
<div>I'm using E for two separate projects:<br />
<br />
* At [http://www.it-innovation.soton.ac.uk/ IT Innovation], for some of our experimental work on service oriented architectures.<br />
* At [http://0install.net/ebox.html 0install.net], as a demonstrator showing how to use 0install to run sandboxed applications with distributed dependency handling.<br />
<br />
== Branches ==<br />
<br />
I publish my patches to [http://gitorious.org/~tal-itinnov/repo-roscidus/it-innovation my E Git repository]. The '''next''' branch generally contains things I consider ready for merging into the E svn repository.<br />
<br />
Other patches/branches:<br />
<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-October/013647.html Make CapTP shutdown when its vat is shutdown] (on next).<br />
* [http://www.eros-os.org/pipermail/e-lang/2010-September/013620.html Split Scope] into Scope (internal data structure for the E interpreter, including local variables, etc) and EEnv (simpler structure exposed to E code, replacing safeScope, etc). This avoids the need to tame access to these objects and hopefully makes the code easier to read.<br />
* Various possible optimisations are on the '''compiler''' branch (these mostly have only a small benefit or don't work fully; otherwise I push them to next). These optimisations work for both the current E interpreter and for a possible future E compiler. There is also a very old wip-compiler branch that actually does compile E to JVM bytecode. However, it turned out that the major performance problems were elsewhere.</div>ThomasLeonardhttp://wiki.erights.org/wiki/User:ThomasLeonardUser:ThomasLeonard2010-11-09T11:53:12Z<p>ThomasLeonard: </p>
<hr />
<div>I'm using E for two separate projects:<br />
<br />
* At [http://www.it-innovation.soton.ac.uk/ IT Innovation], for some of our experimental work on service oriented architectures.<br />
* At [http://0install.net/ebox.html 0install.net], as a demonstrator showing how to use 0install to run sandboxed applications with distributed dependency handling.<br />
<br />
== Branches ==<br />
<br />
I publish my patches to [http://gitorious.org/~tal-itinnov/repo-roscidus/it-innovation my E Git repository]. The '''next''' branch generally contains things I consider ready for merging into the E svn repository.<br />
<br />
Other patches/branches:<br />
<br />
* Make CapTP shutdown when its vat is shutdown (on next)<br />
* Various possible optimisations are on the '''compiler''' branch (these mostly have only a small benefit or don't work fully; otherwise I push them to next)<br />
* Split Scope into Scope (internal data structure for the E interpreter, including local variables, etc) and EEnv (simpler structure exposed to E code, replacing safeScope, etc). This avoids the need to tame access to these objects and hopefully makes the code easier to read.</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Objects_and_FunctionsWalnut/Ordinary Programming/Objects and Functions2010-10-21T14:04:01Z<p>ThomasLeonard: /* Getting Help About an Object With Rune */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Objects and Functions===<br />
<br />
As noted earlier, if the file is to use the Swing gui toolkit, it must have a suffix of ".e-awt". If the file is to use the SWT gui toolkit, it must have a suffix of ".e-swt". If the file will run headless, it should be placed in a file with suffix ".e".<br />
<br />
But first, we need to declare what version of E we're using here.<br />
<pre><br />
? pragma.syntax("0.9")<br />
</pre><br />
<br />
====Functions====<br />
<br />
A basic function looks like this:<br />
<br />
<pre># E sample<br />
def addNumbers(a,b) {<br />
return a + b<br />
}<br />
# Now use the function<br />
def answer := addNumbers(3,4)<br />
</pre><br />
<br />
You can nest the definitions of functions and objects inside other functions and objects, giving you functionality comparable to that of inner classes in Java. Nested functions and objects play a crucial role in <span class="e">''E''</span>, notably in the construction of objects as described shortly.<br />
<br />
A parameterless function must still have an open/close paren pair. Calls to parameterless functions must also include the parens.<br />
<br />
Functions can of course call themselves recursively, as in<br />
<br />
<pre># E sample<br />
def factorial(n) {<br />
if (n == 0) {<br />
return 1<br />
} else {<br />
return n * factorial(n-1)<br />
}<br />
}<br />
</pre><br />
<br />
====Dynamic "type checking" and Guards====<br />
<br />
<span class="e">''E''</span> guards perform many of the functions usually thought of as type checking, though they are so flexible, they also work as concise assertions. Guards can be placed on variables, parameters, and return values.<br />
<br />
Guards are not checked during compilation. They are checked during execution, and will throw exceptions if the value cannot be coerced to pass the guard. Guards play a key role in protecting the security properties when working with untrusted code, as discussed in Secure Distributed Computing.<br />
<br />
The available guards include the items below. Some of them are typical types (String, int). Others are used most often in distributed programming, and are explained later in the book. A detailed explanation of all the things you can do with guards is postponed to the [[Walnut/Aditional_Features|Aditional Features]] chapter.<br />
<br />
* int<br />
* char<br />
* float64<br />
* boolean<br />
* String<br />
* void<br />
* notNull<br />
* nullOk<br />
* near<br />
* vow<br />
* rcvr<br />
* pbc<br />
* Data<br />
* Java classes<br />
* <span class="e">''E''</span> interfaces<br />
* subranges and more complex expressions<br />
<br />
import weakpointermaker<br />
makevat 2 args 1)kind of vat, string"headless, awt, swt",<br />
2)name of vat for debugging<br />
import seedvatauthor<br />
authorize it to get a seedvat function with uri getter<br />
seedvat takes 2 args: 1)vat<br />
2)string that is contents of a dot-e file except<br />
all evaluated at once. seedvat function returns a promise for<br />
the result of evaluating that expression. since it evaluates in foreighn vat,<br />
it is a far reference.typical pattern: only do importing and construction <br />
in the expression string<br />
<br />
Here are some quick examples of guards being declared:<br />
<br />
<pre># E sample<br />
# guarding a variable<br />
def title :String := "abc"<br />
# guarding a parameter, and a return value. Note the guard on the <br />
# return value is part of the def line for the function.<br />
def reciprocal(x :float64) :float64 {<br />
return 1 / x<br />
}<br />
</pre><br />
<br />
Different people use different strategies about how much type checking/guard information to include in their programs. In this book, the general style is to use guards sparingly, as might be typical in a rapid prototyping environment. One place where guards must be used with rigor is in the objects on the boundaries between trust realms, in security aware applications; see the Powerbox pattern in the [[Walnut/Secure_Distributed_Computing|Secure Distributed Programming section]] for an important example.<br />
<br />
====Objects====<br />
<br />
Objects, and object constructors, look considerably different in <span class="e">''E''</span> than in Java or C++. We will start our exploration of objects with a simple singleton object.<br />
<br />
=====A Singleton Object=====<br />
<br />
Objects, functions, and variables are defined with the keyword "def"; all of these can be passed as arguments in parameter lists. Methods on an object, in contrast, are defined with the keyword "to":<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def origin {<br />
to getX() {return 0}<br />
to getY() {return 0}<br />
}<br />
# Now invoke the methods<br />
def myY := origin.getY()<br />
</nowiki><br />
<br />
</pre><br />
<br />
Like functions, methods require a parenthesis pair even if there are no arguments. ''(But, Python programmers beware, methods are not functions. Methods are just the public hooks to the object that receive messages; functions are standalone objects)''.<br />
<br />
When invoking the method, the object name and the method called are separated by a dot.<br />
<br />
=====Stateful objects and object constructors=====<br />
<br />
The "class" concept in Java is used to achieve multiple goals. In <span class="e">''E''</span>, these goals are factored out in a different way. For example, Java classes supply a place to put constructors, which have a special syntax unique to constructors. In <span class="e">''E''</span>, objects are constructed by ordinary functions.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Point constructor<br />
def makePoint(x,y) {<br />
def point {<br />
to getX() {return x}<br />
to getY() {return y}<br />
to makeOffsetPoint(offsetX, offsetY) {<br />
return makePoint(x + offsetX, y + offsetY)<br />
}<br />
to makeOffsetPoint(offset) {<br />
return makePoint(x + offset, y + offset)<br />
}<br />
} <br />
return point<br />
}<br />
# Create a point<br />
def origin := makePoint(0,0)<br />
# get the y value of the origin<br />
def y := origin.getY()</nowiki><br />
<br />
</pre><br />
<br />
Inside the function makePoint, we define a point and return it. As demonstrated by the makeOffsetPoint method, the function (makePoint) can be referenced from within its own body. Also note that you can overload method names (two versions of makeOffsetPoint) as long as they can be distinguished by the number of parameters they take.<br />
<br />
The (x, y) passed into the function are not ephemeral parameters that go out of existence when the function exits. Rather, they are true variables (implicitly declared with "def" ), and they persist as long as any of the objects that use them persist. Since the point uses these variables, x and y will exist as long as the point exists. This saves us the often tedious business in Java of copying the arguments from the parameter list into instance variables: x and y already are instance variables.<br />
<br />
We refer to an object-making function such as makePoint as a "Maker". Let us look at a more serious example, with additional instance variables:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(var name) {<br />
var x := 0<br />
var y := 0<br />
def car {<br />
to moveTo(newX,newY) {<br />
x := newX<br />
y := newY<br />
}<br />
to getX() {return x}<br />
to getY() {return y}<br />
to setName(newName) {name := newName}<br />
to getName() {return name}<br />
} <br />
return car<br />
}<br />
# Now use the makeCar function to make a car, which we will move and print<br />
def sportsCar := makeCar("Ferrari")<br />
sportsCar.moveTo(10,20)<br />
println(`The car ${sportsCar.getName()} is at X location ${sportsCar.getX()}`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
Inside the Maker, we create the instance variables for the object being made (x and y in this example), then we create the object (car). Note that the variable "name", passed into the function, is explicitly declared with "var", so that it can be altered later; in this case, it is reassigned in the setName() method.<br />
<br />
=====Self-referencing objects=====<br />
<br />
Sometimes in the body of an object you wish to refer to the object itself. A keyword like "this" is not required. The name given to the object is in scope in the body of the object, so just use it:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
var x := 0<br />
var y := 0<br />
def </nowiki>car {<br />
to moveDistance(newX,newY) {car.moveTo(x + newX, y + newY)}<br />
# ....define other methods including moveTo as above ....<br />
}<br />
return car<br />
}<br />
<br />
</pre><br />
<br />
What if you need to reference the object during the object's construction, i.e., during the creation of the instance variables that precedes the definition of the object itself? In the below example, we give the car a weatherReportRadio that is supposed to alert the car to changing weather conditions. This radio requires, as a parameter during its construction, the car it will be alerting. So the radio needs the car during radio construction, and the car needs the radio during car construction.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeRadio(car) {<br />
# define radios<br />
}<br />
def makeCar(name) { <br />
var x := 0 <br />
var y := 0<br />
# using def with no assignment<br />
def car<br />
def myWeatherRadio := makeRadio(car)<br />
bind car {<br />
to receiveWeatherAlert(myWeatherRadio) {<br />
# ....process the weather report....<br />
} <br />
to getX() {return x} <br />
to getY() {return y}<br />
# ....list the rest of the car methods....<br />
}<br />
return car<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here, we do a "def" of the car with no assignment, then we use the car, then we do a "bind" of the car which binds a value to the car. This looks and behaves like a "forward reference" from C. Under the covers, the statement "def car" creates a ''promise'' for the car, and the ''bind'' statement ''fulfills'' the promise. We discuss promises in greater depth in the [[Walnut/Distributed_Computing|Distributed Computing]] chapter, where they play a key role.<br />
<br />
=====Secret Life of Functions, Multiple Constructors and "Static Methods"=====<br />
<br />
Before we can talk about multiple constructors and the static-method-like behavior in <span class="e">''E''</span>, it is time to reveal the truth about <span class="e">''E''</span> functions. They are in fact simple objects with a single method, the "run" method, that is invoked by default if no other method is explicitly designated. For example, the following square function<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square(x) {return x*x}</nowiki><br />
<br />
</pre><br />
<br />
is really syntactic shorthand for<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square {<br />
to run(x) {return x*x}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
In the second one, the run() method is explicitly defined. Using this explicit form in a Maker function, you can define multiple constructors, discriminated by the number of parameters they receive. Similarly, by adding methods to the Maker other than "run" methods, you get other "static methods". In the example below, we have a queue Maker with 2 constructors and a non-constructor method. The one-argument constructor requires an initial capacity; the no-argument constructor supplies an initial capacity of 10.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeQueue {<br />
to run(initialCapacity) {<br />
# ....create a queue object with the specified initial capacity....<br />
}<br />
to run() {return makeQueue(makeQueue.getDEFAULT_CAPACITY())}<br />
to getDEFAULT_CAPACITY() {return 10}<br />
}<br />
# Now use both constructors<br />
def queue1 := makeQueue(100)<br />
def queue2 := makeQueue()<br />
println(`default capacity is: ${makeQueue.getDEFAULT_CAPACITY()}`)</nowiki><br />
<br />
</pre><br />
<br />
Note also that one can use methods such as getDEFAULT_CAPACITY() to achieve the same effect as Java achieves with public static final variables.<br />
<br />
====Polymorphism====<br />
<br />
<span class="e">''E''</span> enables polymorphism through method name matching. In this example, we move both a car and an airplane to a new location using a single common piece of code:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
def car {<br />
to moveTo(x, y) {<br />
# move the car<br />
}<br />
# other methods<br />
}<br />
return car<br />
}<br />
def makeJet(name) {<br />
def jet { <br />
to moveTo(x, y) { <br />
# move the jet, very different code from the code for car <br />
} <br />
# other methods <br />
} <br />
return jet<br />
}<br />
def vehicles := [makeCar("car"), makeJet("jet")]<br />
for each in vehicles {<br />
each.moveTo(3,4)<br />
} </nowiki><br />
<br />
</pre><br />
<br />
====Extends and Delegation====<br />
<br />
An object can refer calls to itself to another object (a "super-object", built by the "super-constructor", faintly similar to the way one uses superclasses in Java) using the ''extends'' keyword: <span class="note" style="color:red">think of better example</span><br />
<br />
<pre><br />
<br />
<nowiki>? def makePoint(x, y) { <br />
> def point { <br />
> to getX() {return x} <br />
> to getY() {return y}<br />
> to getMagnitude() {return (x*x + y*y)**0.5} <br />
> }<br />
> return point<br />
> } <br />
# value: <makePoint> <br />
<br />
? def makePoint3D(x,y,z) { <br />
> def point3D extends makePoint(x,y) { <br />
> to getZ() {return z} <br />
> to getMagnitude() {<br />
> def xy := super.getMagnitude()<br />
> return (z*z + xy*xy)**0.5<br />
> } <br />
> }<br />
> return point3D <br />
> } <br />
# value: <makePoint3D><br />
<br />
? def place := makePoint3D(1,2,3)<br />
# value: <point3D><br />
<br />
? def x := place.getX()<br />
# value: 1<br />
<br />
? def z := place.getZ()<br />
# value: 3</nowiki><br />
<br />
</pre><br />
<br />
Here makePoint3D acts as an extension of makePoint. Inside the ''extends'' clause, we run the makePoint constructor to create the Point upon which the Point3D will be built. This specially constructed point is referred to in the point3D definition as "super"; you can see super being used in the getMagnitude method.<br />
<br />
Using ''extends'' as described above follows the ''delegation'' pattern. Delegation is a simple pattern of object composition in which an object says, "if another object calls me with a method that I don't have defined here, just route the message to this other object, and send the result back to the caller." Delegation is similar to inheritance, but it is conceptually simpler.<br />
<br />
====Extends and Full Inheritance====<br />
<br />
Some experts consider inheritance to be a dangerous feature. A discussion of the pros and cons of inheritance is beyond the scope of this book. However, none of the full-blown examples in this book actually use full inheritance. Delegation, via the simple ''extends'' keyword plus polymorphism serve most of the purposes for which inheritance was intended, and is used everywhere here.<br />
<br />
Having said that, there are times and places where full inheritance is the right answer. The ''extends'' keyword is also used, with one additional convention, to support such full inheritance. In inheritance, the "self" to which a super-object refers is the sub-object of which it is a part, so that the super-object can use methods in the sub-object:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def makeVehicle(self) {<br />
def vehicle {<br />
to milesTillEmpty() {<br />
return self.milesPerGallon() * self.getFuelRemaining()<br />
}<br />
}<br />
return vehicle<br />
}<br />
<br />
def makeCar() {<br />
var fuelRemaining := 20<br />
def car extends makeVehicle(car) {<br />
to milesPerGallon() {return 19}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return car<br />
}<br />
<br />
def makeJet() {<br />
var fuelRemaining := 2000<br />
def jet extends makeVehicle(jet) {<br />
to milesPerGallon() {return 2}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return jet<br />
}<br />
<br />
def car := makeCar()<br />
println(`The car can go ${car.milesTillEmpty()} miles.`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
As seen in the example, the super-object constructor specifies a parameter, "self", which can be used to refer to the sub-object. The sub-object includes itself in the the call to the super-object constructor, thus becoming "self".<br />
<br />
====E Interfaces====<br />
<br />
You can define an interface like this:<br />
<br />
interface Foo {<br />
}<br />
<br />
def foo implements Foo {<br />
}<br />
<br />
foo :Foo<br />
<br />
The interface body can contain method signatures (without bodies).<br />
<br />
When an object is declared as "implements Foo", Foo acts as a "rubber-stamping" auditor, which marks the object as implementing the interface (whether or not it implements any of the methods defined in the interface). When Foo is used as a guard, it checks that the object was stamped by the auditor.<br />
<br />
This allows your module to give out objects and recognise them when they are given back later. However, this cannot be used for security purposes because the interface (Foo) cannot be kept secret. This is because when a non-Foo object is checked with the Foo guard, object.__conformTo(Foo) is called. <br />
<br />
The two functions of Foo (guard and auditor) may be split up using this syntax:<br />
<br />
interface FooGuard guards FooAuditor { }<br />
<br />
def foo implements FooAuditor { ... }<br />
<br />
foo :FooGuard<br />
<br />
This allows the guard to be given out freely while the auditor is closely held, preventing others from creating fake Foo objects but allowing anyone to check that a given object is a genuine Foo.<br />
<br />
Presumably, you could also implement a public auditor that actually performed some kind of check on an object, and then used the rubber-stamping auditor to stamp it if it passed the checks [how?].<br />
<br />
The interface construct is likely to change in future[http://www.eros-os.org/pipermail/e-lang/2010-February/013432.html].<br />
<br />
====General method name matching and E.call()====<br />
<br />
Delegation with extends does a straight pass-through of the method call. It is possible to intercept collections of calls before delegating them, using ''match''. In this example, we count the number of calls made to a car:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCalledCountCar(name) {<br />
def myCar := makeCar(name) <br />
var myCallCount := 0<br />
def car {<br />
to getCallCount() {return myCallCount}<br />
match [verb,args] {<br />
myCallCount += 1<br />
E.call(myCar,verb,args)<br />
}<br />
}<br />
return car<br />
} </nowiki><br />
<br />
</pre><br />
<br />
In "match[verb,args]", the verb is a string specifying the name of the method being called, and the args is a list of arguments. If the car is called with a method that is not defined in a "to" statement, the name of the method and the arguments are bound to the variables inside the square brackets. We then increment the call count, and finally forward the message using the E.call function. E.call(...) takes as arguments the target object for the action, the name of the method to call, and the list of arguments for the method to invoke. You can manually use E.call() like this:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def car := makeCar("mercedes")<br />
E.call(car, "moveTo", [3,4])<br />
# which is equivalent to<br />
car.moveTo(3,4)</nowiki><br />
<br />
</pre><br />
<br />
In this example, the elements for the argument list are placed in square brackets to form an <span class="e">''E''</span> ConstList, described later in this chapter.<br />
<br />
The match construct is useful for making "adapters" when interfacing to Java. Here we build a singleton object that can be used anywhere a java.awt.event.MouseListener would be used; the match clause is used to absorb and discard events in which we are not interested:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def mouseListener {<br />
to mouseClicked(event) {<br />
# process the event<br />
}<br />
match [verb,args] {}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
This general purpose matching is also useful in security applications when building facets and revocable capabilities, as described in the chapter on Secure Distributed Computing.<br />
<br />
====Edoc, the <span class="e">''E''</span> equivalent of JavaDoc====<br />
<br />
E supports the construction of javadoc-style comments that can be postprocessed into HTML documentation. For this purpose, the "/** ... */" comment format has been specially reserved; comments of this style can only appear in front of a function/object definition (a "def" statement), or in front of an object method definition (a "to" statement):<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
/**<br />
* Add 2 numbers together.<br />
* <p><br />
* Currently works with any objects that support the "plus" method<br />
*<br />
* @param a the first number. <br />
* @param b the second number<br />
* @return the result of adding. <br />
*/<br />
def adder(a, b) {return a + b}</nowiki><br />
<br />
</pre><br />
<br />
For more information on how to generate Edoc HTML from your <span class="e">''E''</span> programs, see the [[Walnut/Additional_Features|Additional Features]].<br />
<br />
====Under the covers: Everything is an Object====<br />
<br />
We have already discussed the fact that functions are really objects with a single method, "run". Functions-as-objects have one practical consequence that would be surprising in the absence of understanding. You cannot create two functions with different numbers of parameters and have them overloaded:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def times2(a) {return a * 2}<br />
def compute(a,b) {<br />
def times2(c,d) {return (c + d) * 2}<br />
# ....do computation...<br />
# The following line will throw an exception<br />
def answer := times2(a)<br />
return answer<br />
}</nowiki><br />
<br />
</pre><br />
<br />
<font color="#FF0000">This would throw an exception because the inner definition of the function-like object times2 completely shadows the outer times2.</font><br />
<br />
Not only functions, but also built-in constants like integers and floats, are objects. Operators such as "+" are really shorthands for message passing: 3.add(4) is identical to 3 + 4. This is why the operation<br />
<br />
<pre>"The number is " + 1</pre><br />
<br />
works but<br />
<br />
<pre>1 + " is the number"</pre><br />
<br />
does not. A string knows how to handle a concatenate message with a number as the argument, but an integer is clueless what to do with an add of a string.<br />
<br />
Since "+" is really just shorthand for "add", you can construct objects that work with the "+" operator just by implementing an "add(argument)" method in the object.<br />
<br />
====Under the covers: Miranda Methods====<br />
<br />
There are a number of messages to which all normal objects respond, known as Miranda Methods. One example of such a method is the printOn(textWriter) method, which defines how an object will write itself out as by default. Other Miranda methods will be described in other sections of the book. The full list of Miranda methods can be found in the Appendix. You can also see them in rune by typing help(def obj{}) <span class="note" style="red">duplicate of next section, fix</span><br />
<br />
One important note about Miranda methods: they are not forwarded by the ''extends'' structure, and they are not intercepted by the match[verb,args] structure. They are always directly interpreted by the object that receives them.<br />
<br />
====Under the covers: Kernel-E====<br />
<br />
When you enter a normal E expression, E expands it into a more primitive form called ''Kernel-E''. If you're ever confused about some E syntax, viewing the Kernel-E expansion may help you to understand what it means. To make rune display the Kernel-E:<br />
<br />
<pre>? interp.setExpand(true)</pre><br />
<br />
Then:<br />
<br />
<pre><br />
? 1+1<br />
# expansion: 1.add(1)<br />
<br />
# value: 2<br />
<br />
? <type:java.lang.String><br />
# expansion: type__uriGetter.get("java.lang.String")<br />
<br />
# value: String<br />
</pre><br />
<br />
<br />
====Getting Help About an Object With Rune====<br />
<br />
Another often convenient way of finding the list of methods associated with an object, be it a Java object or an <span class="e">''E''</span> object or an object delivered as part of the <span class="e">''E''</span> runtime, is to use the help(object) function of <span class="e">''E''</span>, often used in rune.<br />
<br />
<pre><br />
<br />
<nowiki>? def add(a, b) {<br />
> return a + b<br />
> }<br />
# value: <add><br />
<br />
? help(add)<br />
# value: an org.erights.e.elang.evm.EImplByProxy<br />
# interface "__main$add" {<br />
#<br />
# to run(:any, :any) :any<br />
# }<br />
#<br />
?</nowiki><br />
<br />
</pre><br />
<br />
In this very simple example you see the "run" method listed here, which is the implicit method for a function. For a more sophisticated object than a simple add function, each method in the object would be listed as well.<br />
<br />
'''help/1''' doesn't show Miranda methods. To include them, use '''help/2''':<br />
<br />
<pre><br />
? help(add, true)<br />
# value: an org.erights.e.elang.evm.EImplByProxy<br />
# interface "__main$add" {<br />
# <br />
# /** Sugar method*/<br />
# to __conformTo(:nullOk[Guard]) :any<br />
# <br />
# /** Sugar method*/<br />
# to __getAllegedType() :nullOk[TypeDesc]<br />
...<br />
</pre></div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Interfacing_to_JavaWalnut/Ordinary Programming/Interfacing to Java2010-10-21T13:57:49Z<p>ThomasLeonard: /* Importing classes from the Java API */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Interfacing to Java===<br />
<br />
====Importing classes from the Java API====<br />
<br />
We can import a class from the underlying Java virtual machine with the import statement, and speak to the Java object much as we would speak to an E object: <span class="note" style="color:red">replace vector as example</span><br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#create a single vector with a direct call to Java<br />
def myVector := <unsafe:java.util.makeVector>()<br />
myVector.addElement("abc")<br />
<br />
#create a makeVector function which can be called repeatedly to make more vectors<br />
def makeVector := <unsafe:java.util.makeVector><br />
def vector2 := makeVector()<br />
<br />
# create a shorthand for the java.util package, that gives quick access to all the <br />
# classes in java.util<br />
def <util> := <unsafe:java.util.*><br />
def vector3 := <util:makeVector>()</nowiki><br />
</pre><br />
<br />
In the example, we showed 3 ways of getting a Java object, which are roughly comparable to the different styles of using "import" in Java. If you just want one vector, you can get it by directly calling the vector constructor. If you plan to make many vectors, you can import the class into a variable. And if you plan to use many classes in a particular package, you can create your own representative for the package that you can use instead of "&lt;unsafe&gt;".<br />
<br />
Note that the angle-brackets here are simply syntactic sugar: '''&lt;util&gt;''' is short for '''util__uriGetter''' and '''&lt;util:makeVector&gt;''' is short for '''util__uriGetter.get("makeVector")'''.<br />
<br />
Note also that E prefixes every Java class name with "make". The idea here is to make existing Java classes match the naming conventions of E constructors.<br />
<br />
We have now seen 3 uriGetters, file:, unsafe:, and the programmer-defined util:. Four other uriGetters are also predefined, swing: (for accessing javax.swing) and awt: (for accessing java.awt), resource: (for read-only access to resource files such as images, sounds, and static texts), and import:, described next.<br />
<br />
The import: uriGetter is similar to unsafe:, except it only imports those parts of the Java API that have been audited for capability security and found to convey no authority (see the Appendix for a definition of "authority").<br />
<br />
<font color="#FF0000">Put in link, think of better example. Remove vector from the book. Since the Vector class conveys no authority, you should be able to get a vector with import, but currently you can't.</font><br />
<br />
<pre><br />
def vector4 := <unsafe:java.util.makeVector>()<br />
</pre><br />
<br />
As discussed later with Library Packages and Secure Mobile Code, emakers cannot use unsafe: unless the unsafe__uriGetter is explicitly handed to them. So import: is often useful in these security-aware situations. A complete list of safe versus unsafe classes, and the small percentage of Java API methods which are suppressed for security reasons, are listed in the Appendix.<span class="note">link</span><br />
<br />
&lt;resource&gt; is considered safe, and can therefore be used directly in emakers.<br />
<br />
As noted earlier, <span class="e">''E''</span> does not have an expression to directly represent public static final variables. To use such static finals from a Java class, put parentheses at the end of the variable name, making it syntactically look like a function call, prefix it with "get", uppercase the first letter, and <span class="e">''E''</span> will get the value for you:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
<unsafe:java.util.makeCalendar>.getYEAR()</nowiki><br />
<br />
</pre><br />
<br />
====Speaking to Java objects with superclass/subclass overloaded methods====<br />
<br />
Speaking to Java objects is usually as easy as shown above, where we simply sent myVector an addElement(object) message as if it were an <span class="e">''E''</span> object. A problem arises with some Java objects if they have overloaded methods for which the only distinguishing mark is the static typing of the parameters in which one of the methods specifies a type that is a superclass of the type in the other method--a rare but not unheard-of situation. <span class="note" style="color:red">coercion causes same problem</span>In that case, we need to revert to a more descriptive messaging convention.<br />
<br />
We introduced the E.call() function earlier for communicating with E objects. It can also be used to call Java objects and to specify the signature of an overloaded method with the types of the parameters. In this example, we see that the print function for the System.out object is overloaded for both String and Object, with String being a subclass of Object, so the full signature is required:<br />
<br />
<pre><br />
<nowiki>? def out := <unsafe:java.lang.makeSystem>.getOut()<br />
# value: <a PrintStream><br />
<br />
? out.print("abc")<br />
# example problem: <IllegalArgumentException: ...><br />
<br />
? E.call(out, "print(String)", ["abc"])</nowiki><br />
</pre><br />
<br />
(Where should the following explanation go?)<br />
To use an example from awt: or swing:, we need our vat to be running with the AWT event loop. Normally this happens by running in a vat spawned to run a "*.e-awt" file. <tt>currentVat.morphInto("awt")</tt> asks the current vat to start executing instead in the awt event loop. It returns a promise which resolves to null or broken once this operation succeeds or fails. <tt>? interp.waitAtTop(p)</tt> pauses our interpreter (E's read-eval-print loop) until p is resolved.<br />
<br />
<pre><br />
? interp.waitAtTop(currentVat.morphInto("awt"))<br />
</pre><br />
<br />
Now that that's done, we can proceed to the next example.<br />
<br />
<pre><br />
<nowiki>? def myLabel := E.call(<swing:makeJLabel>, "run(String)",["label text"])</nowiki><br />
</pre><br />
<br />
If you encounter one of these special cases that requires multiple parameters, the signatures must be laid out with exact spelling and exact spacing, notably with exactly one space between the comma and the next signature:<br />
<br />
<pre><br />
E.call(javaObject, "method(String, int)", ["abc", 23])<br />
</pre><br />
<br />
====Arrays and primitive types====<br />
<br />
It is possible to make Java arrays of Java primitive types, as in this example:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeFlexList := <elib:tables.makeFlexList><br />
def byteArray := makeFlexList.fromType(<type:byte>, 300)<br />
byteArray.setSize(300)<br />
byteArray[0] := 3</nowiki><br />
<br />
</pre><br />
<br />
Here we have created a 300-element editable array of bytes. The individual elements can be accessed with square bracket notation.<br />
<br />
<font color="#FF0000">XXX Now that this example has been corrected, does it still serve its purpose? Also, it's not technically correct to say this makes a Java array. It makes an E FlexList, which, on E-on-Java, currently happens to be implemented by wrapping a Java array. However, if your program depends on this fact, it is probably broken. </font><br />
<br />
====Java Adapters and Interfaces====<br />
<br />
As described earlier, you can use the match[verb,args] construct to aid in writing adapters and other objects that must meet a Java interface specification. <span class="e">''E''</span> will automatically manipulate the resulting <span class="e">''E''</span> objects and the java virtual machine so that Java understands that the <span class="e">''E''</span> object meets the interface specification. It is not possible to make subclasses of Java classes in <span class="e">''E''</span>. However, because the developers of the Java API have wisely moved aggressively to make sure that interfaces, rather than subclasses, are core to Java object interoperability, there is virtually no Java interfacing goal that cannot be achieved with this machinery.<br />
<br />
====The Java API versus capability security====<br />
<br />
A final note: almost all of the objects and methods in the Java API are available in <span class="e">''E''</span> for version 1.0 through the unsafe_uriGetter; unfortunately very few have been audited sufficiently to be included with the import__uriGetter. In the future, more of the API will be accessible through the import__uriGetter; however, some parts of the Java API will be altered and/or suppressed even in unsafe__uriGetter to achieve a more secure yet easier to use computing framework. This is discussed further in the chapter on Mobile Code. You can see the list of suppressed methods and unsafe classes [http://www.erights.org/javadoc/index.html in the Javadoc].</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Interfacing_to_JavaWalnut/Ordinary Programming/Interfacing to Java2010-10-21T13:49:16Z<p>ThomasLeonard: /* Importing classes from the Java API */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Interfacing to Java===<br />
<br />
====Importing classes from the Java API====<br />
<br />
We can import a class from the underlying Java virtual machine with the import statement, and speak to the Java object much as we would speak to an E object: <span class="note" style="color:red">replace vector as example</span><br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#create a single vector with a direct call to Java<br />
def myVector := <unsafe:java.util.makeVector>()<br />
myVector.addElement("abc")<br />
<br />
#create a makeVector function which can be called repeatedly to make more vectors<br />
def makeVector := <unsafe:java.util.makeVector><br />
def vector2 := makeVector()<br />
<br />
# create a shorthand for the java.util package, that gives quick access to all the <br />
# classes in java.util<br />
def <util> := <unsafe:java.util.*><br />
def vector3 := <util:makeVector>()</nowiki><br />
</pre><br />
<br />
In the example, we showed 3 ways of getting a Java object, which are roughly comparable to the different styles of using "import" in Java. If you just want one vector, you can get it by directly calling the vector constructor. If you plan to make many vectors, you can import the class into a variable. And if you plan to use many classes in a particular package, you can create your own representative for the package that you can use instead of "&lt;unsafe&gt;".<br />
<br />
Note that the angle-brackets here are simply syntactic sugar: '''&lt;util&gt;''' is short for '''util__uriGetter''' and '''&lt;util:makeVector&gt;''' is short for '''util__uriGetter.get("makeVector")'''.<br />
<br />
Note also that E prefixes every Java class name with "make". The idea here is to make existing Java classes match the naming conventions of E constructors.<br />
<br />
We have now seen 3 uriGetters, file:, unsafe:, and the programmer-defined util:. Four other uriGetters are also predefined, swing: (for accessing javax.swing) and awt: (for accessing java.awt), resource: (for read-only access to resource files such as images, sounds, and static texts), and import:, described next.<br />
<br />
The import: uriGetter is similar to unsafe:, except it only imports those parts of the Java API that have been audited for capability security and found to convey no authority (see the Appendix for a definition of "authority").<span class="note">put in link, think of better example. Remove vector from the book</span> Since the Vector class <font color="#FF0000">conveys no authority, you could also get a vector with import</font><nowiki>:</nowiki><br />
<br />
<pre><br />
<br />
def vector4 := <unsafe:java.util.makeVector>()<br />
<br />
</pre><br />
<br />
As discussed later with Library Packages and Secure Mobile Code, emakers cannot use unsafe: unless the unsafe__uriGetter is explicitly handed to them. So import: is often useful in these security-aware situations. A complete list of safe versus unsafe classes, and the small percentage of Java API methods which are suppressed for security reasons, are listed in the Appendix.<span class="note">link</span><br />
<br />
resource: mention it is safe, can be used in emakers<br />
<br />
getting static public constants from Java: must put parens after the name as if it was a method returning a value, not a variable.<br />
<br />
As noted earlier, <span class="e">''E''</span> does not have an expression to directly represent public static final variables. To use such static finals from a Java class, put parentheses at the end of the variable name, making it syntactically look like a function call, prefix it with "get", uppercase the first letter, and <span class="e">''E''</span> will get the value for you:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
<unsafe:java.util.makeCalendar>.getYEAR()</nowiki><br />
<br />
</pre><br />
<br />
====Speaking to Java objects with superclass/subclass overloaded methods====<br />
<br />
Speaking to Java objects is usually as easy as shown above, where we simply sent myVector an addElement(object) message as if it were an <span class="e">''E''</span> object. A problem arises with some Java objects if they have overloaded methods for which the only distinguishing mark is the static typing of the parameters in which one of the methods specifies a type that is a superclass of the type in the other method--a rare but not unheard-of situation. <span class="note" style="color:red">coercion causes same problem</span>In that case, we need to revert to a more descriptive messaging convention.<br />
<br />
We introduced the E.call() function earlier for communicating with E objects. It can also be used to call Java objects and to specify the signature of an overloaded method with the types of the parameters. In this example, we see that the print function for the System.out object is overloaded for both String and Object, with String being a subclass of Object, so the full signature is required:<br />
<br />
<pre><br />
<nowiki>? def out := <unsafe:java.lang.makeSystem>.getOut()<br />
# value: <a PrintStream><br />
<br />
? out.print("abc")<br />
# example problem: <IllegalArgumentException: ...><br />
<br />
? E.call(out, "print(String)", ["abc"])</nowiki><br />
</pre><br />
<br />
(Where should the following explanation go?)<br />
To use an example from awt: or swing:, we need our vat to be running with the AWT event loop. Normally this happens by running in a vat spawned to run a "*.e-awt" file. <tt>currentVat.morphInto("awt")</tt> asks the current vat to start executing instead in the awt event loop. It returns a promise which resolves to null or broken once this operation succeeds or fails. <tt>? interp.waitAtTop(p)</tt> pauses our interpreter (E's read-eval-print loop) until p is resolved.<br />
<br />
<pre><br />
? interp.waitAtTop(currentVat.morphInto("awt"))<br />
</pre><br />
<br />
Now that that's done, we can proceed to the next example.<br />
<br />
<pre><br />
<nowiki>? def myLabel := E.call(<swing:makeJLabel>, "run(String)",["label text"])</nowiki><br />
</pre><br />
<br />
If you encounter one of these special cases that requires multiple parameters, the signatures must be laid out with exact spelling and exact spacing, notably with exactly one space between the comma and the next signature:<br />
<br />
<pre><br />
E.call(javaObject, "method(String, int)", ["abc", 23])<br />
</pre><br />
<br />
====Arrays and primitive types====<br />
<br />
It is possible to make Java arrays of Java primitive types, as in this example:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeFlexList := <elib:tables.makeFlexList><br />
def byteArray := makeFlexList.fromType(<type:byte>, 300)<br />
byteArray.setSize(300)<br />
byteArray[0] := 3</nowiki><br />
<br />
</pre><br />
<br />
Here we have created a 300-element editable array of bytes. The individual elements can be accessed with square bracket notation.<br />
<br />
<font color="#FF0000">XXX Now that this example has been corrected, does it still serve its purpose? Also, it's not technically correct to say this makes a Java array. It makes an E FlexList, which, on E-on-Java, currently happens to be implemented by wrapping a Java array. However, if your program depends on this fact, it is probably broken. </font><br />
<br />
====Java Adapters and Interfaces====<br />
<br />
As described earlier, you can use the match[verb,args] construct to aid in writing adapters and other objects that must meet a Java interface specification. <span class="e">''E''</span> will automatically manipulate the resulting <span class="e">''E''</span> objects and the java virtual machine so that Java understands that the <span class="e">''E''</span> object meets the interface specification. It is not possible to make subclasses of Java classes in <span class="e">''E''</span>. However, because the developers of the Java API have wisely moved aggressively to make sure that interfaces, rather than subclasses, are core to Java object interoperability, there is virtually no Java interfacing goal that cannot be achieved with this machinery.<br />
<br />
====The Java API versus capability security====<br />
<br />
A final note: almost all of the objects and methods in the Java API are available in <span class="e">''E''</span> for version 1.0 through the unsafe_uriGetter; unfortunately very few have been audited sufficiently to be included with the import__uriGetter. In the future, more of the API will be accessible through the import__uriGetter; however, some parts of the Java API will be altered and/or suppressed even in unsafe__uriGetter to achieve a more secure yet easier to use computing framework. This is discussed further in the chapter on Mobile Code. You can see the list of suppressed methods and unsafe classes [http://www.erights.org/javadoc/index.html in the Javadoc].</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Interfacing_to_JavaWalnut/Ordinary Programming/Interfacing to Java2010-10-21T13:48:05Z<p>ThomasLeonard: /* Interfacing to Java */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Interfacing to Java===<br />
<br />
====Importing classes from the Java API====<br />
<br />
We can import a class from the underlying Java virtual machine with the import statement, and speak to the Java object much as we would speak to an E object: <span class="note" style="color:red">replace vector as example</span><br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
#create a single vector with a direct call to Java<br />
def myVector := <unsafe:java.util.makeVector>()<br />
myVector.addElement("abc")<br />
<br />
#create a makeVector function which can be called repeatedly to make more vectors<br />
def makeVector := <unsafe:java.util.makeVector><br />
def vector2 := makeVector()<br />
<br />
# create a shorthand for the java.util package, that gives quick access to all the <br />
# classes in java.util<br />
def <util> := <unsafe:java.util.*><br />
def vector3 := <util:makeVector>()</nowiki><br />
</pre><br />
<br />
In the example, we showed 3 ways of getting a Java object, which are roughly comparable to the different styles of using "import" in Java. If you just want one vector, you can get it by directly calling the vector constructor. If you plan to make many vectors, you can import the class into a variable. And if you plan to use many classes in a particular package, you can create your own representative for the package that you can use instead of "&lt;unsafe&gt;".<br />
<br />
Note that the angle-brackets here are simply syntactic sugar: '''&lt;util&gt;'''; is short for '''util__uriGetter''' and '''&lt;util:makeVector&gt;''' is short for '''util__uriGetter.get("makeVector")'''.<br />
<br />
Note also that E prefixes every Java class name with "make". The idea here is to make existing Java classes match the naming conventions of E constructors.<br />
<br />
We have now seen 3 of these uriGetters, file:, unsafe:, and the programmer-defined util:. Four other uriGetters are also predefined, swing: (for accessing javax.swing) and awt: (for accessing java.awt), resource: (for read-only access to resource files such as images, sounds, and static texts), and import:, described next.<br />
<br />
The import: uriGetter is similar to unsafe:, except it only imports those parts of the Java API that have been audited for capability security and found to convey no authority (see the Appendix for a definition of "authority").<span class="note">put in link, think of better example. Remove vector from the book</span> Since the Vector class <font color="#FF0000">conveys no authority, you could also get a vector with import</font><nowiki>:</nowiki><br />
<br />
<pre><br />
<br />
def vector4 := <unsafe:java.util.makeVector>()<br />
<br />
</pre><br />
<br />
As discussed later with Library Packages and Secure Mobile Code, emakers cannot use unsafe: unless the unsafe__uriGetter is explicitly handed to them. So import: is often useful in these security-aware situations. A complete list of safe versus unsafe classes, and the small percentage of Java API methods which are suppressed for security reasons, are listed in the Appendix.<span class="note">link</span><br />
<br />
resource: mention it is safe, can be used in emakers<br />
<br />
getting static public constants from Java: must put parens after the name as if it was a method returning a value, not a variable.<br />
<br />
As noted earlier, <span class="e">''E''</span> does not have an expression to directly represent public static final variables. To use such static finals from a Java class, put parentheses at the end of the variable name, making it syntactically look like a function call, prefix it with "get", uppercase the first letter, and <span class="e">''E''</span> will get the value for you:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
<unsafe:java.util.makeCalendar>.getYEAR()</nowiki><br />
<br />
</pre><br />
<br />
====Speaking to Java objects with superclass/subclass overloaded methods====<br />
<br />
Speaking to Java objects is usually as easy as shown above, where we simply sent myVector an addElement(object) message as if it were an <span class="e">''E''</span> object. A problem arises with some Java objects if they have overloaded methods for which the only distinguishing mark is the static typing of the parameters in which one of the methods specifies a type that is a superclass of the type in the other method--a rare but not unheard-of situation. <span class="note" style="color:red">coercion causes same problem</span>In that case, we need to revert to a more descriptive messaging convention.<br />
<br />
We introduced the E.call() function earlier for communicating with E objects. It can also be used to call Java objects and to specify the signature of an overloaded method with the types of the parameters. In this example, we see that the print function for the System.out object is overloaded for both String and Object, with String being a subclass of Object, so the full signature is required:<br />
<br />
<pre><br />
<nowiki>? def out := <unsafe:java.lang.makeSystem>.getOut()<br />
# value: <a PrintStream><br />
<br />
? out.print("abc")<br />
# example problem: <IllegalArgumentException: ...><br />
<br />
? E.call(out, "print(String)", ["abc"])</nowiki><br />
</pre><br />
<br />
(Where should the following explanation go?)<br />
To use an example from awt: or swing:, we need our vat to be running with the AWT event loop. Normally this happens by running in a vat spawned to run a "*.e-awt" file. <tt>currentVat.morphInto("awt")</tt> asks the current vat to start executing instead in the awt event loop. It returns a promise which resolves to null or broken once this operation succeeds or fails. <tt>? interp.waitAtTop(p)</tt> pauses our interpreter (E's read-eval-print loop) until p is resolved.<br />
<br />
<pre><br />
? interp.waitAtTop(currentVat.morphInto("awt"))<br />
</pre><br />
<br />
Now that that's done, we can proceed to the next example.<br />
<br />
<pre><br />
<nowiki>? def myLabel := E.call(<swing:makeJLabel>, "run(String)",["label text"])</nowiki><br />
</pre><br />
<br />
If you encounter one of these special cases that requires multiple parameters, the signatures must be laid out with exact spelling and exact spacing, notably with exactly one space between the comma and the next signature:<br />
<br />
<pre><br />
E.call(javaObject, "method(String, int)", ["abc", 23])<br />
</pre><br />
<br />
====Arrays and primitive types====<br />
<br />
It is possible to make Java arrays of Java primitive types, as in this example:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeFlexList := <elib:tables.makeFlexList><br />
def byteArray := makeFlexList.fromType(<type:byte>, 300)<br />
byteArray.setSize(300)<br />
byteArray[0] := 3</nowiki><br />
<br />
</pre><br />
<br />
Here we have created a 300-element editable array of bytes. The individual elements can be accessed with square bracket notation.<br />
<br />
<font color="#FF0000">XXX Now that this example has been corrected, does it still serve its purpose? Also, it's not technically correct to say this makes a Java array. It makes an E FlexList, which, on E-on-Java, currently happens to be implemented by wrapping a Java array. However, if your program depends on this fact, it is probably broken. </font><br />
<br />
====Java Adapters and Interfaces====<br />
<br />
As described earlier, you can use the match[verb,args] construct to aid in writing adapters and other objects that must meet a Java interface specification. <span class="e">''E''</span> will automatically manipulate the resulting <span class="e">''E''</span> objects and the java virtual machine so that Java understands that the <span class="e">''E''</span> object meets the interface specification. It is not possible to make subclasses of Java classes in <span class="e">''E''</span>. However, because the developers of the Java API have wisely moved aggressively to make sure that interfaces, rather than subclasses, are core to Java object interoperability, there is virtually no Java interfacing goal that cannot be achieved with this machinery.<br />
<br />
====The Java API versus capability security====<br />
<br />
A final note: almost all of the objects and methods in the Java API are available in <span class="e">''E''</span> for version 1.0 through the unsafe_uriGetter; unfortunately very few have been audited sufficiently to be included with the import__uriGetter. In the future, more of the API will be accessible through the import__uriGetter; however, some parts of the Java API will be altered and/or suppressed even in unsafe__uriGetter to achieve a more secure yet easier to use computing framework. This is discussed further in the chapter on Mobile Code. You can see the list of suppressed methods and unsafe classes [http://www.erights.org/javadoc/index.html in the Javadoc].</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Objects_and_FunctionsWalnut/Ordinary Programming/Objects and Functions2010-10-21T13:37:08Z<p>ThomasLeonard: /* Objects and Functions */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Objects and Functions===<br />
<br />
As noted earlier, if the file is to use the Swing gui toolkit, it must have a suffix of ".e-awt". If the file is to use the SWT gui toolkit, it must have a suffix of ".e-swt". If the file will run headless, it should be placed in a file with suffix ".e".<br />
<br />
But first, we need to declare what version of E we're using here.<br />
<pre><br />
? pragma.syntax("0.9")<br />
</pre><br />
<br />
====Functions====<br />
<br />
A basic function looks like this:<br />
<br />
<pre># E sample<br />
def addNumbers(a,b) {<br />
return a + b<br />
}<br />
# Now use the function<br />
def answer := addNumbers(3,4)<br />
</pre><br />
<br />
You can nest the definitions of functions and objects inside other functions and objects, giving you functionality comparable to that of inner classes in Java. Nested functions and objects play a crucial role in <span class="e">''E''</span>, notably in the construction of objects as described shortly.<br />
<br />
A parameterless function must still have an open/close paren pair. Calls to parameterless functions must also include the parens.<br />
<br />
Functions can of course call themselves recursively, as in<br />
<br />
<pre># E sample<br />
def factorial(n) {<br />
if (n == 0) {<br />
return 1<br />
} else {<br />
return n * factorial(n-1)<br />
}<br />
}<br />
</pre><br />
<br />
====Dynamic "type checking" and Guards====<br />
<br />
<span class="e">''E''</span> guards perform many of the functions usually thought of as type checking, though they are so flexible, they also work as concise assertions. Guards can be placed on variables, parameters, and return values.<br />
<br />
Guards are not checked during compilation. They are checked during execution, and will throw exceptions if the value cannot be coerced to pass the guard. Guards play a key role in protecting the security properties when working with untrusted code, as discussed in Secure Distributed Computing.<br />
<br />
The available guards include the items below. Some of them are typical types (String, int). Others are used most often in distributed programming, and are explained later in the book. A detailed explanation of all the things you can do with guards is postponed to the [[Walnut/Aditional_Features|Aditional Features]] chapter.<br />
<br />
* int<br />
* char<br />
* float64<br />
* boolean<br />
* String<br />
* void<br />
* notNull<br />
* nullOk<br />
* near<br />
* vow<br />
* rcvr<br />
* pbc<br />
* Data<br />
* Java classes<br />
* <span class="e">''E''</span> interfaces<br />
* subranges and more complex expressions<br />
<br />
import weakpointermaker<br />
makevat 2 args 1)kind of vat, string"headless, awt, swt",<br />
2)name of vat for debugging<br />
import seedvatauthor<br />
authorize it to get a seedvat function with uri getter<br />
seedvat takes 2 args: 1)vat<br />
2)string that is contents of a dot-e file except<br />
all evaluated at once. seedvat function returns a promise for<br />
the result of evaluating that expression. since it evaluates in foreighn vat,<br />
it is a far reference.typical pattern: only do importing and construction <br />
in the expression string<br />
<br />
Here are some quick examples of guards being declared:<br />
<br />
<pre># E sample<br />
# guarding a variable<br />
def title :String := "abc"<br />
# guarding a parameter, and a return value. Note the guard on the <br />
# return value is part of the def line for the function.<br />
def reciprocal(x :float64) :float64 {<br />
return 1 / x<br />
}<br />
</pre><br />
<br />
Different people use different strategies about how much type checking/guard information to include in their programs. In this book, the general style is to use guards sparingly, as might be typical in a rapid prototyping environment. One place where guards must be used with rigor is in the objects on the boundaries between trust realms, in security aware applications; see the Powerbox pattern in the [[Walnut/Secure_Distributed_Computing|Secure Distributed Programming section]] for an important example.<br />
<br />
====Objects====<br />
<br />
Objects, and object constructors, look considerably different in <span class="e">''E''</span> than in Java or C++. We will start our exploration of objects with a simple singleton object.<br />
<br />
=====A Singleton Object=====<br />
<br />
Objects, functions, and variables are defined with the keyword "def"; all of these can be passed as arguments in parameter lists. Methods on an object, in contrast, are defined with the keyword "to":<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def origin {<br />
to getX() {return 0}<br />
to getY() {return 0}<br />
}<br />
# Now invoke the methods<br />
def myY := origin.getY()<br />
</nowiki><br />
<br />
</pre><br />
<br />
Like functions, methods require a parenthesis pair even if there are no arguments. ''(But, Python programmers beware, methods are not functions. Methods are just the public hooks to the object that receive messages; functions are standalone objects)''.<br />
<br />
When invoking the method, the object name and the method called are separated by a dot.<br />
<br />
=====Stateful objects and object constructors=====<br />
<br />
The "class" concept in Java is used to achieve multiple goals. In <span class="e">''E''</span>, these goals are factored out in a different way. For example, Java classes supply a place to put constructors, which have a special syntax unique to constructors. In <span class="e">''E''</span>, objects are constructed by ordinary functions.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Point constructor<br />
def makePoint(x,y) {<br />
def point {<br />
to getX() {return x}<br />
to getY() {return y}<br />
to makeOffsetPoint(offsetX, offsetY) {<br />
return makePoint(x + offsetX, y + offsetY)<br />
}<br />
to makeOffsetPoint(offset) {<br />
return makePoint(x + offset, y + offset)<br />
}<br />
} <br />
return point<br />
}<br />
# Create a point<br />
def origin := makePoint(0,0)<br />
# get the y value of the origin<br />
def y := origin.getY()</nowiki><br />
<br />
</pre><br />
<br />
Inside the function makePoint, we define a point and return it. As demonstrated by the makeOffsetPoint method, the function (makePoint) can be referenced from within its own body. Also note that you can overload method names (two versions of makeOffsetPoint) as long as they can be distinguished by the number of parameters they take.<br />
<br />
The (x, y) passed into the function are not ephemeral parameters that go out of existence when the function exits. Rather, they are true variables (implicitly declared with "def" ), and they persist as long as any of the objects that use them persist. Since the point uses these variables, x and y will exist as long as the point exists. This saves us the often tedious business in Java of copying the arguments from the parameter list into instance variables: x and y already are instance variables.<br />
<br />
We refer to an object-making function such as makePoint as a "Maker". Let us look at a more serious example, with additional instance variables:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(var name) {<br />
var x := 0<br />
var y := 0<br />
def car {<br />
to moveTo(newX,newY) {<br />
x := newX<br />
y := newY<br />
}<br />
to getX() {return x}<br />
to getY() {return y}<br />
to setName(newName) {name := newName}<br />
to getName() {return name}<br />
} <br />
return car<br />
}<br />
# Now use the makeCar function to make a car, which we will move and print<br />
def sportsCar := makeCar("Ferrari")<br />
sportsCar.moveTo(10,20)<br />
println(`The car ${sportsCar.getName()} is at X location ${sportsCar.getX()}`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
Inside the Maker, we create the instance variables for the object being made (x and y in this example), then we create the object (car). Note that the variable "name", passed into the function, is explicitly declared with "var", so that it can be altered later; in this case, it is reassigned in the setName() method.<br />
<br />
=====Self-referencing objects=====<br />
<br />
Sometimes in the body of an object you wish to refer to the object itself. A keyword like "this" is not required. The name given to the object is in scope in the body of the object, so just use it:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
var x := 0<br />
var y := 0<br />
def </nowiki>car {<br />
to moveDistance(newX,newY) {car.moveTo(x + newX, y + newY)}<br />
# ....define other methods including moveTo as above ....<br />
}<br />
return car<br />
}<br />
<br />
</pre><br />
<br />
What if you need to reference the object during the object's construction, i.e., during the creation of the instance variables that precedes the definition of the object itself? In the below example, we give the car a weatherReportRadio that is supposed to alert the car to changing weather conditions. This radio requires, as a parameter during its construction, the car it will be alerting. So the radio needs the car during radio construction, and the car needs the radio during car construction.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeRadio(car) {<br />
# define radios<br />
}<br />
def makeCar(name) { <br />
var x := 0 <br />
var y := 0<br />
# using def with no assignment<br />
def car<br />
def myWeatherRadio := makeRadio(car)<br />
bind car {<br />
to receiveWeatherAlert(myWeatherRadio) {<br />
# ....process the weather report....<br />
} <br />
to getX() {return x} <br />
to getY() {return y}<br />
# ....list the rest of the car methods....<br />
}<br />
return car<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here, we do a "def" of the car with no assignment, then we use the car, then we do a "bind" of the car which binds a value to the car. This looks and behaves like a "forward reference" from C. Under the covers, the statement "def car" creates a ''promise'' for the car, and the ''bind'' statement ''fulfills'' the promise. We discuss promises in greater depth in the [[Walnut/Distributed_Computing|Distributed Computing]] chapter, where they play a key role.<br />
<br />
=====Secret Life of Functions, Multiple Constructors and "Static Methods"=====<br />
<br />
Before we can talk about multiple constructors and the static-method-like behavior in <span class="e">''E''</span>, it is time to reveal the truth about <span class="e">''E''</span> functions. They are in fact simple objects with a single method, the "run" method, that is invoked by default if no other method is explicitly designated. For example, the following square function<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square(x) {return x*x}</nowiki><br />
<br />
</pre><br />
<br />
is really syntactic shorthand for<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square {<br />
to run(x) {return x*x}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
In the second one, the run() method is explicitly defined. Using this explicit form in a Maker function, you can define multiple constructors, discriminated by the number of parameters they receive. Similarly, by adding methods to the Maker other than "run" methods, you get other "static methods". In the example below, we have a queue Maker with 2 constructors and a non-constructor method. The one-argument constructor requires an initial capacity; the no-argument constructor supplies an initial capacity of 10.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeQueue {<br />
to run(initialCapacity) {<br />
# ....create a queue object with the specified initial capacity....<br />
}<br />
to run() {return makeQueue(makeQueue.getDEFAULT_CAPACITY())}<br />
to getDEFAULT_CAPACITY() {return 10}<br />
}<br />
# Now use both constructors<br />
def queue1 := makeQueue(100)<br />
def queue2 := makeQueue()<br />
println(`default capacity is: ${makeQueue.getDEFAULT_CAPACITY()}`)</nowiki><br />
<br />
</pre><br />
<br />
Note also that one can use methods such as getDEFAULT_CAPACITY() to achieve the same effect as Java achieves with public static final variables.<br />
<br />
====Polymorphism====<br />
<br />
<span class="e">''E''</span> enables polymorphism through method name matching. In this example, we move both a car and an airplane to a new location using a single common piece of code:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
def car {<br />
to moveTo(x, y) {<br />
# move the car<br />
}<br />
# other methods<br />
}<br />
return car<br />
}<br />
def makeJet(name) {<br />
def jet { <br />
to moveTo(x, y) { <br />
# move the jet, very different code from the code for car <br />
} <br />
# other methods <br />
} <br />
return jet<br />
}<br />
def vehicles := [makeCar("car"), makeJet("jet")]<br />
for each in vehicles {<br />
each.moveTo(3,4)<br />
} </nowiki><br />
<br />
</pre><br />
<br />
====Extends and Delegation====<br />
<br />
An object can refer calls to itself to another object (a "super-object", built by the "super-constructor", faintly similar to the way one uses superclasses in Java) using the ''extends'' keyword: <span class="note" style="color:red">think of better example</span><br />
<br />
<pre><br />
<br />
<nowiki>? def makePoint(x, y) { <br />
> def point { <br />
> to getX() {return x} <br />
> to getY() {return y}<br />
> to getMagnitude() {return (x*x + y*y)**0.5} <br />
> }<br />
> return point<br />
> } <br />
# value: <makePoint> <br />
<br />
? def makePoint3D(x,y,z) { <br />
> def point3D extends makePoint(x,y) { <br />
> to getZ() {return z} <br />
> to getMagnitude() {<br />
> def xy := super.getMagnitude()<br />
> return (z*z + xy*xy)**0.5<br />
> } <br />
> }<br />
> return point3D <br />
> } <br />
# value: <makePoint3D><br />
<br />
? def place := makePoint3D(1,2,3)<br />
# value: <point3D><br />
<br />
? def x := place.getX()<br />
# value: 1<br />
<br />
? def z := place.getZ()<br />
# value: 3</nowiki><br />
<br />
</pre><br />
<br />
Here makePoint3D acts as an extension of makePoint. Inside the ''extends'' clause, we run the makePoint constructor to create the Point upon which the Point3D will be built. This specially constructed point is referred to in the point3D definition as "super"; you can see super being used in the getMagnitude method.<br />
<br />
Using ''extends'' as described above follows the ''delegation'' pattern. Delegation is a simple pattern of object composition in which an object says, "if another object calls me with a method that I don't have defined here, just route the message to this other object, and send the result back to the caller." Delegation is similar to inheritance, but it is conceptually simpler.<br />
<br />
====Extends and Full Inheritance====<br />
<br />
Some experts consider inheritance to be a dangerous feature. A discussion of the pros and cons of inheritance is beyond the scope of this book. However, none of the full-blown examples in this book actually use full inheritance. Delegation, via the simple ''extends'' keyword plus polymorphism serve most of the purposes for which inheritance was intended, and is used everywhere here.<br />
<br />
Having said that, there are times and places where full inheritance is the right answer. The ''extends'' keyword is also used, with one additional convention, to support such full inheritance. In inheritance, the "self" to which a super-object refers is the sub-object of which it is a part, so that the super-object can use methods in the sub-object:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def makeVehicle(self) {<br />
def vehicle {<br />
to milesTillEmpty() {<br />
return self.milesPerGallon() * self.getFuelRemaining()<br />
}<br />
}<br />
return vehicle<br />
}<br />
<br />
def makeCar() {<br />
var fuelRemaining := 20<br />
def car extends makeVehicle(car) {<br />
to milesPerGallon() {return 19}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return car<br />
}<br />
<br />
def makeJet() {<br />
var fuelRemaining := 2000<br />
def jet extends makeVehicle(jet) {<br />
to milesPerGallon() {return 2}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return jet<br />
}<br />
<br />
def car := makeCar()<br />
println(`The car can go ${car.milesTillEmpty()} miles.`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
As seen in the example, the super-object constructor specifies a parameter, "self", which can be used to refer to the sub-object. The sub-object includes itself in the the call to the super-object constructor, thus becoming "self".<br />
<br />
====E Interfaces====<br />
<br />
You can define an interface like this:<br />
<br />
interface Foo {<br />
}<br />
<br />
def foo implements Foo {<br />
}<br />
<br />
foo :Foo<br />
<br />
The interface body can contain method signatures (without bodies).<br />
<br />
When an object is declared as "implements Foo", Foo acts as a "rubber-stamping" auditor, which marks the object as implementing the interface (whether or not it implements any of the methods defined in the interface). When Foo is used as a guard, it checks that the object was stamped by the auditor.<br />
<br />
This allows your module to give out objects and recognise them when they are given back later. However, this cannot be used for security purposes because the interface (Foo) cannot be kept secret. This is because when a non-Foo object is checked with the Foo guard, object.__conformTo(Foo) is called. <br />
<br />
The two functions of Foo (guard and auditor) may be split up using this syntax:<br />
<br />
interface FooGuard guards FooAuditor { }<br />
<br />
def foo implements FooAuditor { ... }<br />
<br />
foo :FooGuard<br />
<br />
This allows the guard to be given out freely while the auditor is closely held, preventing others from creating fake Foo objects but allowing anyone to check that a given object is a genuine Foo.<br />
<br />
Presumably, you could also implement a public auditor that actually performed some kind of check on an object, and then used the rubber-stamping auditor to stamp it if it passed the checks [how?].<br />
<br />
The interface construct is likely to change in future[http://www.eros-os.org/pipermail/e-lang/2010-February/013432.html].<br />
<br />
====General method name matching and E.call()====<br />
<br />
Delegation with extends does a straight pass-through of the method call. It is possible to intercept collections of calls before delegating them, using ''match''. In this example, we count the number of calls made to a car:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCalledCountCar(name) {<br />
def myCar := makeCar(name) <br />
var myCallCount := 0<br />
def car {<br />
to getCallCount() {return myCallCount}<br />
match [verb,args] {<br />
myCallCount += 1<br />
E.call(myCar,verb,args)<br />
}<br />
}<br />
return car<br />
} </nowiki><br />
<br />
</pre><br />
<br />
In "match[verb,args]", the verb is a string specifying the name of the method being called, and the args is a list of arguments. If the car is called with a method that is not defined in a "to" statement, the name of the method and the arguments are bound to the variables inside the square brackets. We then increment the call count, and finally forward the message using the E.call function. E.call(...) takes as arguments the target object for the action, the name of the method to call, and the list of arguments for the method to invoke. You can manually use E.call() like this:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def car := makeCar("mercedes")<br />
E.call(car, "moveTo", [3,4])<br />
# which is equivalent to<br />
car.moveTo(3,4)</nowiki><br />
<br />
</pre><br />
<br />
In this example, the elements for the argument list are placed in square brackets to form an <span class="e">''E''</span> ConstList, described later in this chapter.<br />
<br />
The match construct is useful for making "adapters" when interfacing to Java. Here we build a singleton object that can be used anywhere a java.awt.event.MouseListener would be used; the match clause is used to absorb and discard events in which we are not interested:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def mouseListener {<br />
to mouseClicked(event) {<br />
# process the event<br />
}<br />
match [verb,args] {}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
This general purpose matching is also useful in security applications when building facets and revocable capabilities, as described in the chapter on Secure Distributed Computing.<br />
<br />
====Edoc, the <span class="e">''E''</span> equivalent of JavaDoc====<br />
<br />
E supports the construction of javadoc-style comments that can be postprocessed into HTML documentation. For this purpose, the "/** ... */" comment format has been specially reserved; comments of this style can only appear in front of a function/object definition (a "def" statement), or in front of an object method definition (a "to" statement):<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
/**<br />
* Add 2 numbers together.<br />
* <p><br />
* Currently works with any objects that support the "plus" method<br />
*<br />
* @param a the first number. <br />
* @param b the second number<br />
* @return the result of adding. <br />
*/<br />
def adder(a, b) {return a + b}</nowiki><br />
<br />
</pre><br />
<br />
For more information on how to generate Edoc HTML from your <span class="e">''E''</span> programs, see the [[Walnut/Additional_Features|Additional Features]].<br />
<br />
====Under the covers: Everything is an Object====<br />
<br />
We have already discussed the fact that functions are really objects with a single method, "run". Functions-as-objects have one practical consequence that would be surprising in the absence of understanding. You cannot create two functions with different numbers of parameters and have them overloaded:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def times2(a) {return a * 2}<br />
def compute(a,b) {<br />
def times2(c,d) {return (c + d) * 2}<br />
# ....do computation...<br />
# The following line will throw an exception<br />
def answer := times2(a)<br />
return answer<br />
}</nowiki><br />
<br />
</pre><br />
<br />
<font color="#FF0000">This would throw an exception because the inner definition of the function-like object times2 completely shadows the outer times2.</font><br />
<br />
Not only functions, but also built-in constants like integers and floats, are objects. Operators such as "+" are really shorthands for message passing: 3.add(4) is identical to 3 + 4. This is why the operation<br />
<br />
<pre>"The number is " + 1</pre><br />
<br />
works but<br />
<br />
<pre>1 + " is the number"</pre><br />
<br />
does not. A string knows how to handle a concatenate message with a number as the argument, but an integer is clueless what to do with an add of a string.<br />
<br />
Since "+" is really just shorthand for "add", you can construct objects that work with the "+" operator just by implementing an "add(argument)" method in the object.<br />
<br />
====Under the covers: Miranda Methods====<br />
<br />
There are a number of messages to which all normal objects respond, known as Miranda Methods. One example of such a method is the printOn(textWriter) method, which defines how an object will write itself out as by default. Other Miranda methods will be described in other sections of the book. The full list of Miranda methods can be found in the Appendix. You can also see them in rune by typing help(def obj{}) <span class="note" style="red">duplicate of next section, fix</span><br />
<br />
One important note about Miranda methods: they are not forwarded by the ''extends'' structure, and they are not intercepted by the match[verb,args] structure. They are always directly interpreted by the object that receives them.<br />
<br />
====Under the covers: Kernel-E====<br />
<br />
When you enter a normal E expression, E expands it into a more primitive form called ''Kernel-E''. If you're ever confused about some E syntax, viewing the Kernel-E expansion may help you to understand what it means. To make rune display the Kernel-E:<br />
<br />
<pre>? interp.setExpand(true)</pre><br />
<br />
Then:<br />
<br />
<pre><br />
? 1+1<br />
# expansion: 1.add(1)<br />
<br />
# value: 2<br />
<br />
? <type:java.lang.String><br />
# expansion: type__uriGetter.get("java.lang.String")<br />
<br />
# value: String<br />
</pre><br />
<br />
<br />
====Getting Help About an Object With Rune====<br />
<br />
Another often convenient way of finding the list of methods associated with an object, be it a Java object or an <span class="e">''E''</span> object or an object delivered as part of the <span class="e">''E''</span> runtime, is to use the help(object) function of <span class="e">''E''</span>, often used in rune.<br />
<br />
<pre><br />
<br />
<nowiki>? def add(a, b) {<br />
> return a + b<br />
> }<br />
# value: <add><br />
<br />
? help(add)<br />
# value: an org.erights.e.elang.evm.EImplByProxy<br />
# interface "__main$add" {<br />
#<br />
# to run(:any, :any) :any<br />
# }<br />
#<br />
?</nowiki><br />
<br />
</pre><br />
<br />
In this very simple example you see the "run" method listed here, which is the implicit method for a function. The rest of the methods shown are Miranda methods. For a more sophisticated object than a simple add function, each method in the object would be listed as well.</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Objects_and_FunctionsWalnut/Ordinary Programming/Objects and Functions2010-10-21T13:32:25Z<p>ThomasLeonard: /* Under the covers: Everything is an Object */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Objects and Functions===<br />
<br />
As noted earlier, if the file is to use the Swing gui toolkit, it must have a suffix of ".e-awt". If the file is to use the SWT gui toolkit, it must have a suffix of ".e-swt". If the file will run headless, it should be placed in a file with suffix ".e".<br />
<br />
But first, we need to declare what version of E we're using here.<br />
<pre><br />
? pragma.syntax("0.9")<br />
</pre><br />
<br />
====Functions====<br />
<br />
A basic function looks like this:<br />
<br />
<pre># E sample<br />
def addNumbers(a,b) {<br />
return a + b<br />
}<br />
# Now use the function<br />
def answer := addNumbers(3,4)<br />
</pre><br />
<br />
You can nest the definitions of functions and objects inside other functions and objects, giving you functionality comparable to that of inner classes in Java. Nested functions and objects play a crucial role in <span class="e">''E''</span>, notably in the construction of objects as described shortly.<br />
<br />
A parameterless function must still have an open/close paren pair. Calls to parameterless functions must also include the parens.<br />
<br />
Functions can of course call themselves recursively, as in<br />
<br />
<pre># E sample<br />
def factorial(n) {<br />
if (n == 0) {<br />
return 1<br />
} else {<br />
return n * factorial(n-1)<br />
}<br />
}<br />
</pre><br />
<br />
====Dynamic "type checking" and Guards====<br />
<br />
<span class="e">''E''</span> guards perform many of the functions usually thought of as type checking, though they are so flexible, they also work as concise assertions. Guards can be placed on variables, parameters, and return values.<br />
<br />
Guards are not checked during compilation. They are checked during execution, and will throw exceptions if the value cannot be coerced to pass the guard. Guards play a key role in protecting the security properties when working with untrusted code, as discussed in Secure Distributed Computing.<br />
<br />
The available guards include the items below. Some of them are typical types (String, int). Others are used most often in distributed programming, and are explained later in the book. A detailed explanation of all the things you can do with guards is postponed to the [[Walnut/Aditional_Features|Aditional Features]] chapter.<br />
<br />
* int<br />
* char<br />
* float64<br />
* boolean<br />
* String<br />
* void<br />
* notNull<br />
* nullOk<br />
* near<br />
* vow<br />
* rcvr<br />
* pbc<br />
* Data<br />
* Java classes<br />
* <span class="e">''E''</span> interfaces<br />
* subranges and more complex expressions<br />
<br />
import weakpointermaker<br />
makevat 2 args 1)kind of vat, string"headless, awt, swt",<br />
2)name of vat for debugging<br />
import seedvatauthor<br />
authorize it to get a seedvat function with uri getter<br />
seedvat takes 2 args: 1)vat<br />
2)string that is contents of a dot-e file except<br />
all evaluated at once. seedvat function returns a promise for<br />
the result of evaluating that expression. since it evaluates in foreighn vat,<br />
it is a far reference.typical pattern: only do importing and construction <br />
in the expression string<br />
<br />
Here are some quick examples of guards being declared:<br />
<br />
<pre># E sample<br />
# guarding a variable<br />
def title :String := "abc"<br />
# guarding a parameter, and a return value. Note the guard on the <br />
# return value is part of the def line for the function.<br />
def reciprocal(x :float64) :float64 {<br />
return 1 / x<br />
}<br />
</pre><br />
<br />
Different people use different strategies about how much type checking/guard information to include in their programs. In this book, the general style is to use guards sparingly, as might be typical in a rapid prototyping environment. One place where guards must be used with rigor is in the objects on the boundaries between trust realms, in security aware applications; see the Powerbox pattern in the [[Walnut/Secure_Distributed_Computing|Secure Distributed Programming section]] for an important example.<br />
<br />
====Objects====<br />
<br />
Objects, and object constructors, look considerably different in <span class="e">''E''</span> than in Java or C++. We will start our exploration of objects with a simple singleton object.<br />
<br />
=====A Singleton Object=====<br />
<br />
Objects, functions, and variables are defined with the keyword "def"; all of these can be passed as arguments in parameter lists. Methods on an object, in contrast, are defined with the keyword "to":<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def origin {<br />
to getX() {return 0}<br />
to getY() {return 0}<br />
}<br />
# Now invoke the methods<br />
def myY := origin.getY()<br />
</nowiki><br />
<br />
</pre><br />
<br />
Like functions, methods require a parenthesis pair even if there are no arguments. ''(But, Python programmers beware, methods are not functions. Methods are just the public hooks to the object that receive messages; functions are standalone objects)''.<br />
<br />
When invoking the method, the object name and the method called are separated by a dot.<br />
<br />
=====Stateful objects and object constructors=====<br />
<br />
The "class" concept in Java is used to achieve multiple goals. In <span class="e">''E''</span>, these goals are factored out in a different way. For example, Java classes supply a place to put constructors, which have a special syntax unique to constructors. In <span class="e">''E''</span>, objects are constructed by ordinary functions.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Point constructor<br />
def makePoint(x,y) {<br />
def point {<br />
to getX() {return x}<br />
to getY() {return y}<br />
to makeOffsetPoint(offsetX, offsetY) {<br />
return makePoint(x + offsetX, y + offsetY)<br />
}<br />
to makeOffsetPoint(offset) {<br />
return makePoint(x + offset, y + offset)<br />
}<br />
} <br />
return point<br />
}<br />
# Create a point<br />
def origin := makePoint(0,0)<br />
# get the y value of the origin<br />
def y := origin.getY()</nowiki><br />
<br />
</pre><br />
<br />
Inside the function makePoint, we define a point and return it. As demonstrated by the makeOffsetPoint method, the function (makePoint) can be referenced from within its own body. Also note that you can overload method names (two versions of makeOffsetPoint) as long as they can be distinguished by the number of parameters they take.<br />
<br />
The (x, y) passed into the function are not ephemeral parameters that go out of existence when the function exits. Rather, they are true variables (implicitly declared with "def" ), and they persist as long as any of the objects that use them persist. Since the point uses these variables, x and y will exist as long as the point exists. This saves us the often tedious business in Java of copying the arguments from the parameter list into instance variables: x and y already are instance variables.<br />
<br />
We refer to an object-making function such as makePoint as a "Maker". Let us look at a more serious example, with additional instance variables:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(var name) {<br />
var x := 0<br />
var y := 0<br />
def car {<br />
to moveTo(newX,newY) {<br />
x := newX<br />
y := newY<br />
}<br />
to getX() {return x}<br />
to getY() {return y}<br />
to setName(newName) {name := newName}<br />
to getName() {return name}<br />
} <br />
return car<br />
}<br />
# Now use the makeCar function to make a car, which we will move and print<br />
def sportsCar := makeCar("Ferrari")<br />
sportsCar.moveTo(10,20)<br />
println(`The car ${sportsCar.getName()} is at X location ${sportsCar.getX()}`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
Inside the Maker, we create the instance variables for the object being made (x and y in this example), then we create the object (car). Note that the variable "name", passed into the function, is explicitly declared with "var", so that it can be altered later; in this case, it is reassigned in the setName() method.<br />
<br />
=====Self-referencing objects=====<br />
<br />
Sometimes in the body of an object you wish to refer to the object itself. A keyword like "this" is not required. The name given to the object is in scope in the body of the object, so just use it:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
var x := 0<br />
var y := 0<br />
def </nowiki>car {<br />
to moveDistance(newX,newY) {car.moveTo(x + newX, y + newY)}<br />
# ....define other methods including moveTo as above ....<br />
}<br />
return car<br />
}<br />
<br />
</pre><br />
<br />
What if you need to reference the object during the object's construction, i.e., during the creation of the instance variables that precedes the definition of the object itself? In the below example, we give the car a weatherReportRadio that is supposed to alert the car to changing weather conditions. This radio requires, as a parameter during its construction, the car it will be alerting. So the radio needs the car during radio construction, and the car needs the radio during car construction.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeRadio(car) {<br />
# define radios<br />
}<br />
def makeCar(name) { <br />
var x := 0 <br />
var y := 0<br />
# using def with no assignment<br />
def car<br />
def myWeatherRadio := makeRadio(car)<br />
bind car {<br />
to receiveWeatherAlert(myWeatherRadio) {<br />
# ....process the weather report....<br />
} <br />
to getX() {return x} <br />
to getY() {return y}<br />
# ....list the rest of the car methods....<br />
}<br />
return car<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here, we do a "def" of the car with no assignment, then we use the car, then we do a "bind" of the car which binds a value to the car. This looks and behaves like a "forward reference" from C. Under the covers, the statement "def car" creates a ''promise'' for the car, and the ''bind'' statement ''fulfills'' the promise. We discuss promises in greater depth in the [[Walnut/Distributed_Computing|Distributed Computing]] chapter, where they play a key role.<br />
<br />
=====Secret Life of Functions, Multiple Constructors and "Static Methods"=====<br />
<br />
Before we can talk about multiple constructors and the static-method-like behavior in <span class="e">''E''</span>, it is time to reveal the truth about <span class="e">''E''</span> functions. They are in fact simple objects with a single method, the "run" method, that is invoked by default if no other method is explicitly designated. For example, the following square function<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square(x) {return x*x}</nowiki><br />
<br />
</pre><br />
<br />
is really syntactic shorthand for<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square {<br />
to run(x) {return x*x}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
In the second one, the run() method is explicitly defined. Using this explicit form in a Maker function, you can define multiple constructors, discriminated by the number of parameters they receive. Similarly, by adding methods to the Maker other than "run" methods, you get other "static methods". In the example below, we have a queue Maker with 2 constructors and a non-constructor method. The one-argument constructor requires an initial capacity; the no-argument constructor supplies an initial capacity of 10.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeQueue {<br />
to run(initialCapacity) {<br />
# ....create a queue object with the specified initial capacity....<br />
}<br />
to run() {return makeQueue(makeQueue.getDEFAULT_CAPACITY())}<br />
to getDEFAULT_CAPACITY() {return 10}<br />
}<br />
# Now use both constructors<br />
def queue1 := makeQueue(100)<br />
def queue2 := makeQueue()<br />
println(`default capacity is: ${makeQueue.getDEFAULT_CAPACITY()}`)</nowiki><br />
<br />
</pre><br />
<br />
Note also that one can use methods such as getDEFAULT_CAPACITY() to achieve the same effect as Java achieves with public static final variables.<br />
<br />
====Polymorphism====<br />
<br />
<span class="e">''E''</span> enables polymorphism through method name matching. In this example, we move both a car and an airplane to a new location using a single common piece of code:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
def car {<br />
to moveTo(x, y) {<br />
# move the car<br />
}<br />
# other methods<br />
}<br />
return car<br />
}<br />
def makeJet(name) {<br />
def jet { <br />
to moveTo(x, y) { <br />
# move the jet, very different code from the code for car <br />
} <br />
# other methods <br />
} <br />
return jet<br />
}<br />
def vehicles := [makeCar("car"), makeJet("jet")]<br />
for each in vehicles {<br />
each.moveTo(3,4)<br />
} </nowiki><br />
<br />
</pre><br />
<br />
====Extends and Delegation====<br />
<br />
An object can refer calls to itself to another object (a "super-object", built by the "super-constructor", faintly similar to the way one uses superclasses in Java) using the ''extends'' keyword: <span class="note" style="color:red">think of better example</span><br />
<br />
<pre><br />
<br />
<nowiki>? def makePoint(x, y) { <br />
> def point { <br />
> to getX() {return x} <br />
> to getY() {return y}<br />
> to getMagnitude() {return (x*x + y*y)**0.5} <br />
> }<br />
> return point<br />
> } <br />
# value: <makePoint> <br />
<br />
? def makePoint3D(x,y,z) { <br />
> def point3D extends makePoint(x,y) { <br />
> to getZ() {return z} <br />
> to getMagnitude() {<br />
> def xy := super.getMagnitude()<br />
> return (z*z + xy*xy)**0.5<br />
> } <br />
> }<br />
> return point3D <br />
> } <br />
# value: <makePoint3D><br />
<br />
? def place := makePoint3D(1,2,3)<br />
# value: <point3D><br />
<br />
? def x := place.getX()<br />
# value: 1<br />
<br />
? def z := place.getZ()<br />
# value: 3</nowiki><br />
<br />
</pre><br />
<br />
Here makePoint3D acts as an extension of makePoint. Inside the ''extends'' clause, we run the makePoint constructor to create the Point upon which the Point3D will be built. This specially constructed point is referred to in the point3D definition as "super"; you can see super being used in the getMagnitude method.<br />
<br />
Using ''extends'' as described above follows the ''delegation'' pattern. Delegation is a simple pattern of object composition in which an object says, "if another object calls me with a method that I don't have defined here, just route the message to this other object, and send the result back to the caller." Delegation is similar to inheritance, but it is conceptually simpler.<br />
<br />
====Extends and Full Inheritance====<br />
<br />
Some experts consider inheritance to be a dangerous feature. A discussion of the pros and cons of inheritance is beyond the scope of this book. However, none of the full-blown examples in this book actually use full inheritance. Delegation, via the simple ''extends'' keyword plus polymorphism serve most of the purposes for which inheritance was intended, and is used everywhere here.<br />
<br />
Having said that, there are times and places where full inheritance is the right answer. The ''extends'' keyword is also used, with one additional convention, to support such full inheritance. In inheritance, the "self" to which a super-object refers is the sub-object of which it is a part, so that the super-object can use methods in the sub-object:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def makeVehicle(self) {<br />
def vehicle {<br />
to milesTillEmpty() {<br />
return self.milesPerGallon() * self.getFuelRemaining()<br />
}<br />
}<br />
return vehicle<br />
}<br />
<br />
def makeCar() {<br />
var fuelRemaining := 20<br />
def car extends makeVehicle(car) {<br />
to milesPerGallon() {return 19}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return car<br />
}<br />
<br />
def makeJet() {<br />
var fuelRemaining := 2000<br />
def jet extends makeVehicle(jet) {<br />
to milesPerGallon() {return 2}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return jet<br />
}<br />
<br />
def car := makeCar()<br />
println(`The car can go ${car.milesTillEmpty()} miles.`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
As seen in the example, the super-object constructor specifies a parameter, "self", which can be used to refer to the sub-object. The sub-object includes itself in the the call to the super-object constructor, thus becoming "self".<br />
<br />
====E Interfaces====<br />
<br />
You can define an interface like this:<br />
<br />
interface Foo {<br />
}<br />
<br />
def foo implements Foo {<br />
}<br />
<br />
foo :Foo<br />
<br />
The interface body can contain method signatures (without bodies).<br />
<br />
When an object is declared as "implements Foo", Foo acts as a "rubber-stamping" auditor, which marks the object as implementing the interface (whether or not it implements any of the methods defined in the interface). When Foo is used as a guard, it checks that the object was stamped by the auditor.<br />
<br />
This allows your module to give out objects and recognise them when they are given back later. However, this cannot be used for security purposes because the interface (Foo) cannot be kept secret. This is because when a non-Foo object is checked with the Foo guard, object.__conformTo(Foo) is called. <br />
<br />
The two functions of Foo (guard and auditor) may be split up using this syntax:<br />
<br />
interface FooGuard guards FooAuditor { }<br />
<br />
def foo implements FooAuditor { ... }<br />
<br />
foo :FooGuard<br />
<br />
This allows the guard to be given out freely while the auditor is closely held, preventing others from creating fake Foo objects but allowing anyone to check that a given object is a genuine Foo.<br />
<br />
Presumably, you could also implement a public auditor that actually performed some kind of check on an object, and then used the rubber-stamping auditor to stamp it if it passed the checks [how?].<br />
<br />
The interface construct is likely to change in future[http://www.eros-os.org/pipermail/e-lang/2010-February/013432.html].<br />
<br />
====General method name matching and E.call()====<br />
<br />
Delegation with extends does a straight pass-through of the method call. It is possible to intercept collections of calls before delegating them, using ''match''. In this example, we count the number of calls made to a car:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCalledCountCar(name) {<br />
def myCar := makeCar(name) <br />
var myCallCount := 0<br />
def car {<br />
to getCallCount() {return myCallCount}<br />
match [verb,args] {<br />
myCallCount += 1<br />
E.call(myCar,verb,args)<br />
}<br />
}<br />
return car<br />
} </nowiki><br />
<br />
</pre><br />
<br />
In "match[verb,args]", the verb is a string specifying the name of the method being called, and the args is a list of arguments. If the car is called with a method that is not defined in a "to" statement, the name of the method and the arguments are bound to the variables inside the square brackets. We then increment the call count, and finally forward the message using the E.call function. E.call(...) takes as arguments the target object for the action, the name of the method to call, and the list of arguments for the method to invoke. You can manually use E.call() like this:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def car := makeCar("mercedes")<br />
E.call(car, "moveTo", [3,4])<br />
# which is equivalent to<br />
car.moveTo(3,4)</nowiki><br />
<br />
</pre><br />
<br />
In this example, the elements for the argument list are placed in square brackets to form an <span class="e">''E''</span> ConstList, described later in this chapter.<br />
<br />
The match construct is useful for making "adapters" when interfacing to Java. Here we build a singleton object that can be used anywhere a java.awt.event.MouseListener would be used; the match clause is used to absorb and discard events in which we are not interested:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def mouseListener {<br />
to mouseClicked(event) {<br />
# process the event<br />
}<br />
match [verb,args] {}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
This general purpose matching is also useful in security applications when building facets and revocable capabilities, as described in the chapter on Secure Distributed Computing.<br />
<br />
====Edoc, the <span class="e">''E''</span> equivalent of JavaDoc====<br />
<br />
E supports the construction of javadoc-style comments that can be postprocessed into HTML documentation. For this purpose, the "/** ... */" comment format has been specially reserved; comments of this style can only appear in front of a function/object definition (a "def" statement), or in front of an object method definition (a "to" statement):<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
/**<br />
* Add 2 numbers together.<br />
* <p><br />
* Currently works with any objects that support the "plus" method<br />
*<br />
* @param a the first number. <br />
* @param b the second number<br />
* @return the result of adding. <br />
*/<br />
def adder(a, b) {return a + b}</nowiki><br />
<br />
</pre><br />
<br />
For more information on how to generate Edoc HTML from your <span class="e">''E''</span> programs, see the [[Walnut/Additional_Features|Additional Features]].<br />
<br />
====Under the covers: Everything is an Object====<br />
<br />
We have already discussed the fact that functions are really objects with a single method, "run". Functions-as-objects have one practical consequence that would be surprising in the absence of understanding. You cannot create two functions with different numbers of parameters and have them overloaded:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def times2(a) {return a * 2}<br />
def compute(a,b) {<br />
def times2(c,d) {return (c + d) * 2}<br />
# ....do computation...<br />
# The following line will throw an exception<br />
def answer := times2(a)<br />
return answer<br />
}</nowiki><br />
<br />
</pre><br />
<br />
<font color="#FF0000">This would throw an exception because the inner definition of the function-like object times2 completely shadows the outer times2.</font><br />
<br />
Not only functions, but also built-in constants like integers and floats, are objects. Operators such as "+" are really shorthands for message passing: 3.add(4) is identical to 3 + 4. This is why the operation<br />
<br />
<pre>"The number is " + 1</pre><br />
<br />
works but<br />
<br />
<pre>1 + " is the number"</pre><br />
<br />
does not. A string knows how to handle a concatenate message with a number as the argument, but an integer is clueless what to do with an add of a string.<br />
<br />
Since "+" is really just shorthand for "add", you can construct objects that work with the "+" operator just by implementing an "add(argument)" method in the object.<br />
<br />
====Under the covers: Miranda Methods====<br />
<br />
There are a number of messages to which all normal objects respond, known as Miranda Methods. One example of such a method is the printOn(textWriter) method, which defines how an object will write itself out as by default. Other Miranda methods will be described in other sections of the book. The full list of Miranda methods can be found in the Appendix. You can also see them in rune by typing help(def obj{}) <span class="note" style="red">duplicate of next section, fix</span><br />
<br />
One important note about Miranda methods: they are not forwarded by the ''extends'' structure, and they are not intercepted by the match[verb,args] structure. They are always directly interpreted by the object that receives them.<br />
<br />
====Getting Help About an Object With Rune====<br />
<br />
Another often convenient way of finding the list of methods associated with an object, be it a Java object or an <span class="e">''E''</span> object or an object delivered as part of the <span class="e">''E''</span> runtime, is to use the help(object) function of <span class="e">''E''</span>, often used in rune.<br />
<br />
<pre><br />
<br />
<nowiki>? def add(a, b) {<br />
> return a + b<br />
> }<br />
# value: <add><br />
<br />
? help(add)<br />
# value: an org.erights.e.elang.evm.EImplByProxy<br />
# interface "__main$add" {<br />
#<br />
# to run(:any, :any) :any<br />
# }<br />
#<br />
?</nowiki><br />
<br />
</pre><br />
<br />
In this very simple example you see the "run" method listed here, which is the implicit method for a function. The rest of the methods shown are Miranda methods. For a more sophisticated object than a simple add function, each method in the object would be listed as well.</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Data_StructuresWalnut/Ordinary Programming/Data Structures2010-09-17T15:44:06Z<p>ThomasLeonard: /* Flex and Const, List, Map and Set */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
===Data Structures===<br />
<br />
In the next section, we will learn how to interface to Java, which will allow you to use most of the data structures supplied by the underlying jvm. E does offer a few data structures of its own, however, which are not only convenient, but which have special properties useful in distributed programming.<br />
<br />
====Flex and Const, List, Map and Set====<br />
<br />
There are three built-in data structures in <span class="e">''E''</span>, Lists, Maps, and Sets. Each of these structures comes in two flavors, Flex (editable) and Const (immutable). The ConstList is the simplest:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def list := ["a",2,true]<br />
#This is true: list[0] == "a"<br />
#This is true: list[2] == true<br />
def newList := list + ["last"]<br />
#This is true: newList[3] == "last"<br />
for each in newList {println(`Element: $each`)}<br />
for i => each in newList {println(`Element number $i is $each`)}<br />
def listSize := newList.size()<br />
# get subrange starting at 0, running up to element 2, but not including element 2<br />
def subrange := list(0,2)<br />
#This is true: subrange == ["a",2]</nowiki><br />
<br />
</pre><br />
<br />
Lists are numerically indexed starting from 0, use the "+" operator to create a new list which is the concatenation of lists. Lists work with the for loop. The "size" method returns the number of elements. The <span class="e">''E''</span> String type is a kind of ConstList in which all the elements are characters. So, for example, the mechanism for taking a subrange shown above gives you a substring if the ConstList is a String.<br />
<br />
You can make a FlexList from a ConstList with the ''diverge'' method:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def newList := []<br />
def editable := newList.diverge()<br />
editable.push(100)<br />
if (editable.pop() == 100) {<br />
println("Yeah, push and pop make a list work like a stack")<br />
}<br />
editable[0] := "b"<br />
def frozen := editable.snapshot() </nowiki><br />
<br />
</pre><br />
<br />
Warning: don't try to use the editable.add() method to push an item (as you would do in Java). "add" does the same thing as "+"; it returns a new list while leaving the original unchanged.<br />
<br />
All the methods that work on a ConstList also work on a FlexList. In addition, there are editing operations for FlexLists, including push/pop (which allows the FlexList to behave like a stack) and element replacement that uses Java array-style syntax. You can get a ConstList from a FlexList with the snapshot method. Just as Java Strings are like ConstLists in which all elements are characters, Java StringBuffers are like FlexLists in which all elements are characters.<br />
<br />
Maps are composed of key/value pairs. In the following example, in the ConstMap table, "a" is a key, and 1 is a value:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def table := ["a" => 1, 2 => "b"]<br />
# This is true: table["a"] == 1<br />
# This is true: table[2] == "b"<br />
def emptyTable := [].asMap()<br />
def keyTable := ["a",1,true].asKeys()<br />
# This is true: keyTable[true] == null <br />
# This is true: keyTable.maps("a") == true<br />
for key => value in table {println(`Key: $key Value: $value`)}<br />
for each in table {println(`Value: $each`)}<br />
def mapSize := table.size()</nowiki><br />
<br />
</pre><br />
<br />
Elements in a map are retrieved using an array-like syntax, using the key as the index in the square brackets. <br />
If you're not sure whether the key will be present, you can use the fetch method instead; this takes a function as its second argument and evaluates that if the key isn't present. e.g.<br />
<br />
<pre><br />
def value := table.fetch("key", def ifMissing() { return null })<br />
</pre><br />
<br />
You will often see this shortened further, using the "fn" syntax for anonymous functions:<br />
<br />
<pre><br />
def value := table.fetch("key", fn { null })<br />
</pre><br />
<br />
Maps can be made from lists using asMap and asKeys; when you use asKeys, the values are nulls. The for loop works nicely with the map structures.<br />
<br />
FlexMaps can be made from ConstMaps with the diverge method:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def editableMap := table.diverge()<br />
editableMap["c"] := 3<br />
editableMap["a"] := "replacement"<br />
editableMap.removeKey(2)<br />
def frozenMap := editableMap.snapshot() </nowiki><br />
<br />
</pre><br />
<br />
Values in a FlexMap can be added and replaced with array-like syntax. Key-value pairs can be removed with removeKey(key). The snapshot method creates a ConstMap from a FlexMap.<br />
<br />
Sets are quite similar, with ["a","b"].asSet() producing a ConstSet with 2 elements. Documentation for all the operations on Const and Flex lists, maps, and sets can be reached directly from the [http://www.erights.org/javadoc/index.html Javadoc For <span class="e">''E''</span> index].<br />
<br />
A String is actually a ConstList of characters. You can create a FlexList of elements of a specific type by specifying the type in the diverge/snapshot method:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def aString := [].diverge(char)</nowiki><br />
<br />
</pre><br />
<br />
This aString will not accept elements which are not of type char; the variable aString has many of the characteristics of a StringBuffer from Java.<br />
<br />
One feature of <span class="e">''E''</span> that Java/C programmers will find surprising but useful is the ability to define multiple variables by using a list:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def [a,b] := [2,3] <br />
#a holds the value 2<br />
#b holds the value 3</nowiki><br />
<br />
</pre><br />
<br />
While this is an amusing way to initialize a random bunch of variables at once, the structure is most valuable when creating groups of variables that have no meaning in the absence of one another. The method Ref.promise(), described in Distributed Computing, is an important user of this pattern.<br />
<br />
====Equality Testing for Structures====<br />
<br />
One of the biggest differences between Flex and Const structures is the test for equality. Const structures are compared by value, and as such are considered equal if their contents are identical. The test for equality is, in other words, the same as the test for equality between Java integers.<br />
<br />
Two Flex structures are considered equal if and only if they are the same structure, i.e., both of the variables being tested are references to a single object. This test for equality is, in other words, the same as the test for equality between Java StringBuffers.</div>ThomasLeonardhttp://wiki.erights.org/wiki/ELoaderELoader2010-06-10T11:33:03Z<p>ThomasLeonard: Fixed links</p>
<hr />
<div>When you run a .e or (.updoc) file, it is given a loader called '''<this>''' which can be used to import .emaker files from the same directory (or from a sub-directory).<br />
<br />
For example, create a new directory and add two files. main.e is the main program:<br />
<br />
# main.e<br />
def makeMyObject := <this:makeMyObject><br />
def obj := makeMyObject()<br />
...<br />
<br />
makeMyObject.emaker is a support file:<br />
<br />
# makeMyObject.emaker<br />
def makeMyObject() {<br />
...<br />
}<br />
<br />
Files imported using '''<this>''' also have the loader in their environment, and can import further files using it.<br />
<br />
An ELoader also allows access to the raw files (use '''<this>.getRoot()''' to get a read-only directory object). This is useful for accessing icons, documentation, etc.<br />
<br />
= Using multiple modules =<br />
<br />
If a program is made up of multiple modules, a separate loader can be created for each one. Each module is given its own loader as '''<this>''', as well as loaders for its dependencies. For example, here we have two modules. "prog" is a program that depends on a library called "libfoo".<br />
<br />
def makeTraceln := <unsafe:org.erights.e.elib.debug.makeTraceln><br />
def makeELoader := <elang:interp.ELoaderAuthor>(makeTraceln)<br />
<br />
def <libfoo> := makeELoader(<file:.../libfoo>, ["this__uriGetter" => <libfoo>], "libfoo$")<br />
def <prog> := makeELoader(<file:.../prog>, ["this__uriGetter" => <prog>, => <libfoo>], "prog$")<br />
<br />
def app := <prog:makeApplication>(...)<br />
<br />
* Within libfoo, the library can load other emakers from itself using e.g. '''<this:somefile>'''.<br />
* Within prog, a file can load other emakers from prog using e.g. '''<this:somefile>''', or from libfoo using '''<libfoo:somefile>'''.<br />
<br />
You could also wrap the '''<libfoo>''' given to prog to only expose its public API.<br />
<br />
This avoids the need to set classpath and avoids conflicts between different packages. For example, you could depend on two libraries which, internally, require different versions of libfoo. Each library would see the correct version of libfoo as '''<libfoo>'''.<br />
<br />
In future, it is expected that a separate ''injector'' library will take care of selecting and downloading modules and wiring them together, such as [http://0install.net 0install.net].<br />
<br />
= See also =<br />
<br />
* http://switchb.org/darcs/e-modules/<br />
* http://www.eros-os.org/pipermail/e-lang/2010-February/013416.html -- original discussion</div>ThomasLeonardhttp://wiki.erights.org/wiki/EExprEExpr2010-06-09T14:44:18Z<p>ThomasLeonard: </p>
<hr />
<div>A parsed Kernel-E expression.<br />
<br />
== Protocol ==<br />
<br />
{{instance msgdoc|compile|1|env :Scope|CompiledE}}<br />
<br />
Compile the expression to an internal form (currently transformed E, but could be Java bytecode). The result is a Thunk which can be invoked to evaluate the code in the given environment.<br />
<br />
The CompiledE is also useful if you want to debug the optimiser:<br />
<br />
? def expr := e`def double (x) { return 2*x }`<br />
# value: e`def double {<br />
# <br />
# method run(x) {<br />
# escape __return {<br />
# __return.run(2.multiply(x))<br />
# null<br />
# }<br />
# }<br />
# }`<br />
<br />
? expr.compile(safeScope)<br />
# value: compiled-e`def double {<br />
# <br />
# method run(x) {<br />
# 2.multiply(x)<br />
# }<br />
# }`<br />
<br />
{{instance msgdoc|eval|1|env :Scope|any}}<br />
<br />
Convenience method to compile and evaluate the expression in one go.</div>ThomasLeonardhttp://wiki.erights.org/wiki/EExprEExpr2010-06-09T14:43:41Z<p>ThomasLeonard: </p>
<hr />
<div>A parsed Kernel-E expression.<br />
<br />
== Protocol ==<br />
<br />
{{instance msgdoc|compile|1|env :Scope|CompiledE}}<br />
<br />
Compile the expression to an internal form (currently transformed E, but could be Java bytecode). The result is a Thunk which can be invoked to evaluate the code in the given environment.<br />
<br />
The CompiledE is also useful if you want to debug the optimiser:<br />
<br />
? def expr := e`def double? (x) { return 2*x }`<br />
# value: e`def double {<br />
# <br />
# method run(x) {<br />
# escape __return {<br />
# __return.run(2.multiply(x))<br />
# null<br />
# }<br />
# }<br />
# }`<br />
<br />
? expr.compile(safeScope)<br />
# value: compiled-e`def double {<br />
# <br />
# method run(x) {<br />
# 2.multiply(x)<br />
# }<br />
# }`<br />
<br />
{{instance msgdoc|eval|1|env :Scope|any}}<br />
<br />
Convenience method to compile and evaluate the expression in one go.</div>ThomasLeonardhttp://wiki.erights.org/wiki/EExprEExpr2010-06-09T14:40:19Z<p>ThomasLeonard: </p>
<hr />
<div>A parsed Kernel-E expression.<br />
<br />
== Protocol ==<br />
<br />
{{instance msgdoc|compile|1|env :Scope|CompiledE}}<br />
<br />
Compile the expression to an internal form (e.g. currently Transformed-E, but could be Java bytecode). The result is a Thunk which can be invoked to evaluate the code in the given environment.<br />
<br />
{{instance msgdoc|eval|1|env :Scope|any}}<br />
<br />
Convenience method to compile and evaluate the expression in one go.</div>ThomasLeonardhttp://wiki.erights.org/wiki/ELoaderELoader2010-06-09T13:25:51Z<p>ThomasLeonard: </p>
<hr />
<div>When you run a .e or (.updoc) file, it is given a loader called '''<this>''' which can be used to import .emaker files from the same directory (or from a sub-directory).<br />
<br />
For example, create a new directory and add two files. main.e is the main program:<br />
<br />
# main.e<br />
def makeMyObject := <this:makeMyObject><br />
def obj := makeMyObject()<br />
...<br />
<br />
makeMyObject.emaker is a support file:<br />
<br />
# makeMyObject.emaker<br />
def makeMyObject() {<br />
...<br />
}<br />
<br />
Files imported using '''<this>''' also have the loader in their environment, and can import further files using it.<br />
<br />
An ELoader also allows access to the raw files (use '''<this>.getRoot()''' to get a read-only directory object). This is useful for accessing icons, documentation, etc.<br />
<br />
= Using multiple modules =<br />
<br />
If a program is made up of multiple modules, a separate loader can be created for each one. Each module is given its own loader as '''<this>''', as well as loaders for its dependencies. For example, here we have two modules. "prog" is a program that depends on a library called "libfoo".<br />
<br />
def makeTraceln := <unsafe:org.erights.e.elib.debug.makeTraceln><br />
def makeELoader := <elang:interp.ELoaderAuthor>(makeTraceln)<br />
<br />
def <libfoo> := makeELoader(<file:.../libfoo>, ["this__uriGetter" => <libfoo>], "libfoo$")<br />
def <prog> := makeELoader(<file:.../prog>, ["this__uriGetter" => <prog>, => <libfoo>], "prog$")<br />
<br />
def app := <prog:makeApplication>(...)<br />
<br />
* Within libfoo, the library can load other emakers from itself using e.g. '''<this:somefile>'''.<br />
* Within prog, a file can load other emakers from prog using e.g. '''<this:somefile>''', or from libfoo using '''<libfoo:somefile>'''.<br />
<br />
You could also wrap the '''<libfoo>''' given to prog to only expose its public API.<br />
<br />
This avoids the need to set classpath and avoids conflicts between different packages.<br />
<br />
= See also =<br />
<br />
See [http://www.eros-os.org/pipermail/e-lang/2010-February/013416.html] for details.</div>ThomasLeonardhttp://wiki.erights.org/wiki/ELoaderELoader2010-06-09T13:22:09Z<p>ThomasLeonard: </p>
<hr />
<div>When you run a .e or (.updoc) file, it is given a loader called '''<this>''' which can be used to import .emaker files from the same directory (or from a sub-directory).<br />
<br />
For example:<br />
<br />
# main.e<br />
def makeMyObject := <this:makeMyObject><br />
def obj := makeMyObject()<br />
...<br />
<br />
# makeMyObject.emaker<br />
def makeMyObject() {<br />
...<br />
}<br />
<br />
= Using multiple modules =<br />
<br />
If a program is made up of multiple modules, a separate loader can be created for each one. Each module is given its own loader as '''<this>''', as well as loaders for its dependencies. For example, here we have two modules. "prog" is a program that depends on a library called "libfoo".<br />
<br />
def makeTraceln := <unsafe:org.erights.e.elib.debug.makeTraceln><br />
def makeELoader := <elang:interp.ELoaderAuthor>(makeTraceln)<br />
<br />
def <libfoo> := makeELoader(<file:.../libfoo>, ["this__uriGetter" => <libfoo>], "libfoo$")<br />
def <prog> := makeELoader(<file:.../prog>, ["this__uriGetter" => <prog>, => <libfoo>], "prog$")<br />
<br />
def app := <prog:makeApplication>(...)<br />
<br />
* Within libfoo, the library can load other emakers from itself using e.g. '''<this:somefile>'''.<br />
* Within prog, a file can load other emakers from prog using e.g. '''<this:somefile>''', or from libfoo using '''<libfoo:somefile>'''.<br />
<br />
You could also wrap the '''<libfoo>''' given to prog to only expose its public API.<br />
<br />
This avoids the need to set classpath and avoids conflicts between different packages.<br />
<br />
= See also =<br />
<br />
See [http://www.eros-os.org/pipermail/e-lang/2010-February/013416.html] for details.</div>ThomasLeonardhttp://wiki.erights.org/wiki/ELoaderELoader2010-06-09T13:20:57Z<p>ThomasLeonard: </p>
<hr />
<div>When you run a .e or (.updoc) file, it is given a loader called '''<this>''' which can be used to import .emaker files from the same directory (or from a sub-directory).<br />
<br />
For example:<br />
<br />
# main.e<br />
def makeMyObject := <this:makeMyObject><br />
def obj := makeMyObject()<br />
...<br />
<br />
# makeMyObject.emaker<br />
def makeMyObject() {<br />
...<br />
}<br />
<br />
= Using multiple modules =<br />
<br />
If a program is made up of multiple modules, a separate loader can be created for each one. Each module is given its own loader as '''<this>''', as well as loaders for its dependencies. For example, here we have two modules. "prog" is a program that depends on a library called "libfoo".<br />
<br />
def <libfoo> := makeELoader(<file:.../libfoo>, ["this__uriGetter" => <libfoo>], "libfoo$")<br />
def <prog> := makeELoader(<file:.../prog>, ["this__uriGetter" => <prog>, => <libfoo>], "prog$")<br />
<br />
def app := <prog:makeApplication>(...)<br />
<br />
* Within libfoo, the library can load other emakers from itself using e.g. '''<this:somefile>'''.<br />
* Within prog, a file can load other emakers from prog using e.g. '''<this:somefile>''', or from libfoo using '''<libfoo:somefile>'''.<br />
<br />
You could also wrap the '''<libfoo>''' given to prog to only expose its public API.<br />
<br />
This avoids the need to set classpath and avoids conflicts between different packages.<br />
<br />
= See also =<br />
<br />
See [http://www.eros-os.org/pipermail/e-lang/2010-February/013416.html] for details.</div>ThomasLeonardhttp://wiki.erights.org/wiki/ELoaderELoader2010-06-09T13:07:49Z<p>ThomasLeonard: </p>
<hr />
<div>When you run a .e or (.updoc) file, it is given a loader called '''<this>''' which can be used to import .emaker files from the same directory (or from a sub-directory).<br />
<br />
For example:<br />
<br />
# main.e<br />
def makeMyObject := <this:makeMyObject><br />
def obj := makeMyObject()<br />
...<br />
<br />
# makeMyObject.emaker<br />
def makeMyObject() {<br />
...<br />
}<br />
<br />
If a program is made up of multiple modules, a separate loader can be created for each one. Each module is given its own loader as '''<this>''', as well as loaders for its dependencies.<br />
<br />
This avoids the need to set classpath and avoids conflicts between different packages. See [http://www.eros-os.org/pipermail/e-lang/2010-February/013416.html] for details.</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/EmakersWalnut/Ordinary Programming/Emakers2010-06-09T13:02:17Z<p>ThomasLeonard: /* Where to put your emaker files */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Library Packages: emakers===<br />
<br />
The <span class="e">''E''</span> library package system is based on ''emakers''. An emaker is an E source file named with ".emaker" as the suffix.<br />
<br />
When an emaker is imported into an application, the code is executed at the time of import, and the result of that execution is returned to the importing program.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeQueue() {<br />
var head := null<br />
var tail := null<br />
def makeCarrier(obj) :near {<br />
var next := null<br />
def carrier {<br />
to attach(nextCarrier) {next := nextCarrier}<br />
to get() {return obj}<br />
to next() {return next}<br />
}<br />
}<br />
def queue {<br />
to push(obj) {<br />
if (head == null) {<br />
head := makeCarrier(obj)<br />
tail := head<br />
} else {<br />
tail.attach(makeCarrier(obj))<br />
tail := tail.next()<br />
}<br />
}<br />
to pop() {<br />
def current := head<br />
head := head.next()<br />
return current.get()<br />
}<br />
to iterate(func) {<br />
var current := head<br />
var i := 0<br />
while (current != null) {<br />
func(i, current.get())<br />
current := current.next()<br />
i += 1<br />
}<br />
}<br />
}<br />
return queue<br />
}</nowiki><br />
<br />
</pre><br />
<br />
'''Side Note: '''This queue does have one interesting characteristic: the iterate method is the feature required to work correctly with E's for-loop. Iterate receives a function that expects 2 arguments: a key and an object. In this queue, the key value is filled with the index of the value in the queue. Iterate walks the entire data structure, invoking the function once for each element.<br />
<br />
==== Where to put your emaker files ====<br />
<br />
Place this queuemaker in a file named makeQueue.emaker. There are several ways of making <span class="e">''E''</span> aware of the availability of an emaker, corresponding to the several ways Java can become aware of a class:<br />
<br />
* You can import it using an [[ELoader]], if you have a recent enough version of E.<br />
* You can place it, or a jar that contains it, on the classpath when you start up the jvm, e.g. using '''java -cp libDir ...''' or '''rune -cpa libDir ...'''.<br />
* You can place it in a zip or a jar and place it in the jvm's ext directory.<br />
* By placing the file in a subdirectory under lib/ext in the java directory system. You can use Java-style package specifications: as in Java, you can put the file in a jar in lib/ext. [ Should we be recommending this? Putting files in the Java installation itself seems like a recipe for conflicts between packages, and lost libraries when upgrading Java. ]<br />
<br />
In the below example, we place the file under lib/ext/emakers/com/yourdomain/e/queueMaker.emaker (in your jre directory), and import:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def makeQueue := <import:com.yourdomain.e.makeQueue><br />
def queue := makeQueue()<br />
queue.push(1)<br />
queue.push(2)<br />
for each in queue {println(each)}</nowiki><br />
<br />
</pre><br />
<br />
==== Security of emakers ====<br />
<br />
Emakers have an important security property: they come to life contained in a world with no authority. Such a world is even more restrictive than the Java sandbox used for applets. However, this world is more flexible than the sandbox because authority can be granted and revoked during operation using capabilities, as described in the chapter on Secure Distributed Computing.<br />
<br />
However, while emakers themselves are safe, adding a jar or directory to your classpath has a global effect on the JVM. For example, a jar may contain .safej files that grant emakers access to unsafe Java classes. Therefore you should use a custom loader if possible, rather than modifying the classpath. [ how? ]<br />
<br />
The makeQueue function example is a nice first example of emakers in action because makeQueue and the queues it makes need no authority. For emakers that require authority, by convention we use the Authorizer pattern. Here is an infoWindowMakerAuthor: the infoWindowMaker needs the authority to create windows, so we wrap it in an Authorizer:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
#emaker in file lib/ext/com/skyhunter/infoWindowMakerAuthor.emaker<br />
def infoWindowMakerAuthor(frameMaker) {<br />
def infoWindowMaker(infoText) {<br />
def frame := frameMaker("Information")<br />
def label := <swing:makeJLabel>(infoText)<br />
frame.getContentPane().add(label)<br />
frame.pack()<br />
frame.show()<br />
return frame<br />
}<br />
return infoWindowMaker<br />
}<br />
#.....in using program....<br />
def makeInfoWindow := <import:com.skyhunter.infoWindowMakerAuthor> (<swing:makeJFrame>)<br />
def infoBox := makeInfoWindow("First Bit Of Info")<br />
def detailedInfoBox := makeInfoWindow("Second Bit Of Info")</nowiki><br />
<br />
</pre><br />
<br />
By convention, authors follow the pattern of functions, using an implied run() method to return the Maker that is being wrapped.<br />
<br />
The meticulous reader may have noticed that the JFrame was a capability that needed to be authorized, whereas the JLabel was not. The vast bulk of the Java API is non-capability-transferring, and can just be acquired using import:. Commonly-used exceptions are the JFrame, everything have to do with files in java.io, and the URL object in java.net. For a complete listing of suppressed methods (which are inaccessible in <span class="e">''E''</span> though documented in Java), safe classes (which can be imported directly by emakers), and unsafe classes (which can only be imported using the unsafe__uriGetter, which is not directly available to emakers), see the [http://www.erights.org/javadoc/index.html JavaDoc for <span class="e">''E''</span>].<br />
<br />
<span class="warn" style="color:red">obsolete:</span>Emakers can also just be functions, in which case the naming convention uses "Func" to distinguish it from a Maker:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
#emaker in file lib/ext/org/erights/computeSquareFunc.emaker<br />
def computeSquareFunc(number) {<br />
return number * number<br />
}<br />
<br />
#...in using program...<br />
def computeSquare := <import:org.erights.computeSquareFunc><br />
def squareOfThree := computeSquare(3)</nowiki><br />
<br />
</pre><br />
<br />
There are also functions that require capabilities before they can become operational, in which case they are by convention wrapped in Authorizers, for example, analyzeOutlineFuncAuthor.<br />
<br />
The good news is that, because emakers come to life without authority, they can always be imported with import:, so any emaker can bring in any other emaker (though you won't be able to run the authorizer without sufficient authority). The bad news is that, if you are writing standalone E applications in which the emakers are fully trustworthy (or at least as trustworthy as the program that calls them), it can seem a substantial nuisance at first to be granting lists of authorities just to break your program into packages. If you are writing pure <span class="e">''E''</span> applications that use emakers of your own construction, emakers which you trust totally with the full authority of the system, and you have no qualms about flouting the wisdom of architectural purists around the world, you can take a shortcut by simply granting the unsafe__uriGetter. For example:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def powerfulObjectMakerAuthor(unsafe__uriGetter) {<br />
def file := <unsafe:java.io.File>("name")<br />
def swing__uriGetter := <unsafe:javax.swing.*><br />
def frame := <swing:makeJFrame>("powerful object window title")<br />
def powerfulObjectMaker() {<br />
#....define the objectMaker and the object it makes...<br />
}<br />
return powerfulObjectMaker()<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Note that in this example, one of the things we created from our unsafe__uriGetter was our own swing__uriGetter. Emakers, when they come to life, do have a swing__uriGetter of their own; however, their built-in swing: accesses only the safe subset of swing, much as import: accesses only the safe subset of unsafe:. In the example we create our own swing: that overrides the default swing:, which enables us access unsafe classes such as the JFrame.<br />
<br />
For even more information on the security properties of emakers, see the chapter on Secure Mobile Code.<br />
<br />
==== Exporting multiple objects ====<br />
<br />
As importing an emaker returns the last value in the file, you can export multiple objects by ending with a map. For example:<br />
<br />
# utils.emaker<br />
def foo(x) ...<br />
def bar(y) ...<br />
[ => foo, => bar ]<br />
<br />
They can be used like this:<br />
<br />
def <utils> := <import:utils><br />
<utils:foo>("hello")<br />
<br />
Note: '''<utils:foo>''' is syntactic sugar for '''<utils>["foo"]'''.</div>ThomasLeonardhttp://wiki.erights.org/wiki/SQLSQL2010-06-09T11:22:30Z<p>ThomasLeonard: /* Statements and queries */</p>
<hr />
<div>Examples of using SQL from E can be found in the sql.updoc file. Here is an extract:<br />
<br />
= Setup =<br />
<br />
Create an in-memory relational database using HSQLDB (http://hsqldb.org/):<br />
<br />
? def driver := <unsafe:org.hsqldb.makejdbcDriver>()<br />
? def connection := driver.connect("jdbc:hsqldb:mem:test", null)<br />
<br />
(replace "mem" with "file" to store the database on disk, or replace "hsqldb" to connect to a full database server)<br />
<br />
Wrap it with an SQL quasi-parser:<br />
<br />
? def makeSql__quasiParser := <import:org.erights.e.tools.database.makeSQLQuasiParser><br />
? def sql__quasiParser := makeSql__quasiParser(connection)<br />
<br />
= Creating tables =<br />
<br />
Create a test table:<br />
<br />
? sql`CREATE TABLE users (<br />
> id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY,<br />
> userName VARCHAR(256) NOT NULL,<br />
> created DATETIME DEFAULT NOW NOT NULL,<br />
> karma BIGINT NOT NULL,<br />
> comments VARCHAR(256) DEFAULT NULL)`<br />
<br />
= Statements and queries =<br />
<br />
Insert some values:<br />
<br />
? for name in ["alice", "bob", "carol"] {<br />
> sql`INSERT INTO users (userName, karma) VALUES ($name, 0)`<br />
> }<br />
<br />
Update one row:<br />
<br />
? sql`UPDATE users SET karma=1 WHERE userName='alice'`<br />
# value: 1<br />
<br />
Read all the values out:<br />
<br />
? for [name, karma] in sql`SELECT userName, karma FROM users ORDER BY id ASC` {<br />
> println(`$name => $karma`)<br />
> }<br />
# stdout: alice => 1<br />
# bob => 0<br />
# carol => 0<br />
#<br />
<br />
Get out a single row:<br />
<br />
? def lookupUser(name :String) :int {<br />
> def [id] := sql`SELECT id FROM users WHERE userName=$name`.singleton()<br />
> return id<br />
> }<br />
<br />
? lookupUser("bob")<br />
# value: 1<br />
<br />
? lookupUser("fred")<br />
# problem: no rows returned by "SELECT id FROM users WHERE userName=?"<br />
<br />
We also get an exception if multiple rows are returned:<br />
<br />
? sql`SELECT id FROM users`.singleton()<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
A default can be provided if there are no rows:<br />
<br />
? sql`SELECT id FROM users WHERE userName='david'`.singleton(fn {-1})<br />
# value: -1<br />
<br />
But this is still an error:<br />
<br />
? sql`SELECT id FROM users`.singleton(fn {-1})<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
Internally, we're constructing PreparedStatement objects, not doing string interpolation:<br />
<br />
? def query := "SELECT id FROM users"<br />
? sql`${query}`<br />
# problem: <SQLException: unexpected token: ?><br />
<br />
This means we don't have to worry about quoting:<br />
<br />
? def ono := "O'No! $@?"<br />
? sql`INSERT INTO users (userName, karma) VALUES ($ono, -5)`<br />
# value: 1<br />
<br />
? sql`SELECT id FROM users WHERE karma < 0`.singleton()<br />
# value: [3]<br />
<br />
? sql`INSERT INTO users (userName, karma) VALUES ('$$@@', -6)`<br />
? sql`SELECT userName FROM users WHERE karma = -6`.singleton()<br />
# value: ["$@"]<br />
<br />
As a convenience, we can get all the results as a list too:<br />
<br />
? sql`SELECT id, karma FROM users WHERE karma >= 0 ORDER BY id ASC`.asList()<br />
# value: [[0, 1], [1, 0], [2, 0]]<br />
<br />
= Data Access Objects =<br />
<br />
The SQL quasi-parser is a powerful authority that typically gives complete access to a whole database. You normally don't want to give out this authority to every part of your program that uses the database. You should therefore provide DAO wrapper objects that give more limited access (for example, that give access to a single table, or access only to certain rows).<br />
<br />
For an example, see [http://labs.it-innovation.soton.ac.uk/index.php?option=com_content&view=article&id=74:safe-database-access-in-e&catid=36:experiments Safe database access in E]</div>ThomasLeonardhttp://wiki.erights.org/wiki/SQLSQL2010-06-09T11:20:47Z<p>ThomasLeonard: /* Setup */</p>
<hr />
<div>Examples of using SQL from E can be found in the sql.updoc file. Here is an extract:<br />
<br />
= Setup =<br />
<br />
Create an in-memory relational database using HSQLDB (http://hsqldb.org/):<br />
<br />
? def driver := <unsafe:org.hsqldb.makejdbcDriver>()<br />
? def connection := driver.connect("jdbc:hsqldb:mem:test", null)<br />
<br />
(replace "mem" with "file" to store the database on disk, or replace "hsqldb" to connect to a full database server)<br />
<br />
Wrap it with an SQL quasi-parser:<br />
<br />
? def makeSql__quasiParser := <import:org.erights.e.tools.database.makeSQLQuasiParser><br />
? def sql__quasiParser := makeSql__quasiParser(connection)<br />
<br />
= Creating tables =<br />
<br />
Create a test table:<br />
<br />
? sql`CREATE TABLE users (<br />
> id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY,<br />
> userName VARCHAR(256) NOT NULL,<br />
> created DATETIME DEFAULT NOW NOT NULL,<br />
> karma BIGINT NOT NULL,<br />
> comments VARCHAR(256) DEFAULT NULL)`<br />
<br />
= Statements and queries =<br />
<br />
Insert some values:<br />
<br />
? for name in ["alice", "bob", "carol"] {<br />
> sql`INSERT INTO users (userName, karma) VALUES ($name, 0)`<br />
> }<br />
<br />
Update one row:<br />
<br />
? sql`UPDATE users SET karma=1 WHERE userName='alice'`<br />
# value: 1<br />
<br />
Read all the values out:<br />
<br />
? for [name, karma] in sql`SELECT userName, karma FROM users ORDER BY id ASC` {<br />
> println(`$name => $karma`)<br />
> }<br />
# stdout: alice => 1<br />
# bob => 0<br />
# carol => 0<br />
#<br />
<br />
Get out a single row:<br />
<br />
? def lookupUser(name :String) :int {<br />
> def [id] := sql`SELECT id FROM users WHERE userName=$name`.singleton()<br />
> return id<br />
> }<br />
<br />
? lookupUser("bob")<br />
# value: 1<br />
<br />
? lookupUser("fred")<br />
# problem: no rows returned by "SELECT id FROM users WHERE userName=?"<br />
<br />
We also get an exception if multiple rows are returned:<br />
<br />
? sql`SELECT id FROM users`.singleton()<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
A default can be provided if there are no rows:<br />
<br />
? sql`SELECT id FROM users WHERE userName='david'`.singleton(fn {-1})<br />
# value: -1<br />
<br />
But this is still an error:<br />
<br />
? sql`SELECT id FROM users`.singleton(fn {-1})<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
Internally, we're constructing PreparedStatement objects, not doing string interpolation:<br />
<br />
? def query := "SELECT id FROM users"<br />
? sql`${query}`<br />
# problem: <SQLException: unexpected token: ?><br />
<br />
This means we don't have to worry about quoting:<br />
<br />
? def ono := "O'No! $@?"<br />
? sql`INSERT INTO users (userName, karma) VALUES ($ono, -5)`<br />
# value: 1<br />
<br />
? sql`SELECT id FROM users WHERE karma < 0`.singleton()<br />
# value: [3]<br />
<br />
? sql`INSERT INTO users (userName, karma) VALUES ('$$@@', -6)`<br />
? sql`SELECT userName FROM users WHERE karma = -6`.singleton()<br />
# value: ["$@"]<br />
<br />
As a convenience, we can get all the results as a list too:<br />
<br />
? sql`SELECT id, karma FROM users WHERE karma >= 0 ORDER BY id ASC`.asList()<br />
# value: [[0, 1], [1, 0], [2, 0]]<br />
<br />
= Data Access Objects =<br />
<br />
The SQL quasi-parser is a powerful authority that typically gives complete access to a whole database. You normally don't want to give out this authority to every part of your program that uses the database. You should therefore provide DAO wrapper objects that give more limited access (for example, that give access to a single table, or access only to certain rows).<br />
<br />
For an example, see [http://labs.it-innovation.soton.ac.uk/index.php?option=com_content&view=article&id=74:safe-database-access-in-e&catid=36:experiments Safe database access in E]</div>ThomasLeonardhttp://wiki.erights.org/wiki/SQLSQL2010-06-09T11:12:43Z<p>ThomasLeonard: </p>
<hr />
<div>Examples of using SQL from E can be found in the sql.updoc file. Here is an extract:<br />
<br />
= Setup =<br />
<br />
Create an in-memory relational database using HSQLDB (http://hsqldb.org/):<br />
<br />
? def driver := <unsafe:org.hsqldb.makejdbcDriver>()<br />
? def connection := driver.connect("jdbc:hsqldb:mem:test", null)<br />
<br />
(replace "mem" with "file" to store the database on disk, or replace "hsqldb" to connect to a full database server)<br />
<br />
Wrap it with an SQL quasi-parser:<br />
<br />
? def makeSql__quasiParser := <import:org.erights.e.tools.database.makeSQLQuasiParser><br />
? def sql__quasiParser := makeSql__quasiParser(connection)<br />
# value: <sql__quasiParser><br />
<br />
= Creating tables =<br />
<br />
Create a test table:<br />
<br />
? sql`CREATE TABLE users (<br />
> id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY,<br />
> userName VARCHAR(256) NOT NULL,<br />
> created DATETIME DEFAULT NOW NOT NULL,<br />
> karma BIGINT NOT NULL,<br />
> comments VARCHAR(256) DEFAULT NULL)`<br />
<br />
= Statements and queries =<br />
<br />
Insert some values:<br />
<br />
? for name in ["alice", "bob", "carol"] {<br />
> sql`INSERT INTO users (userName, karma) VALUES ($name, 0)`<br />
> }<br />
<br />
Update one row:<br />
<br />
? sql`UPDATE users SET karma=1 WHERE userName='alice'`<br />
# value: 1<br />
<br />
Read all the values out:<br />
<br />
? for [name, karma] in sql`SELECT userName, karma FROM users ORDER BY id ASC` {<br />
> println(`$name => $karma`)<br />
> }<br />
# stdout: alice => 1<br />
# bob => 0<br />
# carol => 0<br />
#<br />
<br />
Get out a single row:<br />
<br />
? def lookupUser(name :String) :int {<br />
> def [id] := sql`SELECT id FROM users WHERE userName=$name`.singleton()<br />
> return id<br />
> }<br />
<br />
? lookupUser("bob")<br />
# value: 1<br />
<br />
? lookupUser("fred")<br />
# problem: no rows returned by "SELECT id FROM users WHERE userName=?"<br />
<br />
We also get an exception if multiple rows are returned:<br />
<br />
? sql`SELECT id FROM users`.singleton()<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
A default can be provided if there are no rows:<br />
<br />
? sql`SELECT id FROM users WHERE userName='david'`.singleton(fn {-1})<br />
# value: -1<br />
<br />
But this is still an error:<br />
<br />
? sql`SELECT id FROM users`.singleton(fn {-1})<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
Internally, we're constructing PreparedStatement objects, not doing string interpolation:<br />
<br />
? def query := "SELECT id FROM users"<br />
? sql`${query}`<br />
# problem: <SQLException: unexpected token: ?><br />
<br />
This means we don't have to worry about quoting:<br />
<br />
? def ono := "O'No! $@?"<br />
? sql`INSERT INTO users (userName, karma) VALUES ($ono, -5)`<br />
# value: 1<br />
<br />
? sql`SELECT id FROM users WHERE karma < 0`.singleton()<br />
# value: [3]<br />
<br />
? sql`INSERT INTO users (userName, karma) VALUES ('$$@@', -6)`<br />
? sql`SELECT userName FROM users WHERE karma = -6`.singleton()<br />
# value: ["$@"]<br />
<br />
As a convenience, we can get all the results as a list too:<br />
<br />
? sql`SELECT id, karma FROM users WHERE karma >= 0 ORDER BY id ASC`.asList()<br />
# value: [[0, 1], [1, 0], [2, 0]]<br />
<br />
= Data Access Objects =<br />
<br />
The SQL quasi-parser is a powerful authority that typically gives complete access to a whole database. You normally don't want to give out this authority to every part of your program that uses the database. You should therefore provide DAO wrapper objects that give more limited access (for example, that give access to a single table, or access only to certain rows).<br />
<br />
For an example, see [http://labs.it-innovation.soton.ac.uk/index.php?option=com_content&view=article&id=74:safe-database-access-in-e&catid=36:experiments Safe database access in E]</div>ThomasLeonardhttp://wiki.erights.org/wiki/SQLSQL2010-06-09T11:06:20Z<p>ThomasLeonard: SQL examples</p>
<hr />
<div>Examples of using SQL from E can be found in the sql.updoc file. Here is an extract:<br />
<br />
Create an in-memory relational database using HSQLDB (http://hsqldb.org/):<br />
<br />
? def driver := <unsafe:org.hsqldb.makejdbcDriver>()<br />
? def connection := driver.connect("jdbc:hsqldb:mem:test", null)<br />
<br />
(replace "mem" with "file" to store the database on disk, or replace "hsqldb" to connect to a full database server)<br />
<br />
Wrap it with an SQL quasi-parser:<br />
<br />
? def makeSql__quasiParser := <import:org.erights.e.tools.database.makeSQLQuasiParser><br />
? def sql__quasiParser := makeSql__quasiParser(connection)<br />
# value: <sql__quasiParser><br />
<br />
Create a test table:<br />
<br />
? sql`CREATE TABLE users (<br />
> id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY,<br />
> userName VARCHAR(256) NOT NULL,<br />
> created DATETIME DEFAULT NOW NOT NULL,<br />
> karma BIGINT NOT NULL,<br />
> comments VARCHAR(256) DEFAULT NULL)`<br />
<br />
Insert some values:<br />
<br />
? for name in ["alice", "bob", "carol"] {<br />
> sql`INSERT INTO users (userName, karma) VALUES ($name, 0)`<br />
> }<br />
<br />
Update one row:<br />
<br />
? sql`UPDATE users SET karma=1 WHERE userName='alice'`<br />
# value: 1<br />
<br />
Read all the values out:<br />
<br />
? for [name, karma] in sql`SELECT userName, karma FROM users ORDER BY id ASC` {<br />
> println(`$name => $karma`)<br />
> }<br />
# stdout: alice => 1<br />
# bob => 0<br />
# carol => 0<br />
#<br />
<br />
Get out a single row:<br />
<br />
? def lookupUser(name :String) :int {<br />
> def [id] := sql`SELECT id FROM users WHERE userName=$name`.singleton()<br />
> return id<br />
> }<br />
<br />
? lookupUser("bob")<br />
# value: 1<br />
<br />
? lookupUser("fred")<br />
# problem: no rows returned by "SELECT id FROM users WHERE userName=?"<br />
<br />
We also get an exception if multiple rows are returned:<br />
<br />
? sql`SELECT id FROM users`.singleton()<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
A default can be provided if there are no rows:<br />
? sql`SELECT id FROM users WHERE userName='david'`.singleton(fn {-1})<br />
# value: -1<br />
<br />
But this is still an error:<br />
<br />
? sql`SELECT id FROM users`.singleton(fn {-1})<br />
# problem: multiple rows returned by "SELECT id FROM users"<br />
<br />
Internally, we're constructing PreparedStatement objects, not doing string<br />
interpolation:<br />
<br />
? def query := "SELECT id FROM users"<br />
? sql`${query}`<br />
# problem: <SQLException: unexpected token: ?><br />
<br />
This means we don't have to worry about quoting:<br />
<br />
? def ono := "O'No! $@?"<br />
? sql`INSERT INTO users (userName, karma) VALUES ($ono, -5)`<br />
# value: 1<br />
<br />
? sql`SELECT id FROM users WHERE karma < 0`.singleton()<br />
# value: [3]<br />
<br />
? sql`INSERT INTO users (userName, karma) VALUES ('$$@@', -6)`<br />
? sql`SELECT userName FROM users WHERE karma = -6`.singleton()<br />
# value: ["$@"]<br />
<br />
As a convenience, we can get all the results as a list too:<br />
<br />
? sql`SELECT id, karma FROM users WHERE karma >= 0 ORDER BY id ASC`.asList()<br />
# value: [[0, 1], [1, 0], [2, 0]]<br />
<br />
See [http://labs.it-innovation.soton.ac.uk/index.php?option=com_content&view=article&id=74:safe-database-access-in-e&catid=36:experiments Safe database access in E]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Quasi-Literals_and_Quasi-ParsersWalnut/Ordinary Programming/Quasi-Literals and Quasi-Parsers2010-06-09T11:01:37Z<p>ThomasLeonard: /* SQL */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Quasi-Literals and Quasi-Parsers===<br />
<br />
E supports ''quasi-parsers''. A quasi-parser allows one to compress large numbers of operations into a succinct notation (a ''quasi-literal'') in a specific problem domain. Writing your own quasi-parsers (which can be done in <span class="e">''E''</span> itself, as the JPanel quasiparser described below was written) is beyond the scope of this book. However, <span class="e">''E''</span> comes with several quasi-parsers built in: a simple quasi-parser, a regular expression quasi-parser, a JPanel quasi-parser for Swing, and a swtGrid quasi-parser for SWT.<br />
<br />
====Simple quasi-parser====<br />
<br />
The default quasi-parser is a text manipulating parser capable of extracting data from strings and constructing new strings. In its simplest form, it is a clean and simple way of constructing strings for printing:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def a := 3<br />
def answerString := `The value a is $a, and a times two is ${2 * a}.`<br />
println(answerString)</nowiki><br />
<br />
</pre><br />
<br />
Here we use a simple quasi-parser to build an output string in a fashion similar to the printf statement in C. Quasi literals are enclosed in back-ticks. A dollar sign denotes the beginning of a description of a value to be inserted at the dollar sign location. If the dollar sign is immediately followed by a variable name, the value of that variable is used. If the dollar sign is followed by an open brace, everything up to the close brace is evaluated to compute the value to be substituted (so you could put "$" inside the braces to put a dollar sign in the string, as well as doing arithmetic as in the above example). Quasi-literals can span multiple lines, in which case the carriage return is part of the structure.<br />
<br />
A more sophisticated use of simple quasi-literals is for pattern matching. Here we parse a sentence:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def line := "By the rude bridge that arched the flood"<br />
if (line =~ `@word1 @{word2} rude @remainder`) {<br />
println(`text matches, word1 = $word1`)<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The string on the left of =~ is compared to the quasi literal on the right, evaluating true if the string can be parsed in conformance with the quasi literal. The "@" asserts that any text can match this part of the string, and the variable declared after the "@" contains that text at the end of the evaluation. The variable "word2" is enclosed in braces to offset it from the word "rude" immediately following it, which would look like part of the variable name without the offset.<br />
<br />
In this example, the minimal string that can get a match would be space-space-"rude ", in which case the data extracted for variables word1, word2, and remainder would all be zero-length strings. As it is, at the end of the evaluation, word1=="By", word2=="the", and remainder == "bridge that arched the flood".<br />
<br />
A single quasi-literal can contain dollar signs as well as "@"'s, in which case the results of the dollar sign evaluations will be included in the matching conditions.<br />
<br />
The '''int''' guard will not convert strings to ints, so to extract an integer from a string, use something like this:<br />
<br />
def line := "The number 5"<br />
def `The number @xString` := line<br />
def x := __makeInt(xString)<br />
# value: 5<br />
<br />
For floating-point numbers, you can use '''<import:java.lang.makeDouble>.parseDouble(...)'''.<br />
<br />
Quasi-literals can almost always be treated as strings. They accept almost all of the string protocol (technically, the quasi-literals are of type "twine"). The one place where they cannot be treated as strings is in comparisons to actual strings. To compare a quasi-literal to a string, use the "bare" method: <span class="warn">this is now wrong! all strings seem to now be twines</span><br />
<br />
def equalStrings := "abc".bare() == `abc`.bare()<br />
<br />
====Regular expression quasi parser====<br />
<br />
The regular expression quasi-parser gives <span class="e">''E''</span> much of the CGI scripting power that Perl and Python share. Since <span class="e">''E''</span> runs on top of a jvm with all the startup time such jvms entail, using <span class="e">''E''</span> for CGI scripts ''per se'' is not recommended. However, if one uses the distributed computing power of <span class="e">''E''</span> to run CGI-like <span class="e">''E''</span> programs as services for a Web server, one can achieve the same effect, and receive a number of bonuses unavailable in Perl and Python. The example Web server written in <span class="e">''E''</span>, shown at the end of the book, was designed with just this thought in mind.<br />
<br />
====JPanel====<br />
<br />
The JPanel quasi-parser processes visually understandable strings into complex window panel layouts for gui applications. It is a most remarkable and useful example of quasi-parsers in action, giving the developer a rather WYSIWYG presentation of his windows. Thus the <span class="e">''E''</span> programmer has no need to resort to the typical inflexible IDE-specific drawing tools that produce code no one can read and absolutely no one can edit. Under the covers, the JPanel uses the GridBagLayout manager to compose the panel, giving it a flexibility comparable to the TK layout system from TCL (which actually inspired the JPanel). Unlike the typical visual layout editors in Java IDEs, the JPanel system is able to define a broad range of ''resizable'' windows simply and intuitively.<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
# define the panels explanation,label, field, okButton, cancelButton, logo<br />
# pad1, pad2, which are label fields before <br />
# this example begins<br />
def composedPanel := <br />
JPanel`$explanation.Y > ><br />
$label $field ><br />
$okButton $cancelButton $pad1.X<br />
V $pad2 $logo`</nowiki><br />
<br />
</pre><br />
<br />
In this layout, the explanation (presumably a textArea) is at the top of the composedPanel, with the label and field left-to-right underneath, and the okButton to the left of the cancelButton/logo area arranged top-to-bottom. This is a layout for a 3-wide, 4-high grid of cells, though some the panes fill multiple cells, and the rules for which cells grow are sophisticated, as described next:<br />
<br />
The ".Y" says that the explanation should soak up any extra vertical space. The ".X" says the field should soak up any extra horizontal space. The two ">" symbols say that the explanation should span all three of the columns of this pane. The field fills two horizontal cells as denoted by the ">" which follows it. The "V" in the lower lefthand corner says that the okButton should fill two vertical cells.<br />
<br />
When this pane is part of a resizable window, enlarging vertically makes the explanation larger. Enlarging the window horizontally enlarges the field but not the label. Both the cancel button and the okButton should remain the same size regardless of resizing since the extra space is being soaked up elsewhere.<br />
<br />
If several elements have ".Y", the extra vertical space is divided evenly among them; similarly fields with ".X" share extra horizontal space.<br />
<br />
The space characters used to separate the elements of this layout have no meaning to the quasi-parser; we have used the space to create a visual representation of the layout that makes it easy to see the layout even though this is just code.<br />
<br />
It is not possible to lay out all possible compositions with a single JPanel, but JPanels can dramatically reduce the nesting of panels compared to Java applications, while making the layout visually clear in the code itself. And of course, you can always place JPanel-laid-out panels inside of other JPanel layouts. The result is tremendously more compact, easier to understand, and easier to maintain than the result of nesting large numbers of Swing Box layouts.<br />
<br />
A similar quasi-parser, the swtGrid, is included for layout of SWT panels. The main difference, as shown in later example code, is that the swtGrid requires a first entry that is the parent panel for the laid out components, e.g.<br />
<br />
def label := <widget:makeLabel>(frame, SWT.getLEFT())<br />
swtGrid`$frame: $chatArea.X.Y<br />
$label.X<br />
$commandLine.X`<br />
<br />
<span class="note" style="color:red">Improve this discussion</span><br />
<br />
====SQL====<br />
<br />
The SQL quasi-parser can be used to execute SQL statements and queries. Many languages use simple string substitution to build SQL queries, but this opens the risk of SQL injection attacks, where the user (attacker) supplies input to a query that is misinterpreted as part of the SQL statement. Using a quasi-parser, E prevents this possibility. For example, we don't have to worry about the quote character in this user's name:<br />
<br />
def name := "O'No! $@?"<br />
sql`INSERT INTO users (userName, karma) VALUES ($name, 0)`<br />
<br />
For details, see the [[SQL]] page.</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Quasi-Literals_and_Quasi-ParsersWalnut/Ordinary Programming/Quasi-Literals and Quasi-Parsers2010-06-09T10:58:57Z<p>ThomasLeonard: SQL quasi-parser</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Quasi-Literals and Quasi-Parsers===<br />
<br />
E supports ''quasi-parsers''. A quasi-parser allows one to compress large numbers of operations into a succinct notation (a ''quasi-literal'') in a specific problem domain. Writing your own quasi-parsers (which can be done in <span class="e">''E''</span> itself, as the JPanel quasiparser described below was written) is beyond the scope of this book. However, <span class="e">''E''</span> comes with several quasi-parsers built in: a simple quasi-parser, a regular expression quasi-parser, a JPanel quasi-parser for Swing, and a swtGrid quasi-parser for SWT.<br />
<br />
====Simple quasi-parser====<br />
<br />
The default quasi-parser is a text manipulating parser capable of extracting data from strings and constructing new strings. In its simplest form, it is a clean and simple way of constructing strings for printing:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def a := 3<br />
def answerString := `The value a is $a, and a times two is ${2 * a}.`<br />
println(answerString)</nowiki><br />
<br />
</pre><br />
<br />
Here we use a simple quasi-parser to build an output string in a fashion similar to the printf statement in C. Quasi literals are enclosed in back-ticks. A dollar sign denotes the beginning of a description of a value to be inserted at the dollar sign location. If the dollar sign is immediately followed by a variable name, the value of that variable is used. If the dollar sign is followed by an open brace, everything up to the close brace is evaluated to compute the value to be substituted (so you could put "$" inside the braces to put a dollar sign in the string, as well as doing arithmetic as in the above example). Quasi-literals can span multiple lines, in which case the carriage return is part of the structure.<br />
<br />
A more sophisticated use of simple quasi-literals is for pattern matching. Here we parse a sentence:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def line := "By the rude bridge that arched the flood"<br />
if (line =~ `@word1 @{word2} rude @remainder`) {<br />
println(`text matches, word1 = $word1`)<br />
}</nowiki><br />
<br />
</pre><br />
<br />
The string on the left of =~ is compared to the quasi literal on the right, evaluating true if the string can be parsed in conformance with the quasi literal. The "@" asserts that any text can match this part of the string, and the variable declared after the "@" contains that text at the end of the evaluation. The variable "word2" is enclosed in braces to offset it from the word "rude" immediately following it, which would look like part of the variable name without the offset.<br />
<br />
In this example, the minimal string that can get a match would be space-space-"rude ", in which case the data extracted for variables word1, word2, and remainder would all be zero-length strings. As it is, at the end of the evaluation, word1=="By", word2=="the", and remainder == "bridge that arched the flood".<br />
<br />
A single quasi-literal can contain dollar signs as well as "@"'s, in which case the results of the dollar sign evaluations will be included in the matching conditions.<br />
<br />
The '''int''' guard will not convert strings to ints, so to extract an integer from a string, use something like this:<br />
<br />
def line := "The number 5"<br />
def `The number @xString` := line<br />
def x := __makeInt(xString)<br />
# value: 5<br />
<br />
For floating-point numbers, you can use '''<import:java.lang.makeDouble>.parseDouble(...)'''.<br />
<br />
Quasi-literals can almost always be treated as strings. They accept almost all of the string protocol (technically, the quasi-literals are of type "twine"). The one place where they cannot be treated as strings is in comparisons to actual strings. To compare a quasi-literal to a string, use the "bare" method: <span class="warn">this is now wrong! all strings seem to now be twines</span><br />
<br />
def equalStrings := "abc".bare() == `abc`.bare()<br />
<br />
====Regular expression quasi parser====<br />
<br />
The regular expression quasi-parser gives <span class="e">''E''</span> much of the CGI scripting power that Perl and Python share. Since <span class="e">''E''</span> runs on top of a jvm with all the startup time such jvms entail, using <span class="e">''E''</span> for CGI scripts ''per se'' is not recommended. However, if one uses the distributed computing power of <span class="e">''E''</span> to run CGI-like <span class="e">''E''</span> programs as services for a Web server, one can achieve the same effect, and receive a number of bonuses unavailable in Perl and Python. The example Web server written in <span class="e">''E''</span>, shown at the end of the book, was designed with just this thought in mind.<br />
<br />
====JPanel====<br />
<br />
The JPanel quasi-parser processes visually understandable strings into complex window panel layouts for gui applications. It is a most remarkable and useful example of quasi-parsers in action, giving the developer a rather WYSIWYG presentation of his windows. Thus the <span class="e">''E''</span> programmer has no need to resort to the typical inflexible IDE-specific drawing tools that produce code no one can read and absolutely no one can edit. Under the covers, the JPanel uses the GridBagLayout manager to compose the panel, giving it a flexibility comparable to the TK layout system from TCL (which actually inspired the JPanel). Unlike the typical visual layout editors in Java IDEs, the JPanel system is able to define a broad range of ''resizable'' windows simply and intuitively.<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
# define the panels explanation,label, field, okButton, cancelButton, logo<br />
# pad1, pad2, which are label fields before <br />
# this example begins<br />
def composedPanel := <br />
JPanel`$explanation.Y > ><br />
$label $field ><br />
$okButton $cancelButton $pad1.X<br />
V $pad2 $logo`</nowiki><br />
<br />
</pre><br />
<br />
In this layout, the explanation (presumably a textArea) is at the top of the composedPanel, with the label and field left-to-right underneath, and the okButton to the left of the cancelButton/logo area arranged top-to-bottom. This is a layout for a 3-wide, 4-high grid of cells, though some the panes fill multiple cells, and the rules for which cells grow are sophisticated, as described next:<br />
<br />
The ".Y" says that the explanation should soak up any extra vertical space. The ".X" says the field should soak up any extra horizontal space. The two ">" symbols say that the explanation should span all three of the columns of this pane. The field fills two horizontal cells as denoted by the ">" which follows it. The "V" in the lower lefthand corner says that the okButton should fill two vertical cells.<br />
<br />
When this pane is part of a resizable window, enlarging vertically makes the explanation larger. Enlarging the window horizontally enlarges the field but not the label. Both the cancel button and the okButton should remain the same size regardless of resizing since the extra space is being soaked up elsewhere.<br />
<br />
If several elements have ".Y", the extra vertical space is divided evenly among them; similarly fields with ".X" share extra horizontal space.<br />
<br />
The space characters used to separate the elements of this layout have no meaning to the quasi-parser; we have used the space to create a visual representation of the layout that makes it easy to see the layout even though this is just code.<br />
<br />
It is not possible to lay out all possible compositions with a single JPanel, but JPanels can dramatically reduce the nesting of panels compared to Java applications, while making the layout visually clear in the code itself. And of course, you can always place JPanel-laid-out panels inside of other JPanel layouts. The result is tremendously more compact, easier to understand, and easier to maintain than the result of nesting large numbers of Swing Box layouts.<br />
<br />
A similar quasi-parser, the swtGrid, is included for layout of SWT panels. The main difference, as shown in later example code, is that the swtGrid requires a first entry that is the parent panel for the laid out components, e.g.<br />
<br />
def label := <widget:makeLabel>(frame, SWT.getLEFT())<br />
swtGrid`$frame: $chatArea.X.Y<br />
$label.X<br />
$commandLine.X`<br />
<br />
<span class="note" style="color:red">Improve this discussion</span><br />
<br />
====SQL====<br />
<br />
The SQL quasi-parser can be used to execute SQL statements and queries. Many languages use simple string substitution to build SQL queries, but this opens the risk of SQL injection attacks, where the user (attacker) supplies input to a query that is misinterpreted as part of the SQL statement. Using a quasi-parser, E prevents this possibility. For example, we don't have to worry about the quote character in this user's name:<br />
<br />
def name := "O'No! $@?"<br />
sql`INSERT INTO users (userName, karma) VALUES ($name, 0)`<br />
<br />
For details, see [http://labs.it-innovation.soton.ac.uk/index.php?option=com_content&view=article&id=74:safe-database-access-in-e&catid=36:experiments Safe database access in E]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/introWalnut/intro2010-02-16T12:43:01Z<p>ThomasLeonard: The user configuration file</p>
<hr />
<div>[[Category:Walnut|1]]<br />
== Introduction==<br />
<br />
=== Why E? ===<br />
<br />
Java, Perl, Python, C++, Tcl, and on and on. Don't we have enough languages already? How could we justify bringing yet another programming language into the world?<br />
<br />
In fact, there is still a compelling reason for developing better programming languages: we keep on writing more complicated programs. And worse, we keep on writing more complicated systems of interdependent programs.<br />
<br />
We have entered the age of globally distributed computing with a vengeance. Anyone who has cobbled together a major system with a hodgepodge of Web servers, Java, JSP, SQL, CGI, CORBA, RMI, XML, and Perl knows that this cannot be the toolset we will use in 20 years. The sooner we move up to the tools of 20 years hence, the better off we will be. Into this situation we introduce <span class="e">''E''</span><nowiki>:</nowiki><br />
<br />
{| style="float: right; width: 2in; border-style: inset; border-width: 3;background-color: #FFFF99; font-size:80%" <br />
|<span class="e">E</span> uses a specific flavor of capability-based security known as ''object capabilities''. With object capabilities, capability-oriented programming has the same flavor as object-oriented programming, except that capability-oriented programming takes the usual OO strictures more seriously. Often when using object capabilities for security, one finds that a more secure program is simply a program that follows OO principles of modularization more closely.<br />
|}<br />
<br />
* <span class="e">''E''</span> has significant advantages compared to other popular programming languages for distributed computing. As one quick example of its power, <span class="e">E</span>'s ''promise-pipelining'' architecture ensures that ''deadlocks cannot occur.''<br />
<br />
* <span class="e">''E''</span> has dramatic advantages for ''secure'' distributed systems. All communication in <span class="e">''E''</span> is strongly encrypted, transparently to the programmer. Capability-based security enables the concise composition of powerful patterns of interoperation, patterns that enable extensive cooperation even in the presence of severely limited trust. Excluding user interface code, a simple but effective peer-to-peer secure chat system has been written in less than 30 lines of code; no more lines of code were required to write a basic digital-money bank server ''despite the severe security issues involved''. When the time comes for a security inspection, capability security allows simple reachability analysis to exclude huge swaths of code because they cannot embody a threat. As a consequence, auditing a system for security becomes cost effective to an extent that is simply unimaginable with other approaches, as documented in [http://www.combex.com/papers/darpa-report/index.html the DarpaBrowser report]. With <span class="e">''E''</span>, it is straightforward to create systems that run across the Internet that are as secure and safe as if the entire system were running on a single computer in your basement. As one of the original developers of Smalltalk observed, upon learning about the object-capability paradigm from <span class="e">E</span>, capability security is "natural security": if you shouldn't use it, you just can't see it.<br />
<br />
* <span class="e">''E''</span> can even enable the fearless yet powerful use of multi-party limited-trust mobile code. "Mobile code" is just about anything executable on your computer that you get from somewhere else. Every time you turn on a word processor, play a game of Solitaire, or double click on an email attachment, you are executing mobile code written by someone you probably don't know and should not trust. Yet we give Solitaire, Barbie Fashion Designer, and Christmas Elf Bowling the full power to read our most private documents, sell them on EBay to the highest bidder, and then delete all your files. Our grandchildren will laugh at how silly this was, yet today there is no choice. If Microsoft used <span class="e">''E''</span> instead of Visual Basic for its application language, Word and Excel would not be vectors for attacks like the original Love Letter virus. If all software were written in <span class="e">''E''</span>, Klez and BackOrifice could never have existed: indeed, the term "virus", so loved by the press because it implies incurability, would never have been applied to computing.<br />
<br />
These qualities cannot be achieved with traditional security approaches. Do not expect the next release of Java, Windows, or Linux to fix the problem: the flaws in these systems lie at the heart of their architectures, unfixable without breaking upward compatibility, as we shall discuss in the chapter on Secure Distributed Programming. Of course, there is nothing to prevent people from advertising that they are releasing a new, upward compatible, totally-secure version of a product. Just don't jump off the Brooklyn Bridge to buy it.<br />
<br />
<span class="e">''E''</span> wraps these strengths in a C/Java syntax to make it quickly comfortable for a large number of software engineers. It is built with objects at the core of its design, making it easy to write modular, readable, maintainable software using the strategies familiar from Java. It has the kind of powerful string handling that will be recognized and seized upon by the Perl programmer. For both better and for worse, <span class="e">''E''</span> is a dynamically typed language like Smalltalk, not a statically typed language like Java. Users of Perl and Python will immediately assert this is an advantage; Java and C++ programmers will not be so sure. A discussion of the merits and demerits of static typing could fill a book the size of this one. Many of the most complex yet most reliable systems in the world today have been developed with dynamically typed languages. If you are a Java programmer, unshakably convinced of the perfect correctness of static typing, all we can do is urge you to try E first and form your conclusions later. We believe you will find the experience both pleasant and productive, as the long heritage of programmers from Scheme to Smalltalk to Perl and Python have found in the past.<br />
<br />
=== Why not E? ===<br />
<br />
<span class="e">''E''</span> is not a panacea. The current implementation of <span class="e">''E''</span> runs on top of the Java Virtual Machine. As such, it is not a good language for low-level machine manipulation. So do not try to use <span class="e">''E''</span> for writing device drivers. And <span class="e">''E''</span>'s performance is quite unfavorable compared to raw C, so do not write the real-time kernel of a missile guidance system with it, either.<br />
<br />
Actually, most arguments over performance miss the most important points about software development. One of the few time-tested truths of software development is, "first get it to work, then get it to work fast". <span class="e">''E''</span> is an excellent language for getting a system to work. Once it is working, you can gain the performance rewards by profiling to see which portions of the code actually affect performance, then rewriting those (typically small) portions in Java, or C, or assembler, depending on your needs. In fact, for many traditional compute-intensive activities, <span class="e">''E''</span> is just as performance-efficient as anything else: when creating windows and buttons on the screen, you use the GUI widgets from the underlying JVM. Since the JVM uses native drawing machinery, there is little distinction among languages when working with windows.<br />
<br />
So perhaps <span class="e">''E''</span> is in fact almost a panacea. But not quite.<br />
<br />
=== Why this Book? Why not this Book? ===<br />
<br />
This book is intended as an introductory text for practical <span class="e">''E''</span> programming. Comparisons to Java are frequent, so some understanding of Java is desirable. If you wish to write software with point-and-click user interfaces, familiarity with either the Java Swing classes or the IBM Standard Widget Toolkit (SWT) is practically required.<br />
<br />
This book is not a language specification. This book is an introduction to get you started and productive. If you encounter some surprising behavior not explained here, please join the e-lang discussion group and ask there: many helpful people can be found. If you need a precise specification, look to the reference materials posted by the language author and keeper, Mark Miller, at the [http://www.erights.org/ ERights web site]. You can join the e-lang discussion group at the same site.<br />
<br />
=== Fireworks In Part II ===<br />
<br />
When a very early version of '''''E''''' and '''''E''''' ''in a Walnut ''were presented to a programmer chat group, this was one of the comments:<br />
<br />
''"I think the key to hooking someone is to make them read the whole walnut cause it just looks like another scripting language until you get into the security and distribution then its like fireworks."''<br />
<br />
Though '''''E''''' is a powerful language with which to write single-CPU programs, the main power of '''''E''''' becomes evident only after you move into distributed programming. It would be tempting to introduce the distributed computing features first...except that you can't really do any meaningful computing without the basic data, flow, function, and object structures. So this book introduces "Ordinary Programming" Part I before getting into the serious distributed computing facilities. However, since '''''E''''' was designed in the C/Java syntax tradition, an experienced programmer can probably glean enough from the [http://www.erights.org/elang/quick-ref.html Quick Reference Card] to skip directly to [[Walnut/Distributed Computing|Part 3 on Distributed Computing]]. If you are short of time and have the requisite background, we recommend that strategy. Go back and read Part I when you are convinced that '''''E''''''s power for distributed programming meets your needs.<br />
<br />
=== [[Rune]] and Trace Log ===<br />
<br />
If you have read this far, you will probably want to [[Downloads|retrieve a current version of '''''E''''']]. Follow the installation directions in the distribution.<br />
<br />
You will find the [[rune]] interactive interpreter by going into the '''''E ''''' directory and typing<br />
<br />
<blockquote><br />
<br />
java -jar e.jar --rune<br />
<br />
</blockquote><br />
<br />
Rune will be your friend for experimentation as you learn''''' E'''''. Indeed, you may find, as others have, that rune is useful even when developing ordinary Java: with this scratchpad you can quickly explore what the API for Java really does when you use it, quickly and easily, before you put Java code into the middle of a program that is difficult to test.<br />
<br />
<div style="color:red"><br />
''Crucial note: At the time of this writing, '''''E''''' is in transition to a return-keyword based syntax for returning values from methods and functions. The following examples will only work if you put the following pragmas at the top of '''''E''''' source files: ''<br />
</div><br />
<pre><br />
<br />
<nowiki># E sample<br />
pragma.syntax("0.9")</nowiki><br />
<br />
</pre><br />
<br />
Using Rune: One-line commands start with a question mark prompt and return the result on the next line in a comment:<br />
<br />
<pre><br />
<br />
<nowiki>? 2 + 2<br />
# value: 4</nowiki><br />
<br />
</pre><br />
<br />
Commands that cannot be completed in a single line will receive close-angle-bracket continuations when you press carriage return at the end of the first line; the whole set of lines from the question mark down to the end of the command (the closing brace) will be evaluated when you close the statement:<br />
<br />
<pre><br />
<br />
? if (3 < 5) {<br />
> println("is less")<br />
> }<br />
is less<br />
<br />
</pre><br />
<br />
Another one of the wonderful little '''''E''''' features that helps enormously in rune is the help(obj) function. Type "help(interp)" into rune, and you will get a complete listing of all the methods you can call on the interp object. You will be surprised at first glance by the number of methods there; these methods are explained throughout the course of the book, starting at the end of the discussion of '''''E''''' objects.<br />
<br />
We will present examples both as straight '''''E''''' source and as rune source, depending on how complex the example is.<br />
<br />
The Trace Log will be one of your best friends when you step outside of rune and start writing '''''E''''' programs. When you install '''''E''''', one of the items in the "eprops.txt" file is a specification of the directory where trace information should be written when a program fails during execution. Find your etrace directory (enter <code>interp.getProps()["TraceLog_dir"]</code>), and go there when you need debugging information. This is an important resource--more than one early adopter of '''''E''''' has kicked himself for forgetting that it is there, then spending several hours trying to understand a problem that was simple and obvious if you just looked at the log.<br />
<br />
If you find it annoying to have to keep opening the log file, you can get log messages sent to stderr by setting '''TraceLog_dir''' to '''-'''. You can put configuration settings in '''~/.e/user-eprops.txt'''. For example, this configuration sends trace logging to the console and removes the need to press Return after the program exits dues to an error:<br />
<br />
# ~/.e/user-eprops.txt<br />
DTraceLog_dir=-<br />
e.onErrorExit=report<br />
<br />
Next Part: [[Walnut/Ordinary_Programming|Ordinary Programming]]</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/EmakersWalnut/Ordinary Programming/Emakers2010-02-16T12:38:46Z<p>ThomasLeonard: Directory-based emaker loader</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Library Packages: emakers===<br />
<br />
The <span class="e">''E''</span> library package system is based on ''emakers''. An emaker is an E source file named with ".emaker" as the suffix.<br />
<br />
When an emaker is imported into an application, the code is executed at the time of import, and the result of that execution is returned to the importing program.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeQueue() {<br />
var head := null<br />
var tail := null<br />
def makeCarrier(obj) :near {<br />
var next := null<br />
def carrier {<br />
to attach(nextCarrier) {next := nextCarrier}<br />
to get() {return obj}<br />
to next() {return next}<br />
}<br />
}<br />
def queue {<br />
to push(obj) {<br />
if (head == null) {<br />
head := makeCarrier(obj)<br />
tail := head<br />
} else {<br />
tail.attach(makeCarrier(obj))<br />
tail := tail.next()<br />
}<br />
}<br />
to pop() {<br />
def current := head<br />
head := head.next()<br />
return current.get()<br />
}<br />
to iterate(func) {<br />
var current := head<br />
var i := 0<br />
while (current != null) {<br />
func(i, current.get())<br />
current := current.next()<br />
i += 1<br />
}<br />
}<br />
}<br />
return queue<br />
}</nowiki><br />
<br />
</pre><br />
<br />
'''Side Note: '''This queue does have one interesting characteristic: the iterate method is the feature required to work correctly with E's for-loop. Iterate receives a function that expects 2 arguments: a key and an object. In this queue, the key value is filled with the index of the value in the queue. Iterate walks the entire data structure, invoking the function once for each element.<br />
<br />
==== Where to put your emaker files ====<br />
<br />
Place this queuemaker in a file named makeQueue.emaker, and put the file in the classpath. There are several ways of making <span class="e">''E''</span> aware of the availability of an emaker, corresponding to the several ways Java can become aware of a class:<br />
<br />
* You can place it, or a jar that contains it, on the classpath when you start up the jvm, e.g. using '''java -cp libDir ...''' or '''rune -cpa libDir ...'''.<br />
* You can place it in a zip or a jar and place it in the jvm's ext directory.<br />
* By placing the file in a subdirectory under lib/ext in the java directory system. You can use Java-style package specifications: as in Java, you can put the file in a jar in lib/ext. [ Should we be recommending this? Putting files in the Java installation itself seems like a recipe for conflicts between packages, and lost libraries when upgrading Java. ]<br />
* You can use a directory-based loader (e.g. [http://www.eros-os.org/pipermail/e-lang/2010-February/013416.html]), avoiding the need to set classpath at all and avoiding conflicts between different packages.<br />
<br />
In the below example, we place the file under lib/ext/emakers/com/yourdomain/e/queueMaker.emaker (in your jre directory), and import:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def makeQueue := <import:com.yourdomain.e.makeQueue><br />
def queue := makeQueue()<br />
queue.push(1)<br />
queue.push(2)<br />
for each in queue {println(each)}</nowiki><br />
<br />
</pre><br />
<br />
==== Security of emakers ====<br />
<br />
Emakers have an important security property: they come to life contained in a world with no authority. Such a world is even more restrictive than the Java sandbox used for applets. However, this world is more flexible than the sandbox because authority can be granted and revoked during operation using capabilities, as described in the chapter on Secure Distributed Computing.<br />
<br />
However, while emakers themselves are safe, adding a jar or directory to your classpath has a global effect on the JVM. For example, a jar may contain .safej files that grant emakers access to unsafe Java classes. Therefore you should use a custom loader if possible, rather than modifying the classpath. [ how? ]<br />
<br />
The makeQueue function example is a nice first example of emakers in action because makeQueue and the queues it makes need no authority. For emakers that require authority, by convention we use the Authorizer pattern. Here is an infoWindowMakerAuthor: the infoWindowMaker needs the authority to create windows, so we wrap it in an Authorizer:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
#emaker in file lib/ext/com/skyhunter/infoWindowMakerAuthor.emaker<br />
def infoWindowMakerAuthor(frameMaker) {<br />
def infoWindowMaker(infoText) {<br />
def frame := frameMaker("Information")<br />
def label := <swing:makeJLabel>(infoText)<br />
frame.getContentPane().add(label)<br />
frame.pack()<br />
frame.show()<br />
return frame<br />
}<br />
return infoWindowMaker<br />
}<br />
#.....in using program....<br />
def makeInfoWindow := <import:com.skyhunter.infoWindowMakerAuthor> (<swing:makeJFrame>)<br />
def infoBox := makeInfoWindow("First Bit Of Info")<br />
def detailedInfoBox := makeInfoWindow("Second Bit Of Info")</nowiki><br />
<br />
</pre><br />
<br />
By convention, authors follow the pattern of functions, using an implied run() method to return the Maker that is being wrapped.<br />
<br />
The meticulous reader may have noticed that the JFrame was a capability that needed to be authorized, whereas the JLabel was not. The vast bulk of the Java API is non-capability-transferring, and can just be acquired using import:. Commonly-used exceptions are the JFrame, everything have to do with files in java.io, and the URL object in java.net. For a complete listing of suppressed methods (which are inaccessible in <span class="e">''E''</span> though documented in Java), safe classes (which can be imported directly by emakers), and unsafe classes (which can only be imported using the unsafe__uriGetter, which is not directly available to emakers), see the [http://www.erights.org/javadoc/index.html JavaDoc for <span class="e">''E''</span>].<br />
<br />
<span class="warn" style="color:red">obsolete:</span>Emakers can also just be functions, in which case the naming convention uses "Func" to distinguish it from a Maker:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
#emaker in file lib/ext/org/erights/computeSquareFunc.emaker<br />
def computeSquareFunc(number) {<br />
return number * number<br />
}<br />
<br />
#...in using program...<br />
def computeSquare := <import:org.erights.computeSquareFunc><br />
def squareOfThree := computeSquare(3)</nowiki><br />
<br />
</pre><br />
<br />
There are also functions that require capabilities before they can become operational, in which case they are by convention wrapped in Authorizers, for example, analyzeOutlineFuncAuthor.<br />
<br />
The good news is that, because emakers come to life without authority, they can always be imported with import:, so any emaker can bring in any other emaker (though you won't be able to run the authorizer without sufficient authority). The bad news is that, if you are writing standalone E applications in which the emakers are fully trustworthy (or at least as trustworthy as the program that calls them), it can seem a substantial nuisance at first to be granting lists of authorities just to break your program into packages. If you are writing pure <span class="e">''E''</span> applications that use emakers of your own construction, emakers which you trust totally with the full authority of the system, and you have no qualms about flouting the wisdom of architectural purists around the world, you can take a shortcut by simply granting the unsafe__uriGetter. For example:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def powerfulObjectMakerAuthor(unsafe__uriGetter) {<br />
def file := <unsafe:java.io.File>("name")<br />
def swing__uriGetter := <unsafe:javax.swing.*><br />
def frame := <swing:makeJFrame>("powerful object window title")<br />
def powerfulObjectMaker() {<br />
#....define the objectMaker and the object it makes...<br />
}<br />
return powerfulObjectMaker()<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Note that in this example, one of the things we created from our unsafe__uriGetter was our own swing__uriGetter. Emakers, when they come to life, do have a swing__uriGetter of their own; however, their built-in swing: accesses only the safe subset of swing, much as import: accesses only the safe subset of unsafe:. In the example we create our own swing: that overrides the default swing:, which enables us access unsafe classes such as the JFrame.<br />
<br />
For even more information on the security properties of emakers, see the chapter on Secure Mobile Code.<br />
<br />
==== Exporting multiple objects ====<br />
<br />
As importing an emaker returns the last value in the file, you can export multiple objects by ending with a map. For example:<br />
<br />
# utils.emaker<br />
def foo(x) ...<br />
def bar(y) ...<br />
[ => foo, => bar ]<br />
<br />
They can be used like this:<br />
<br />
def <utils> := <import:utils><br />
<utils:foo>("hello")<br />
<br />
Note: '''<utils:foo>''' is syntactic sugar for '''<utils>["foo"]'''.</div>ThomasLeonardhttp://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Objects_and_FunctionsWalnut/Ordinary Programming/Objects and Functions2010-02-16T12:31:18Z<p>ThomasLeonard: /* E Interfaces */</p>
<hr />
<div>[[Category:Walnut|2]]<br />
<br />
===Objects and Functions===<br />
<br />
As noted earlier, if the file is to use the Swing gui toolkit, it must have a suffix of ".e-awt". If the file is to use the SWT gui toolkit, it must have a suffix of ".e-swt". If the file will run headless, it should be placed in a file with suffix ".e".<br />
<br />
But first, we need to declare what version of E we're using here.<br />
<pre><br />
? pragma.syntax("0.9")<br />
</pre><br />
<br />
====Functions====<br />
<br />
A basic function looks like this:<br />
<br />
<pre># E sample<br />
def addNumbers(a,b) {<br />
return a + b<br />
}<br />
# Now use the function<br />
def answer := addNumbers(3,4)<br />
</pre><br />
<br />
You can nest the definitions of functions and objects inside other functions and objects, giving you functionality comparable to that of inner classes in Java. Nested functions and objects play a crucial role in <span class="e">''E''</span>, notably in the construction of objects as described shortly.<br />
<br />
A parameterless function must still have an open/close paren pair. Calls to parameterless functions must also include the parens.<br />
<br />
Functions can of course call themselves recursively, as in<br />
<br />
<pre># E sample<br />
def factorial(n) {<br />
if (n == 0) {<br />
return 1<br />
} else {<br />
return n * factorial(n-1)<br />
}<br />
}<br />
</pre><br />
<br />
====Dynamic "type checking" and Guards====<br />
<br />
<span class="e">''E''</span> guards perform many of the functions usually thought of as type checking, though they are so flexible, they also work as concise assertions. Guards can be placed on variables, parameters, and return values.<br />
<br />
Guards are not checked during compilation. They are checked during execution, and will throw exceptions if the value cannot be coerced to pass the guard. Guards play a key role in protecting the security properties when working with untrusted code, as discussed in Secure Distributed Computing.<br />
<br />
The available guards include the items below. Some of them are typical types (String, int). Others are used most often in distributed programming, and are explained later in the book. A detailed explanation of all the things you can do with guards is postponed to the [[Walnut/Aditional_Features|Aditional Features]] chapter.<br />
<br />
* int<br />
* char<br />
* float64<br />
* boolean<br />
* String<br />
* void<br />
* notNull<br />
* nullOk<br />
* near<br />
* vow<br />
* rcvr<br />
* pbc<br />
* Data<br />
* Java classes<br />
* <span class="e">''E''</span> interfaces<br />
* subranges and more complex expressions<br />
<br />
import weakpointermaker<br />
makevat 2 args 1)kind of vat, string"headless, awt, swt",<br />
2)name of vat for debugging<br />
import seedvatauthor<br />
authorize it to get a seedvat function with uri getter<br />
seedvat takes 2 args: 1)vat<br />
2)string that is contents of a dot-e file except<br />
all evaluated at once. seedvat function returns a promise for<br />
the result of evaluating that expression. since it evaluates in foreighn vat,<br />
it is a far reference.typical pattern: only do importing and construction <br />
in the expression string<br />
<br />
Here are some quick examples of guards being declared:<br />
<br />
<pre># E sample<br />
# guarding a variable<br />
def title :String := "abc"<br />
# guarding a parameter, and a return value. Note the guard on the <br />
# return value is part of the def line for the function.<br />
def reciprocal(x :float64) :float64 {<br />
return 1 / x<br />
}<br />
</pre><br />
<br />
Different people use different strategies about how much type checking/guard information to include in their programs. In this book, the general style is to use guards sparingly, as might be typical in a rapid prototyping environment. One place where guards must be used with rigor is in the objects on the boundaries between trust realms, in security aware applications; see the Powerbox pattern in the [[Walnut/Secure_Distributed_Computing|Secure Distributed Programming section]] for an important example.<br />
<br />
====Objects====<br />
<br />
Objects, and object constructors, look considerably different in <span class="e">''E''</span> than in Java or C++. We will start our exploration of objects with a simple singleton object.<br />
<br />
=====A Singleton Object=====<br />
<br />
Objects, functions, and variables are defined with the keyword "def"; all of these can be passed as arguments in parameter lists. Methods on an object, in contrast, are defined with the keyword "to":<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def origin {<br />
to getX() {return 0}<br />
to getY() {return 0}<br />
}<br />
# Now invoke the methods<br />
def myY := origin.getY()<br />
</nowiki><br />
<br />
</pre><br />
<br />
Like functions, methods require a parenthesis pair even if there are no arguments. ''(But, Python programmers beware, methods are not functions. Methods are just the public hooks to the object that receive messages; functions are standalone objects)''.<br />
<br />
When invoking the method, the object name and the method called are separated by a dot.<br />
<br />
=====Stateful objects and object constructors=====<br />
<br />
The "class" concept in Java is used to achieve multiple goals. In <span class="e">''E''</span>, these goals are factored out in a different way. For example, Java classes supply a place to put constructors, which have a special syntax unique to constructors. In <span class="e">''E''</span>, objects are constructed by ordinary functions.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
# Point constructor<br />
def makePoint(x,y) {<br />
def point {<br />
to getX() {return x}<br />
to getY() {return y}<br />
to makeOffsetPoint(offsetX, offsetY) {<br />
return makePoint(x + offsetX, y + offsetY)<br />
}<br />
to makeOffsetPoint(offset) {<br />
return makePoint(x + offset, y + offset)<br />
}<br />
} <br />
return point<br />
}<br />
# Create a point<br />
def origin := makePoint(0,0)<br />
# get the y value of the origin<br />
def y := origin.getY()</nowiki><br />
<br />
</pre><br />
<br />
Inside the function makePoint, we define a point and return it. As demonstrated by the makeOffsetPoint method, the function (makePoint) can be referenced from within its own body. Also note that you can overload method names (two versions of makeOffsetPoint) as long as they can be distinguished by the number of parameters they take.<br />
<br />
The (x, y) passed into the function are not ephemeral parameters that go out of existence when the function exits. Rather, they are true variables (implicitly declared with "def" ), and they persist as long as any of the objects that use them persist. Since the point uses these variables, x and y will exist as long as the point exists. This saves us the often tedious business in Java of copying the arguments from the parameter list into instance variables: x and y already are instance variables.<br />
<br />
We refer to an object-making function such as makePoint as a "Maker". Let us look at a more serious example, with additional instance variables:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(var name) {<br />
var x := 0<br />
var y := 0<br />
def car {<br />
to moveTo(newX,newY) {<br />
x := newX<br />
y := newY<br />
}<br />
to getX() {return x}<br />
to getY() {return y}<br />
to setName(newName) {name := newName}<br />
to getName() {return name}<br />
} <br />
return car<br />
}<br />
# Now use the makeCar function to make a car, which we will move and print<br />
def sportsCar := makeCar("Ferrari")<br />
sportsCar.moveTo(10,20)<br />
println(`The car ${sportsCar.getName()} is at X location ${sportsCar.getX()}`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
Inside the Maker, we create the instance variables for the object being made (x and y in this example), then we create the object (car). Note that the variable "name", passed into the function, is explicitly declared with "var", so that it can be altered later; in this case, it is reassigned in the setName() method.<br />
<br />
=====Self-referencing objects=====<br />
<br />
Sometimes in the body of an object you wish to refer to the object itself. A keyword like "this" is not required. The name given to the object is in scope in the body of the object, so just use it:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
var x := 0<br />
var y := 0<br />
def </nowiki>car {<br />
to moveDistance(newX,newY) {car.moveTo(x + newX, y + newY)}<br />
# ....define other methods including moveTo as above ....<br />
}<br />
return car<br />
}<br />
<br />
</pre><br />
<br />
What if you need to reference the object during the object's construction, i.e., during the creation of the instance variables that precedes the definition of the object itself? In the below example, we give the car a weatherReportRadio that is supposed to alert the car to changing weather conditions. This radio requires, as a parameter during its construction, the car it will be alerting. So the radio needs the car during radio construction, and the car needs the radio during car construction.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeRadio(car) {<br />
# define radios<br />
}<br />
def makeCar(name) { <br />
var x := 0 <br />
var y := 0<br />
# using def with no assignment<br />
def car<br />
def myWeatherRadio := makeRadio(car)<br />
bind car {<br />
to receiveWeatherAlert(myWeatherRadio) {<br />
# ....process the weather report....<br />
} <br />
to getX() {return x} <br />
to getY() {return y}<br />
# ....list the rest of the car methods....<br />
}<br />
return car<br />
}</nowiki><br />
<br />
</pre><br />
<br />
Here, we do a "def" of the car with no assignment, then we use the car, then we do a "bind" of the car which binds a value to the car. This looks and behaves like a "forward reference" from C. Under the covers, the statement "def car" creates a ''promise'' for the car, and the ''bind'' statement ''fulfills'' the promise. We discuss promises in greater depth in the [[Walnut/Distributed_Computing|Distributed Computing]] chapter, where they play a key role.<br />
<br />
=====Secret Life of Functions, Multiple Constructors and "Static Methods"=====<br />
<br />
Before we can talk about multiple constructors and the static-method-like behavior in <span class="e">''E''</span>, it is time to reveal the truth about <span class="e">''E''</span> functions. They are in fact simple objects with a single method, the "run" method, that is invoked by default if no other method is explicitly designated. For example, the following square function<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square(x) {return x*x}</nowiki><br />
<br />
</pre><br />
<br />
is really syntactic shorthand for<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def square {<br />
to run(x) {return x*x}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
In the second one, the run() method is explicitly defined. Using this explicit form in a Maker function, you can define multiple constructors, discriminated by the number of parameters they receive. Similarly, by adding methods to the Maker other than "run" methods, you get other "static methods". In the example below, we have a queue Maker with 2 constructors and a non-constructor method. The one-argument constructor requires an initial capacity; the no-argument constructor supplies an initial capacity of 10.<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeQueue {<br />
to run(initialCapacity) {<br />
# ....create a queue object with the specified initial capacity....<br />
}<br />
to run() {return makeQueue(makeQueue.getDEFAULT_CAPACITY())}<br />
to getDEFAULT_CAPACITY() {return 10}<br />
}<br />
# Now use both constructors<br />
def queue1 := makeQueue(100)<br />
def queue2 := makeQueue()<br />
println(`default capacity is: ${makeQueue.getDEFAULT_CAPACITY()}`)</nowiki><br />
<br />
</pre><br />
<br />
Note also that one can use methods such as getDEFAULT_CAPACITY() to achieve the same effect as Java achieves with public static final variables.<br />
<br />
====Polymorphism====<br />
<br />
<span class="e">''E''</span> enables polymorphism through method name matching. In this example, we move both a car and an airplane to a new location using a single common piece of code:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCar(name) {<br />
def car {<br />
to moveTo(x, y) {<br />
# move the car<br />
}<br />
# other methods<br />
}<br />
return car<br />
}<br />
def makeJet(name) {<br />
def jet { <br />
to moveTo(x, y) { <br />
# move the jet, very different code from the code for car <br />
} <br />
# other methods <br />
} <br />
return jet<br />
}<br />
def vehicles := [makeCar("car"), makeJet("jet")]<br />
for each in vehicles {<br />
each.moveTo(3,4)<br />
} </nowiki><br />
<br />
</pre><br />
<br />
====Extends and Delegation====<br />
<br />
An object can refer calls to itself to another object (a "super-object", built by the "super-constructor", faintly similar to the way one uses superclasses in Java) using the ''extends'' keyword: <span class="note" style="color:red">think of better example</span><br />
<br />
<pre><br />
<br />
<nowiki>? def makePoint(x, y) { <br />
> def point { <br />
> to getX() {return x} <br />
> to getY() {return y}<br />
> to getMagnitude() {return (x*x + y*y)**0.5} <br />
> }<br />
> return point<br />
> } <br />
# value: <makePoint> <br />
<br />
? def makePoint3D(x,y,z) { <br />
> def point3D extends makePoint(x,y) { <br />
> to getZ() {return z} <br />
> to getMagnitude() {<br />
> def xy := super.getMagnitude()<br />
> return (z*z + xy*xy)**0.5<br />
> } <br />
> }<br />
> return point3D <br />
> } <br />
# value: <makePoint3D><br />
<br />
? def place := makePoint3D(1,2,3)<br />
# value: <point3D><br />
<br />
? def x := place.getX()<br />
# value: 1<br />
<br />
? def z := place.getZ()<br />
# value: 3</nowiki><br />
<br />
</pre><br />
<br />
Here makePoint3D acts as an extension of makePoint. Inside the ''extends'' clause, we run the makePoint constructor to create the Point upon which the Point3D will be built. This specially constructed point is referred to in the point3D definition as "super"; you can see super being used in the getMagnitude method.<br />
<br />
Using ''extends'' as described above follows the ''delegation'' pattern. Delegation is a simple pattern of object composition in which an object says, "if another object calls me with a method that I don't have defined here, just route the message to this other object, and send the result back to the caller." Delegation is similar to inheritance, but it is conceptually simpler.<br />
<br />
====Extends and Full Inheritance====<br />
<br />
Some experts consider inheritance to be a dangerous feature. A discussion of the pros and cons of inheritance is beyond the scope of this book. However, none of the full-blown examples in this book actually use full inheritance. Delegation, via the simple ''extends'' keyword plus polymorphism serve most of the purposes for which inheritance was intended, and is used everywhere here.<br />
<br />
Having said that, there are times and places where full inheritance is the right answer. The ''extends'' keyword is also used, with one additional convention, to support such full inheritance. In inheritance, the "self" to which a super-object refers is the sub-object of which it is a part, so that the super-object can use methods in the sub-object:<br />
<br />
<pre><br />
<br />
<nowiki># E sample <br />
def makeVehicle(self) {<br />
def vehicle {<br />
to milesTillEmpty() {<br />
return self.milesPerGallon() * self.getFuelRemaining()<br />
}<br />
}<br />
return vehicle<br />
}<br />
<br />
def makeCar() {<br />
var fuelRemaining := 20<br />
def car extends makeVehicle(car) {<br />
to milesPerGallon() {return 19}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return car<br />
}<br />
<br />
def makeJet() {<br />
var fuelRemaining := 2000<br />
def jet extends makeVehicle(jet) {<br />
to milesPerGallon() {return 2}<br />
to getFuelRemaining() {return fuelRemaining}<br />
}<br />
return jet<br />
}<br />
<br />
def car := makeCar()<br />
println(`The car can go ${car.milesTillEmpty()} miles.`)<br />
</nowiki><br />
<br />
</pre><br />
<br />
As seen in the example, the super-object constructor specifies a parameter, "self", which can be used to refer to the sub-object. The sub-object includes itself in the the call to the super-object constructor, thus becoming "self".<br />
<br />
====E Interfaces====<br />
<br />
You can define an interface like this:<br />
<br />
interface Foo {<br />
}<br />
<br />
def foo implements Foo {<br />
}<br />
<br />
foo :Foo<br />
<br />
The interface body can contain method signatures (without bodies).<br />
<br />
When an object is declared as "implements Foo", Foo acts as a "rubber-stamping" auditor, which marks the object as implementing the interface (whether or not it implements any of the methods defined in the interface). When Foo is used as a guard, it checks that the object was stamped by the auditor.<br />
<br />
This allows your module to give out objects and recognise them when they are given back later. However, this cannot be used for security purposes because the interface (Foo) cannot be kept secret. This is because when a non-Foo object is checked with the Foo guard, object.__conformTo(Foo) is called. <br />
<br />
The two functions of Foo (guard and auditor) may be split up using this syntax:<br />
<br />
interface FooGuard guards FooAuditor { }<br />
<br />
def foo implements FooAuditor { ... }<br />
<br />
foo :FooGuard<br />
<br />
This allows the guard to be given out freely while the auditor is closely held, preventing others from creating fake Foo objects but allowing anyone to check that a given object is a genuine Foo.<br />
<br />
Presumably, you could also implement a public auditor that actually performed some kind of check on an object, and then used the rubber-stamping auditor to stamp it if it passed the checks [how?].<br />
<br />
The interface construct is likely to change in future[http://www.eros-os.org/pipermail/e-lang/2010-February/013432.html].<br />
<br />
====General method name matching and E.call()====<br />
<br />
Delegation with extends does a straight pass-through of the method call. It is possible to intercept collections of calls before delegating them, using ''match''. In this example, we count the number of calls made to a car:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def makeCalledCountCar(name) {<br />
def myCar := makeCar(name) <br />
var myCallCount := 0<br />
def car {<br />
to getCallCount() {return myCallCount}<br />
match [verb,args] {<br />
myCallCount += 1<br />
E.call(myCar,verb,args)<br />
}<br />
}<br />
return car<br />
} </nowiki><br />
<br />
</pre><br />
<br />
In "match[verb,args]", the verb is a string specifying the name of the method being called, and the args is a list of arguments. If the car is called with a method that is not defined in a "to" statement, the name of the method and the arguments are bound to the variables inside the square brackets. We then increment the call count, and finally forward the message using the E.call function. E.call(...) takes as arguments the target object for the action, the name of the method to call, and the list of arguments for the method to invoke. You can manually use E.call() like this:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def car := makeCar("mercedes")<br />
E.call(car, "moveTo", [3,4])<br />
# which is equivalent to<br />
car.moveTo(3,4)</nowiki><br />
<br />
</pre><br />
<br />
In this example, the elements for the argument list are placed in square brackets to form an <span class="e">''E''</span> ConstList, described later in this chapter.<br />
<br />
The match construct is useful for making "adapters" when interfacing to Java. Here we build a singleton object that can be used anywhere a java.awt.event.MouseListener would be used; the match clause is used to absorb and discard events in which we are not interested:<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
def mouseListener {<br />
to mouseClicked(event) {<br />
# process the event<br />
}<br />
match [verb,args] {}<br />
}</nowiki><br />
<br />
</pre><br />
<br />
This general purpose matching is also useful in security applications when building facets and revocable capabilities, as described in the chapter on Secure Distributed Computing.<br />
<br />
====Edoc, the <span class="e">''E''</span> equivalent of JavaDoc====<br />
<br />
E supports the construction of javadoc-style comments that can be postprocessed into HTML documentation. For this purpose, the "/** ... */" comment format has been specially reserved; comments of this style can only appear in front of a function/object definition (a "def" statement), or in front of an object method definition (a "to" statement):<br />
<br />
<pre><br />
<br />
<nowiki># E sample<br />
/**<br />
* Add 2 numbers together.<br />
* <p><br />
* Currently works with any objects that support the "plus" method<br />
*<br />
* @param a the first number. <br />
* @param b the second number<br />
* @return the result of adding. <br />
*/<br />
def adder(a, b) {return a + b}</nowiki><br />
<br />
</pre><br />
<br />
For more information on how to generate Edoc HTML from your <span class="e">''E''</span> programs, see the [[Walnut/Additional_Features|Additional Features]].<br />
<br />
====Under the covers: Everything is an Object====<br />
<br />
We have already discussed the fact that functions are really objects with a single method, "run". Functions-as-objects have one practical consequence that would be surprising in the absence of understanding. You cannot create two functions with different numbers of parameters and have them overloaded:<br />
<br />
<pre><br />
<br />
<nowiki># E syntax<br />
def times2(a) {return a * 2}<br />
def compute(a,b) {<br />
def times2(c,d) {return (c + d) * 2}<br />
# ....do computation...<br />
# The following line will throw an exception<br />
def answer := times2(a)<br />
return answer<br />
}</nowiki><br />
<br />
</pre><br />
<br />
<font color="#FF0000">This would throw an exception because the inner definition of the function-like object times2 completely shadows the outer times2.</font><br />
<br />
<font color="#FF0000">Not only functions, but also built-in constants like integers and floats, are objects. Operators such as "+" are really shorthands for message passing: 3.add(4) is identical to 3 + 4. This is why the operation</font><br />
<br />
<pre><br />
<br />
<font color="#FF0000">"The number is " + 1</font><br />
<br />
</pre><br />
<br />
<font color="#FF0000">works but</font><br />
<br />
<pre><br />
<br />
<font color="#FF0000">1 + " is the number" </font><br />
<br />
</pre><br />
<br />
<font color="#FF0000">does not. A string knows how to handle a concatenate message with a number as the argument, but an integer is clueless what to do with an add of a string.</font><br />
<br />
<font color="#FF0000">Since "+" is really just shorthand for "add", you can construct objects that work with the "+" operator just by implementing an "add(argument)" method in the object.</font><br />
<br />
====Under the covers: Miranda Methods====<br />
<br />
There are a number of messages to which all normal objects respond, known as Miranda Methods. One example of such a method is the printOn(textWriter) method, which defines how an object will write itself out as by default. Other Miranda methods will be described in other sections of the book. The full list of Miranda methods can be found in the Appendix. You can also see them in rune by typing help(def obj{}) <span class="note" style="red">duplicate of next section, fix</span><br />
<br />
One important note about Miranda methods: they are not forwarded by the ''extends'' structure, and they are not intercepted by the match[verb,args] structure. They are always directly interpreted by the object that receives them.<br />
<br />
====Getting Help About an Object With Rune====<br />
<br />
Another often convenient way of finding the list of methods associated with an object, be it a Java object or an <span class="e">''E''</span> object or an object delivered as part of the <span class="e">''E''</span> runtime, is to use the help(object) function of <span class="e">''E''</span>, often used in rune.<br />
<br />
<pre><br />
<br />
<nowiki>? def add(a, b) {<br />
> return a + b<br />
> }<br />
# value: <add><br />
<br />
? help(add)<br />
# value: an org.erights.e.elang.evm.EImplByProxy<br />
# interface "__main$add" {<br />
#<br />
# to run(:any, :any) :any<br />
# }<br />
#<br />
?</nowiki><br />
<br />
</pre><br />
<br />
In this very simple example you see the "run" method listed here, which is the implicit method for a function. The rest of the methods shown are Miranda methods. For a more sophisticated object than a simple add function, each method in the object would be listed as well.</div>ThomasLeonard