ALU capability (was Re: [E-Lang] Authority -- what is its dual?)

Richard Uhtenwoldt greon@best.com
Mon, 22 Oct 2001 08:34:48 -0700


I will be representing the viewpoint of the functional programming
community in this discussion.  Objects are not an essential part of how
I model programs, though I'm open to change.  Eg, I found Tribble's
explanation just now of how Joule verifiers work really cool.  I'm
learn a lot from MarkM's posts to e-lang.

JAR:
>>- It usually has a very imperative, operational flavor to it.
>>   It begs you to write a recipe, not to describe the result that you
>>   want as functional languages do.

Tribble:
>Almost ever successful "functional" or "logic programming" program is
>written by people who thought operationally about the results.  I've
>seen lots of amateur prolog programs that took forever on trivial
>problems because they were written "declaratively".  In addition, with
>the ability to raise your expressive level of abstraction, you can make
>the operations appropriately abstract for the problem you are solving
>(e.g., match this graph pattern).  This supports conceptual
>decomposition and strong separation of concerns, without sweeping real
>computation issues under the rug.

I side with Tribble on this point: I do not believe the
declarative-programming argument is persuasive.  There are better
arguments for FP, eg, Hughes's Why FP Matters, which emphasizes FP's
ability to abstract.  (I do not think FP is inefficient in use of cpu
cycles or memory.)

Tribble:
>In the E/Joule computational model, lambda is a degenerate form of
>object; that does not mean that all objects are expressible as lambda.

I think that Tribble was just tired when he wrote that, and does not really
believe lambda calculus is incapable of representing objects in their
full generality because Tribble goes on to point out that both models, EiaO
and lambda calculus (which underlies FP of course), are turing complete
and thus capable of representing each other.

I think, however, that the lambda calculus can more gracefully and
succinctly represent object-oriented code than the EiaO model can
represent certain useful constructs easily represented in the lambda
calculus.  I conclude from that that the lambda calculus is the more
general model.  I'm thinking in particular of higher-order functions
like map and foldr.

Moreover, the lambda calculus and its center, the function, have been
applied to disciplines outside computing, like Frege's 1870s
formalization of logic and Church et al's 1920s and 1930s work on some
metamathematical question posed by Hilbert.  Object concepts, OTOH, were
not used before computer programming became important and their use in
*formal* ways (math, symbolic logic, programming and accounting are
formal, most philosophy is not) outside programming has not helped
anyone AFAIK.  E.g., mathematicians, who are pretty promiscuous, have
not applied OO ideas to math.  (They have applied, eg, type theory to
OOP, but that does not support the generality of OO ideas but rather of
type theory.)  Again, more evidence that the lambda model is more
general.

there are other criteria beside generality, but I assert that generality
(being able to express many varied phenomena) is a very good thing in a
model that is applied to as many different areas of life as the model
underlying your programming language is.

This is not strictly an argument against EiaO.  It is an argument that
even if you think EiaO, you should also think that everything is a
function, too.  That sounds inane: I mean that I'm responding narrowly
to a few sentences in Tribble's post rather than to the main issue of
whether EiaO is defective, pernicious or overused.  I think Tribble has
defended EiaO quite well so far.  (Let's see how he does when in the
future I assert that it is weak in abstracting ability and less amenable
to formal reasoning. ;> )

Now to my point that the lambda-calculus model
can gracefully/easily express any OO computation.

I'm not educated enough in the object techniques to go in the reverse
direction, but if anyone else wants to do that, I can suggest a code
snippet I would like to see done in the EiaO model.  It will use
higher-order functions.

MarkM himself explains the basic strategy I will use at the beginning of
http://www.erights.org/elib/capability/ode/ode-objects.html.  I will go
one step beyond what he wrote there and show how  method dispatch
can be done with just lambda calculus.  That last URL gives this next
example of method dispatch:

define PointMaker(x,y) :any {
    define Point {
        to printOn(out)    { out print(`<$x,$y>`) }
        to getX       :any { x }
        to getY       :any { y }
        to add(other) :any {
            PointMaker(x + other getX, y + other getY)
        }
    }
}
define p := PointMaker(3,5)
p getX
p + PointMaker(4,8)

And here's my pure lambda version.  the basic idea is to represent a
message by an "algebraic data type" defined by (Haskell syntax)

  data Message = PrintOn Handle | GetX | GetY | Add Point

and in turn to use, eg, (lambda (printOn getX getY add) (printOn
<argument>)) to represent, eg, PrintOn <argument>.

(define (PointMaker x y)
  (lambda (message)
    (message 
      (lambda (out) 
        (out 
          (lambda (print <out's other method names here>) (print "<$x,$y>")) ))
      (lambda () x)
      (lambda () y)
      (lambda (other) 
        (PointMaker 
          (+ x (other (lambda (printOn getX getY add) (getX))))
          (+ y (other (lambda (printOn getX getY add) (getY)))) ))
      )))
(define p (PointMaker 3 5))
(p (lambda (printOn getX getY add) (getX)))
(p (lambda (printOn getX getY add) (add (PointMaker 4 8)))

I'm assuming that the pure-objects model contains mutation at its core,
and thus I feel justified in including mutation in my basic model, too.
(I did not need mutation in that last code snippet.)  Mutation is not
strictly necessary in lambda calculus, but without an explicit mutation
ADT we sure as hell do not know how to compile some practical categories
of functional programs into efficient machine language, so it is more
honest to include it in the model.

Tribble:
>Also, in Scheme, 
>vectors, lists, etc. are not objects, and they can't be just swept them 
>under the rug. Scheme has specific. built-in magic data-types that cannot 
>be emulated/extended/anything by programmers.

The Scheme programmer who thinks he might want to extend it can instead of
referring to 5 refer to an object that responds to a getValue message, eg,
to (five (lambda (getValue) (getValue))) where

(define five
  (let ((instanceVariable 5))
    (lambda (message)
      (message
        (lambda () instanceVariable) ))))

As long as Scheme can represent objects, I do not see why its having
non-object data is a weakness.  Programmers must exercise forethought,
and calling an object (eg, five) instead of referring to the non-object
datum (eg, 5) whenever you think you might want to extend/redefine is
part of that, right?

I trust Tribble can extrapolate from integers to lists, vectors, etc, in
his head.

Now I'll take the OO side for a paragraph.  I have learned in my reading
of the e-lang list that OO concepts are very helpful in describing
capability OSes.  FP concepts are not particularly helpful in
understanding the design of OSes.  Capability OSes are important, so
that speaks well for OO concepts.