Goodness, this sealer makes a delightful little E exercise! Hopefully one day I will teach an advanced class on secure distributed programming, with E as the language, at which time I shall surely use this as a homework assignment (or even 2 or 3 assignments, tightening the requirements each time--in the first version you're allowed to trust the box or the sealer, for example).
Anyway, I forced myself not to read ping's solution till after I'd done my own, just to see how much variation there might be in the solutions. Ping's solution is more elegant, in that it is shorter and simpler and easier to understand. It also throws a nice exception if you mismatch unsealers and envelopes, whereas mine needs to be even more complicated to support that (though not much). I think mine might have the advantage that it is possible to garbage collect the messages and envelopes (though my knowledge of distributed garbage collection is almost nonexistent, I could easily be wrong). With that, here's the marcs solution:
? def sealSystemMaker new() : any {
> def privateCurrentContent := null
> def sysUnsealer unseal(box) : any {
> privateCurrentContent := null
> box offerContent
> def content := privateCurrentContent
> privateCurrentContent := null
> content
> }
> def boxMaker new(message) : any {
> def box {
> to offerContent {
> privateCurrentContent := message
> }
> }
> }
> def sysSealer seal(message) : any {boxMaker new(message)}
> [sysSealer,sysUnsealer]
> }
# value: <sealSystemMaker>
? def [sealer1,unsealer1] := sealSystemMaker new() # value: [<sysSealer>, <sysUnsealer>]
? def envelope := sealer1 seal("sealed message") # value: <box>
? unsealer1 unseal(envelope)
# value: sealed message
?
> On Tue, 2 Nov 1999, Chip Morningstar wrote:
> > Ping ventures:
> > > define BrandMaker make(name) {
> > > ...
> > > }
> >
> > Now, for an extra 5 points, can you do it *without* using object EQ (or
> > random numbers)?
>
> Yeah, like this:
>
>
> define BrandMaker make(name) {
> define table := [] # I don't know how to make an empty Map.
>
> define sealer {
> to seal(contents) : any {
> define envelope { }
> table[envelope] := contents
> envelope
> }
> }
>
> define unsealer {
> to unseal(envelope) : any {
> if table has(envelope) {
> table[envelope]
> }
> else {
> throw(UnsealingException(
> "envelope not sealed by matching sealer"))
> }
> }
> }
>
> [sealer, unsealer]
> }
>
>
> ... although i suppose you could call it cheating because it
> still uses object identity. Happily, however, i think it does
> not fall prey to the attack described in MarkM's other message.
>
>
>
> -- ?!ng
>