;; foam - functional object-oriented applicative metaarchitecture

f.x = #x f
f x = f.apply x
env1.apply env2 = env1.merge env2

stateful_account: Class {
  balance:  ref 0
  withdraw: amount -> balance = balance#value - amount
  deposit:  amount -> withdraw amount#negate
  show:     () -> "An account with " + balance#value#show() + " EUR"
}

my_account: account#new
my_account#deposit 50
print my_account



functional_account: Class {
  balance:  0
  withdraw: amount -> self { balance: balance - amount }
  deposit:  amount -> withdraw amount#negate
  show:     () -> "An account with " + balance#show() + " EUR"
}

my_account: account#new
my_account2: my_account#deposit 50
print my_account2


Class = {
  new: #copy(Mirror self)
  self: self   ; self is magically injected into every env
}

Monkeypatch: Monkeypatch {
  ...
}


; syntactic sugar
(x,y,z) = Tuple { 1:x, 2:y, 3:z }

h::t = Cons { hd:h, tl:t }
[x,y,z] = x::y::z::Nil = Cons{hd:x, tl:Cons{hd:y, tl:Cons{hd:z, tl:Nil}}}

; let x = 5 in ...
{
  x: 5
  ...
}
; exactly the same as  (x -> ...) 5  !

a -> b  =  Lambda { arg: #a, body: b }
(x,y) -> z  =  Lambda { arg: Tuple { 1: #x, 2: #y }, body: z }
define Lambda#match
define Lambda#| for pattern matching composition
  cf.  a -> b | c -> d