archives

Casting addresses of other Actors considered harmful

For an Actor to cast an address of another Actor is a dubious operation. Instead, an Actor should only cast its own address to interfaces that it implements. For example,

Consider the following definition:

Interface Account with getBalance[ ] ↦ Currency,
                       deposit[Currency] ↦ Void,
                       withdraw[Currency] ↦ Void

The following is an implementation of Account:

Actor SimpleAccount[aBalance:Currency]
     myBalance ≔ aBalance。
     implements Account using  
        getBalance[ ] → myBalance
        deposit[anAmount] → Void afterward  myBalance ≔ myBalance+anAmount   
        withdraw[anAmount] → (anAmount > myBalance) �
                               TrueThrow Overdrawn[ ]
                               FalseVoid afterward myBalance ≔ myBalance–anAmount

 
The above implementation of Account can be extended as follows to provide the ability to revoke some abilities to change an account by providing AccountSupervisor and AccountRevoker interfaces:

The implementation AccountSupervisor below implements the Account interface as well as AccountSupervisor and AccountRevoker interfaces as an extension of the implementation SimpleAccount: 

  Actor AccountSupervisor[initialBalance:Currency] extends SimpleAccount[initialBalance]
  withdrawableIsRevoked ≔ False,
  depositabeIsRevoked ≔ False。
  implements AccountSupervisor using  
     getRevoker[ ]→ ⍠AccountRevoker
     getAccount[ ] → ⍠Account
     withdrawFee[anAmount] → Void afterward myBalance ≔ myBalance–anAmount //  withdraw fee even if balance goes negative
  also partially reimplements exportable Account using
    withdraw[anAmount] → withdrawableIsRevoked �
                           TrueThrow  Revoked[ ]
                           False ⦂ ⍠SimpleAccount.withdraw[anAmount] 
    deposit[anAmount] → depositableIsRevoked �
                           True ⦂ Throw  Revoked[ ]
                           False ⦂ ⍠SimpleAccount.deposit[anAmount] 
   also implements exportable AccountRevoker using
      revokeDepositable[ ] →  Void afterward depositableIsRevoked ≔ True   
      revokeWithdrawable[ ] → Void afterward withdrawableIsRevoked ≔ True

 
For example, the following expression returns negative €3:
   Let  anAccountSupervisor ← AccountSupervisor.[€3]。
      Let   anAccount ← anAccountSupervisor.getAccount[ ],
            aRevoker ← anAccountSupervisor.getRevoker[ ]。
         anAccount.withdraw[€2]                           //  the balance is €1
         aRevoker.revokeWithdrawable[ ]
                                                                  //  withdrawableIsRevoked in is True        
         Try anAccount.withdraw[€5]                  //  try another withdraw
                 catch�  _  ⦂ Void                    //  ignore the thrown exception
               //  the balance remains €1
         anAccountSupervisor.withdrawFee[€4]
                           //  €4 is withdrawn even though  withdrawableIsRevoked
         anAccount.getBalance[ ]  //  the balance is negative €3