At 04:57 PM 11/2/99 , Ka-Ping Yee wrote:
>Notes:
You'll have to remind me about Python's equality semantics. Not knowing
which is Python's object identity operation, or what the other means, I did
not get the point of your comment.
> 1. This is personal, but it seems surprising that "==" means
> object identity here, and i can imagine a novice asking
> "Why can't i get the contents of just any envelope with
> envelope getContents([])?" I'm very hooked on Python's
> "is" and "is not" operators.
> 2. I wandered through the E language documentation to find the
> proper syntax for throwing an exception, and at first
> thought that the lack of a "throw expression" section on
> the grammar page was an omission. Now i realize that
> "throw" must be a function object provided by the big bang,
> but you might want to make this more explicit on the
> grammar page. In general it was tricky to find the info
> i needed to throw the right kind of exception (no sealer
> documentation yet, throw signature not mentioned on grammar
> page, no UnsealingException signature until i went to the
> Java docs).
You are correct. The state of documentation on the E language still sucks. I believe I (or MarcS?) once asked you to hold off contributing writings during a time when I was doing more writing. I believe we made a mistake. Documentation contributions would be most welcome from everyone! I will, of course, act as editor before posting any docs on the erights site.
> 3. In the above i am using the convention of a leading _ for
> private variables, often seen in C++. Perhaps this could
> be another useful sanity check: variables whose names
> begin with _ are never intended to escape outside the
> scope in which they were defined.
> 4. The above is not tested in E. I just wrote it in a text
> editor (which happens to be vim with E highlighting :) ).
>
>Does this work?
Here is the subset of your code with the problems:
> define BrandMaker make(name) {
> define _key := []
> define EnvelopeMaker make(contents) {
> define Envelope {
> to getContents(key) : any {
> if (key == _key) {
> contents
> }
> }
> }
> }
> define unsealer {
> to unseal(envelope) : any {
> envelope getContents(_key)
> }
> }
Actually, this code contains two problems, one trivial and one interesting.
The trivial one:
"[]" evaluates to a ConstList. ConstLists are PassByCopy and hence without object identity. "==" on two ConstLists compares contents rather than identity. Were this not the case, it would not be semantics-preserving to copy them when passed over the network. This problem is easily fixed by saying either "[] diverge" or "define _ {}" instead, in order to trivially create fresh objects with object identity.
The interesting one:
Let's say your code was being used by the mint in our MintMaker example, and, of course, that Alice and Bob know this. Without trusting Alice, Bob wishes to deposit a payment from Alice and only dispense some service or whatever if he's actually been paid. The mint, of course, trusts neither Alice nor Bob, and must preserve the integrity of money despite their possible misbehavior. Here's how a dishonest Alice can create a BadPurse that fools Bob and violates conservation of the mint's currency.
? define keyStash := null
? define BadPurse {
> to getDecr : any {
> define BadEnvelope {
> to getContents(key) : any {
> keyStash := key
> define BadDecr(amount) {
> # do nothing silently
> }
> }
> }
> }
> }
Alice's BadPurse, when asked for an envelope encapsulating the decr function, hands back a BadEnvelope. Bob's purse then gives Alice's BadEnvelope the key to the mint! The BadEnvelope then puts or send this somewhere where Alice can then use it to engage in further mischief. Finally, Alice's BadDecr function does not decrement anything but claims to succeed, by returning without throwing an exception, fooling Bob's Purse into incrementing its balance and reporting success to Bob.
Cheers,
--MarkM