Lenses in Babel-17

Google App Engine (GAE) uses a document centric database model (Big Table). Therefore, before digging into the details of how to integrate it with Babel-17, I decided first to implement lenses for Babel-17. A complete implementation is checked into the repository, and it will come out as part of Babel-17 v3.1 . I am pretty excited about applying it to GAE and the standard library of Babel-17.

So a lens in Babel-17 is a value of type lens_, and there is a new keyword lens which is used to create lenses from scratch. The old record update syntax has become part of how lenses work. I will update the Babel-17 spec within the next few days, for now to get a sneak preview of how lenses in Babel-17 work, check out this unit test module for lenses:

module lang.unittest.spec.lenses

val u = {a = 1, b = {i = 2, j = 3}}
val v = u

val l = lens x => x.b.i

#assert l u == u.(l) == 2

#assert typeof l == (: lens_)

u.(l) = 5

#assert u == {a = 1, b = {i = 5, j = 3}}
#assert v == {a = 1, b = {i = 2, j = 3}}

v.b.j = 42
v.(l) = 6
v.a = v.a + 10

#assert v == {a = 11, b = {i = 6, j = 42}}

v.b.j = v.b.i
v.b.i ^= 2
v.b.j =^ 2

#assert v.b == { i = 6^2, j = 2^6 }

l = lens x => x

v.(l) = 77

#assert v == 77

typedef mymap (c : map) = 
    object
      def lookup k = c k
      def lookup_putback_ k = x => mymap (c + (k, x))
      def get k = if c.containsKey(k) then Some (c k) else None end
      def get_putback_ k = 
        (case Some x => mymap (c + (k, x))
         case None => mymap (c - k))
      def this:map = c
    end
  
val c = { 1 -> 2, 2 -> 3, 3 -> 4, 4 -> 1 }
val m = mymap c

#assert m.get 3 == Some 4

m.get 3 = Some 10

#assert m == {1 -> 2, 2 -> 3, 3 -> 10, 4 -> 1}

m.get 3 = None

#assert m == {1 -> 2, 2 -> 3, 4 -> 1}

#catch DomainError try: m.lookup 10
m.lookup 10 = 24
#assert m.lookup 10 == 24

val f = lens x => x.b
val g = lens x => x.i      

u.(f*g) = 13

#assert u.b.i == 13
#assert u.(f*g) == 13

val h = lens x => x.(f).(g)

#assert u.(h) == 13

u.(h) = 79

#assert u.b.i == 79

u.(f).(g) = 80

#assert u.b.i == 80

#catch ApplyError try: u.(2)

#catch DomainError try:
  begin
    u.(2) = 18
  end

#catch 2 try:
  begin
    u.(exception 2) = 18
  end
  
val fst = lens ((x, y) => x, (x, y) => z => (z, y))
val snd = lens ((x, y) => y, (x, y) => z => (x, z))

val x = (1, 2)

x.(fst) = 10

#assert x == (10, 2)

x.(snd) = 13

#assert x == (10, 13)

val x = 10
x += 2
#assert x == 12

x div= 2
#assert x == 6

x =div 18
#assert x == 3

val x = true

x xor= true

#assert not x


end
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: