I get the distinct impression that ObjectFunctional
means object + functional, instead of object * functional. A mere piling on of features instead of a synergistic combination.
In The Beginning were the primitive concepts: gotos and records. And the goto begat the function. And the function begat the higher order function. And the higher order function begat the generic function. Meanwhile, the record begat the abstract data type. And the abstract data type begat the object. And the object begat the prototype. (This is a logical progression, not an actual chronology.)
And ever since The Exile, Code and Data have barely looked at each other instead of engaging in the kind of down and dirty fucking I expect from the words 'Go forth and multiply!'
All elegant languages have code or data subordinate to the other. CLOS has objects subordinate to functions. Self has code subordinate to slots. Has anyone come up with a new
concept that encompasses them both or, as I expect, do other languages merely pile on the junk? -- RichardKulisz
and "patterns". ArcLanguage
and the "compound data objects are functions from indices to values" idiom.
Also, objects and functions do
have a surprising synergy. It makes a lot of sense to treat a function as an "object" (in the MultiMethod?
sense), where it has applicable methods like compose, partial-application, currying, etc. CLOS does subordinate objects to functions, but many more recent ObjectFunctional
languages (Dylan, Goo, Needle) make it clear that the "objectness" of functions is just as real as the "functionness" of methods. -- JonathanTang
That last word better have been an error, otherwise you're doing everything you can to prove my point.
And I'll happily grant the equivalence of code and data at a low level. Like you say, a data object is
just a function from an index to a value. But I'm a high level thinker.
Functional programming organizes programs around generic functions. Organizing programs around classes is blown away by multimethods. Meanwhile, OOP organization of programs around classes/prototypes eliminates multimethods, lazy evaluation and many other things. How do you reconcile that
? -- rk
Why must it be presented as mutually incompatible options. Model with objects when you need to, model with generic functions when you need to, one is more conducive to nouns, the other to verbs, I'd think you need both. Of course that's assuming a language that would allow both.
It's not a question of how you present them. I'm pretty sure you could construct a delevopment environment that presents both on an equal footing, in such a way that they mesh, right after you solve speech recognition. No, the problem is that they ARE mutually incompatible. A single multimethod can wreck the elegant organization of a dozen classes.
Maybe you can explain that position a little more. How can a mulitmethod be any worse than a visitor hierarchy. When you want operations easily added, you use the multimethod, when you want types easily added, you use objects. If you only need single dispatch, objects, when needing multiple dispatch, multimethod. You may be totally correct, but I still fail to see how one ruins the other, can you elaborate further?
Assume you're working in Smalltalk, Self or other halfway decent language. So you've got an integrated environment with a browser of some kind. This browser organizes your program so you can navigate and reason about it.
In OOP, each method belongs to a class, prototype or object. Multimethods destroy that assumption.
I don't follow that reasoning. A multimethod is an object, full of methods. You could browse it too right? It's not like that method would belong in any one class anyway, browsing multimethods would be no different than browsing a visitor hierarchy who's methods also wouldn't be in the classes they worked on. If those environments treated a multimethod as any other object, I see no problems.
[Multimethods subsume traditional object methods, not the other way around. They're much more flexible, and I can't see how they could be said to "wreck the elegant organization of a dozen classes". They don't affect classes at all. Multimethods that dispatch polymorphically on a single object correspond directly to object methods, and multimethods that dispatch on multiple objects elegantly solve problems that are quite messy to implement with object methods. -- DanMuller
Multimethods are good. Multimethods are great. What they aren't
is object-oriented. Especially if multimethods "subsume traditional object methods". Because if they do then you have to cease organizing your code around objects.
- Well, wait a minute. In languages that fully support multimethods, like Lisp, you might use strictly OO code everywhere except places that absolutely demand a multimethod, and then you just go ahead and write one, whereas in a language that doesn't directly support them, you have to drop everything and figure out a kludgy workaround (e.g. in C++, where this can be a serious problem). Double-dispatch may or may not save the day just as well -- but there's an argument for using just the right tool for the problem at hand. Having multimethods doesn't necessarily mean completely ceasing to do things in the simple OO style, but it does mean that, when the need arises, you don't have to fight to do what needs to be done. -- DougMerritt
- What I meant by "you have to cease organizing your code around objects" when I could've said "you cannot organize" ... is that once you have multimethods, organizing your code around objects becomes a hack. An ugly one at that. You break a fundamental principle of the paradigm and you're left with what? -- rk
Where would you put a multimethod accepting three parameters in the Smalltalk hierarchy? If you put it in the class of the first parameter, how do you distinguish between the various methods involved? Especially considering that Smalltalk presents no notion of type to its users. NOW do you understand?
- I personally wouldn't be worrying about multimethods in Smalltalk, since they're not supported, so just do what does work.
To antecedent author; the difference between multimethods and visitor pattern is that you know
that an object accepts a visitor. Can you do the same for multimethods? Probably. Can you do it in a way that's elegant and uniform? I don't know.
Besides, it isn't good enough to subsume FP within OO. Where's the equality in that?
[Why the obsession with organizing only around objects? A multimethod dispatching on one object is exactly
the same as an object method, except for a truly minor difference in syntactic arrangement. If you want to organize your multimethods around objects that they most naturally belong to, you can do so.
In typical Visitor pattern applications, neither class is particularly special; what's important is some process involving both of them. This can't be expressed naturally within the straightjacket of an objects-only organization.
BTW, multimethods are not particularly "functional", so this is actually off topic for the page... ]
Why organize only around objects? Because you need to organize around something
and it needs to be the only thing
you organize around. Elegance and uniformity require this.
So what you organize around can be objects, in which case you lose the FP aspect. Or it can be functions, in which case you lose the objects aspect. Or it can be both, if you find a concept that subsumes them both
There is no "most natural" object around which a multimethod can be organized. That is completely arbitrary bullshit. And you've yet to explain how it's even possible to put two methods with the same selector in the same class.
And I disagree that multimethods aren't particularly FP. They're one of the heights of FP.
[We'll just have to disagree on one thing -- I see no reason that entire programs have to be organized around a single principle.
An object method is obviously associated with a single class. If I write a multimethod that does exactly the same thing as the object method, how on earth can it be "arbitrary bullshit" to say that the multimethod is associated with that object? If I were to write in a comment for you "these methods are associated with this class", what's arbitrary about it? It's quite deliberate.
Two multimethods with the same parameter would not be "in" the same class, since multimethods aren't "in classes". But you can organize and comment your code any way you like -- however makes sense for your application and architecture. So it's easy to associate
methods with a class.
Multimethods are not particularly FP. In Common Lisp, for instance, they often have side effects. They are another, and more flexible, way of organizing polymorphic
I agree that associating a multimethod with a class is a deliberate act by a user. That's the problem. That's what makes it arbitrary. Because it's a deliberate choice
, whereas object methods just don't feel that way. And the asymmetry of single delegation ensures you don't
have a choice.
This is the same reason why there must be only one organizing principle. So that users, by which I mean programmers, can't pick and choose what they want in a completely random fashion. Two organizing principles is equivalent to NO organizing principles.
Not true. Physics organizes itself around complementary principles referred to as "waves" and "particles"; natural languages often organize themselves arond complementary principles of 'things' and 'actions' (noun phrases and verb phrases in the case of indo-european languages); biological species organize themselves around two sexes; many human beings organize themselves around "mind" and "body"... Perhaps two is the minimum number of organizing principles that is sufficient?
I don't see referential transparency as the essence of FP. And if it is essential to FP then we have a further problem because the idea of reconciling it
with OOP boggles the mind.
To me, the essence of FP has always been 'higher level concepts for code' just as the essence of OOP has always been 'higher level concepts for data'. That makes them duals to each other.
And if both of them are broken separately then that must mean there's a higher language somewhere, higher than both of them. I want to learn those concepts which are higher level than I can currently imagine. That's what Object Functional means to me
. -- RK
[Honestly, I used to think that OO used to elevate data in some way, too. I no longer think so -- I really see it as little more than a collection of packaging and syntactic conventions. And over the years I've come to see those conventions as a potential straightjacket, because there are more ways to organize programs, and some of them make more sense in some situations.
At the bottom, there's only data, and a processor to interpret it. The higher level concepts are things we invent to manage the complexity that arises from there. I don't think this is like physics, where we seek to deconstruct the laws of the universe to find their simplest underpinnings -- it's almost the opposite, it's an act of synthesis to invent paradigms that fit our own problems and brains. The concepts of data and code are robust and useful. There are other paradigms that are useful too -- declarative programming, for instance, in its various forms.
I am in favor of multi
-paradigm programming, because different ways of thinking fit different circumstances and problems best. I have come to view OO as somewhat obstructive, because it takes several useful concepts -- e.g. polymorphism, packaging/data hiding, reflection -- and binds them tightly together so that they can't be wielded and combined separately. In doing so, I think it may be more limiting than liberating.]
You mean, you want to AVOID reflection? Or data hiding? Or polymorphism?
What do you refer to when you say that OO is a collection of syntactic conventions?
I agree that OO is a straightjacket. That's why I want a higher paradigm, one that embraces other legitimate concepts/tools/principles from FP. However, this doesn't mean that OO doesn't elevate data, because it does. And it doesn't mean that putting you (the programmer) in a straightjacket is bad for those that will have to follow you (users, maintainers). Just because YOU chafe at it doesn't mean it's a Bad Thing. -- RK
Avoid reflection, data hiding, and polymorphism? Heavens no, how on earth would you deduce that? Multimethods depend on polymorphism, for instance. (Note that someone else added "reflection" to my last piece -- I don't usually consider reflection to be part and parcel of OO, although some may.)''
I'd be interested in hearing what you mean by the phrase "elevate data". OO doesn't really change the nature of data at all. It packages procedures and and data together. You can't even truly say that it organizes a program around data -- although that's often how it's described -- because it organizes programs around objects
, which are both
. In fact, much of OO is really not that big an innovation.
I realize that in some circumstances, it might be better to have a simple language, e.g. Java, that places limitations on programmers. But those are circumstances that I'm not terribly interested in. In general, I don't subscribe to the notion that AllFeaturesShouldBeSimple
. Besides, experience shows clearly (at least from where I stand) that simple languages don't
achieve the ideal of easily understood programs; they lead to verbosity, and mediocre programmers still create reams of perfectly inscrutable code, albeit built from simple parts.
I wish you luck in your search for a "higher" paradigm. Personally, I think we already have several perfectly good, useful, and reasonably well understood ways of expressing algorithms -- the problem is that we don't use them. How many programmers use declarative programming techniques? Few, because few of the mainstream languages support it directly, and it can take a lot of work to build yourself a framework that lets you express programs this way. (Perhaps not a good example, because the applications of declarative techniques vary enough that you might need to do that work anyway.) The Visitor pattern in OO languages is a very good example. Here we have a wonderfully powerful tool, polymorphism, and we hobble it by limiting it to dispatch on one object at a time. When our program really needs
multiple-dispatch to express an algorithm, we have to add a lot of cruft in order to get there, obscuring the simple underlying concept.
You really ought to take a close look at CommonLisp
, if you haven't already. CLOS is
an object-oriented system, but different enough from most others that some people have a hard time accepting it as OO. In spite of the fact that the objects are simpler -- not having methods per se -- CLOS is every bit as powerful as other OO languages, and then some. (Who knows? Perhaps multimethods are
the higher paradigm that you're looking for -- try them on for size.)
Oh well, I don't know if I've added anything useful to the discussion, and this certainly has strayed a bit from the ObjectFunctional
topic, but there are some more thought sfor whatever they're worth.
Okay, this will be quick cause I'm chatting with WilliamUnderwood
 at the moment, and we've just figured out a lot of this stuff.
If CLOS' objects don't have methods then they're not objects as far as I'm concerned. There's a reason that I don't program in Lisp, or bothered to learn it much. It's because I have a hard time wrapping my mind around organizing programs around functions. And I'm NOT going to accept learning an alien way of thinking to write decent programs; that's elitist crap. [That's what I'm here for :p]
Multimethods are a problem not just because they don't "belong to" one object/class. Or rather, there are two distinct ways in which multimethods do not belong to an object/class and BOTH are problems.
- The first way in which multimethods don't belong to objects is that in a class' method dictionary, you can't find a multimethod's selector. You can't because with multimethods you can have multiple methods in the same class with the same selector.
- The second way in which multimethods don't belong to objects is that multimethods can access the hidden state of ALL of their arguments. This completely ANNIHILATES any notion of data hiding and makes a mockery of CLOS being OO.
So how do you solve these problems? How do you make multimethods OO?
- First, to make a multimethod it must be possible for you to make a method in ALL of the relevant classes.
- Second, a multimethod belongs to NONE of the classes involved. It belongs to a subclass which has ALL of the relevant classes as superclasses. [Vaguely in the sense of BottomType]
What that means is that you have something resembling a multiple inheritance scheme, but not quite ....
Suppose you have classes A and B, and (A #multimethod: B). The VM looks up the method in A, notices it's a multimethod and so delegates DOWNWARDS to the appropriate subclass based on the type of B.
So #multimethod: can access the hidden state of both A and B, but it's legitimate for it to do so.
This is a lot like a special case of PredicateClasses
actually, which I've condemned. What do you know, a legitimate use for predicate classes .... -- RK
You've taken as an axiom the notion that objects must have "hidden state". I'm assuming that you mean what is called "private" in C++. Many OO languages don't have this notion of data hiding, and it's perhaps a bit outside the mainstream to identify this as an essential
feature of an OO model. But then, that's one of the things that makes it nearly always futile to have these discussions: There is
no well-defined OO theory, and everyone has a different definition of what's essential. In fact, over on ObjectOriented
just posted a notion similar to yours, but going so far as to label encapsulation the
organizing principle of OO and proposing that even inheritance and polymorphism are optional -- something that very few OO proponents would agree with.
For me to understand your first objection, you'll have to explain what a method dictionary and a method selector are, in your OO model. I'm not sure if you're talking about implementation details, tools for reflection, or concepts here. In any case, it's perfectly feasible to associate multimethods with their parameter classes in a fashion that supports finding the multimethods by reflection. I don't know if CLOS can do this or not, but regardless, there's no reason that a language couldn't provide such facilities.
"There's a reason that I don't program in Lisp, or bothered to learn it much. It's because I have a hard time wrapping my mind around organizing programs around functions." You don't have to organize a program around functions to use Lisp, or even C. People were using data-centric program organization in C long before C++ came around. One of the great things that OO brought to the table was polymorphism; but since then, people have studied language features enough to realize that polymorphism is a more general concept than OO. Or perhaps it's better to say that it's a more specific feature than the (varying) agglomeration of features that make up an OO model. Multimethods still leave objects a great deal of power; it's the specific types of the objects that drive the selection of function implementations at run-time, just as in OO models. Certainly sounds to me like objects are still in the driver's seat in that paradigm.
"And I'm NOT going to accept learning an alien way of thinking to write decent programs; that's elitist crap." I honestly don't understand how you can, at the same time, claim to be seeking a "higher paradigm" for programming, and yet so categorically (and rudely) reject the idea of even entertaining thoughts about different ways to organize programs. That seems incredibly contradictory, and destined to find paradigms that are perhaps all of 1/16 of an inch higher than current ones, if even that.
The fact that MultiMethods
don't "belong" to objects is, IMNSHO, a GoodThing
. Consider this obvious example:
You have a language which allows OperatorOverloading
, but has no MultiMethods
. (Please don't argue about the relative value of OperatorOverloading
--that is WAY OffTopic
c = a + b // overloaded operators translate to:
c = a.operator+(b)
with precedence rules in mind, of course.
You want to write a Complex class that can compare equivalent to both Complex and Real numbers.
public Real real;
public Real imag;
// blah blah
bool operator==(Real other)
if(imag) return 0;
return (other == real);
Complex c = new Complex(0, 0);
Real r = new Real(0);
c == r // works
r == c // ERROR
...And you can't modify the Real class, it's a built-in class, and we don't want tampering with builtins, do we?
Implementing operator overloading in MultiMethods
, IMNSHO, is probably the cleanest way to allow overloading of operators to work with builtin types. But that's just my 2c.
Further discussion moved to MultiMethodsDiscussion
In reverse order, let me resolve the contradiction. By alien way of thinking, I don't mean alien to my current way of thinking, but inherently alien to dominant human modes of thought. IOW, UNnatural. A paradigm that can only be learned by a small fraction of the population simply isn't worth the bother. In addition, I never claimed that I
was going to invent a higher paradigm. I've got way too much to do without taking on this undefined project. Just that people ought to start thinking that it needs to be done.
CLOS isn't OO, not due to multimethods, but due to the fact that Lisp gives primacy to functions over data. Lisp hides functions, lambdas, where an OO language hides data, objects. You can only hide objects if you put them inside functions first. You can't NOT organize around functions in Lisp.
I refer to implementation, reflection and concepts. In Smalltalk, a selector is what you'd call the function name. So in the expression (dictionary at: #crazy_evil_fucker put: CCC) the selector is the symbol (unique string) #at:put:. During the method call, the VM looks up that selector in the method dictionary (a key-value index containing selectors as keys and methods as values) of the class of the receiver of the message (dictionary in this case). My concern when I described my scheme wasn't simply to allow finding multimethods by reflection, but implementing multimethods in a way that's consistent with OO.
If you don't have hidden state in objects then security, by which I mean capabilities, becomes impossible. IIRC, Self is a language with no hidden state, with no security. That makes it uniquely suited to building in security by a fundamental modification to the language. -- rk
["inherently alien to dominant human modes of thought" -- A very broad contention that is simply not true. People think as often about actions as they do about things. Life would be pretty boring if all we ever thought about was things.
"Lisp gives primacy to functions over data" -- Not particularly. It doesn't force functions to be subordinate to data, nor vice versa.
"You can't NOT organize around functions in Lisp." -- Beg to differ. Lisp is very flexible.
"You can only hide objects if you put them inside functions first." -- Are you talking here about data hiding in Lisp? We weren't really talking about hiding objects, but rather the internals of an object. I've been given to understand that The Common Lisp package system can be used for hiding object internals. In any case, I didn't intend to advocate Lisp per se, but rather to point out that it has a working system of objects and multimethods, so it might be worthwhile to take a look at it if you're interested in seeing how it can transcend other OO models.
"...but implementing multimethods in a way that's consistent with OO" -- If you're worrying about method dictionaries, then you're starting from a wildly narrow view of what's "consistent with OO". The analogous thing in C++ would be the vtable, which is an implementation detail that is often assumed to exist for illustrative purposes, but needn't exist at all in a particular implementation. With CLOS' multimethods, the implementation has to exactly the same thing -- given the name and specific argument type, find the relevant bit of code, if it exists. If there's only one argument, then this is exactly the same thing that happens in an OO system. The distinction you're trying to make doesn't exist. Multimethods can do everything that OO methods can do -- and not in some trivial Turing-equivalence sense, they do it every bit as conveniently as OO methods do. And that's just a degenerate case of what they're really capable of, using multi-argument polymorphism.
"If you don't have hidden state in objects then security, by which I mean capabilities, becomes impossible." -- I agree that some form of data hiding is desirable for a language, but it's not inherently an OO thing. It's actually more of a module packaging feature -- which points back to my opinion that OO models usually intertwine a number of distinct aspects of programming.]
- The knife of the undefinedness of OO cuts both ways. It's inherently a part of this particular model of OO. Likewise, the issues with m-methods are how they fit into an existing model while maintaining the simplicity, consistency and elegance of that model.
- There have been many books written on why the OOness of Smalltalk, Lisp, Java, C++, etc is superior to the rest. This is our contribution to the mess. May the most consistent and elegant 'OO' win. :)
"People think as often about actions as they do about things." Yeah, people also often think of adjectives. Want to tell me what that has to do with programming languages? FYI, OriginOfConsciousness
puts forth the hypothesis that human language developed from adverbs first and finished with nouns. Yet the best way to learn a language now
is to learn the nouns first and leave adverbs last. So I have to repeat myself, thinking primarily in verbs is completely unnatural to human thought. I find it so, and that's the primary contention of every OOP adherent when they state that OO is particularly good at modeling. What is it you thought "modeling" meant? It means mapping human thought.
"Not particularly. It doesn't force functions to be subordinate to data, nor vice versa." You know, you stand a better chance (better than zero) of convincing me by using something other than a bald assertion of the exact opposite of what I believe.
"I didn't intend to advocate Lisp per se, but rather to point out that it has a working system of objects and multimethods". Except it doesn't. What Lisp has is a bunch of idioms made up of functions and lambdas which it calls objects. If you transmute verbs to nouns, I suppose they are objects. But egoizing negating giving doubting going mutating verbing into nouning. <-- didn't catch that? Well how about, I negation allowance charity direction that verbs into nouns crap. And then
you claim that using only verbs is natural to human thought? Fuck that! The only thing worse than using only verbs is to have to compose nouns out of
verbs the way that CLOS does it, and then to have to figure out whether a verb is a verb or whether it's a noun. Now
do you get the problem? FP is unnatural
. It's not a question of power, because I'm pretty sure it's more powerful than OO. And it's not a question of elegance, because ditto. FP is powerful and elegant once you "get it". But most people never "get it" because it's not natural
. And what's the point of learning a language that most people will never understand?
(And the difficulty in reading only verbs is but a fraction of having to write them. There is no verb for 'I'. Hell, 'egoizing' is a verbed form of 'ego' which isn't even the same thing as 'I'. For that matter, verbing and nouning are both verbed nouns. And doubting and mutating are equivocal. Meanwhile, negating is a verbed adjective. So how many original unequivocal verbs are there in that sentence? Two; giving and going. Out of a sentence of 8 verbs, only a quarter are genuine verbs. Nice
"If you're worrying about method dictionaries, then you're starting from a wildly narrow view of what's consistent with OO." That's right. The only worthwhile OO languages are the reflexive ones. If your vtables and classes aren't REAL objects which you can touch and manipulate, then your language is worthless. C++ is worthless.
"Multimethods can do everything that OO methods can do... they do it every bit as conveniently as OO methods do." Gotos can do everything that any other control structure can do. So you're not convincing me on that point. And your assertion that they do so conveniently is severely undermined by your belief that FP is a natural mode of thought. I
don't find it so, so why would I think Lisp's multimethods are more convenient than anything else in Lisp? -- rk
""People think as often about actions as they do about things." Yeah, people also often think of adjectives. Want to tell me what that has to do with programming languages?" ... followed by ... "What is it you thought "modeling" meant? It means mapping human thought." Do I even have to answer this? You're contradicting yourself within the paragraph. My statement was about what people think about, not about the structure of human language. Read it again. I agree that the relevance of human language structure to programming languages is marginal; certainly not compelling enough to argue for forcing programs to be organized around nouns, just because nouns might be a better place to start learning a new human language from.
"You know, you stand a better chance (better than zero) of convincing me by using something other than a bald assertion of the exact opposite of what I believe." What do you want me to do, give you a course on Common Lisp programming? Sorry, you'll have to take my assertion at face value, or make the effort to learn it yourself. If you've already learned it, tell me what makes you think my assertion is false.
"What Lisp has is a bunch of idioms made up of functions and lambdas which it calls objects. " This isn't even close to correct. Common Lisp has simple structures, and classes that are basically similar to structures (just as classes are in many OO languages) but add multiple inheritance, and a well-developed and extensible type taxonomy that they're all part of and which encompasses all the built-in types, too. That all exists separate from, and interoperates with, multimethods.
you claim that using only verbs is natural to human thought? Fuck that! " What's up your ass? I never said that. Read again. All the gobbledygook immediately following this false assertion is completely irrelevant. (Especially since you yourself implied the structure of human language is irrelevant to programming languages.)
"If your vtables and classes aren't REAL objects which you can touch and manipulate, then your language is worthless. C++ is worthless." OK, that's a matter of opinion. But even assuming this definition of "worthless", it doesn't apply to Lisp, which does have class objects. It also ignores the possibility that you can get the reflexive information without having to expose the internals of how it's organized, so no, there is never a need to expose something like a vtable. Furthermore, multimethods in CLOSE are actually objects too, and there's no particular reason that you couldn't get information from those -- whether CLOS provides this, I don't know, but it certainly could.
"Gotos can do everything that any other control structure can do." But not as conveniently, so that's hardly an answer to what I said.
"so why would I think Lisp's multimethods are more convenient than anything else in Lisp?" Can you be more specific about what you find inconvenient?
"... is severely undermined by your belief that FP is a natural mode of thought." Something else that I never said. I'm actually not an advocate for limiting human tools to what fits a "natural mode of thought", because many of the problems that humans solve nowadays are anything but
natural, so this belief would be irrelevant to me in any case. Solving hard problems is easier using powerful tools -- but those tools won't always be simple. I'm much more an advocate of kicking lazy programmers in their butts and getting them to learn new things, rather than dumbing down the tools to match the prevalent mediocracy.]
In reverse order, it's not a question of simplicity. I guess I should've called you in on it the first time you brought it up. It's a question of naturalness. I agree completely about kicking lazy programmers in the butt.
I find the entirety of function-centric thinking inconvenient. Lisp's multimethods derive their inconvenience from Lisp, not from anything inherent to them since when all is said and done, they can
be reconciled with OO as I conceive of it.
Lots of retreading of stuff skipped.
Okay, I did sortof imply that natural languages weren't relevant. My bad. Natural languages aren't
irrelevant. Not at all since programming languages utilize the same mental faculties as natural languages and towards the exact same purpose, communicating with other human beings. What's irrelevant is a simplistic view that 'hey, natural languages have verbs in equal proportion to nouns so verbs must be just as important as nouns'.
To pick just a trivial issue, one of the easiest word orders is SVO - subject-verb-object. VSO is distinctly more difficult. Smalltalk has SVO, Lisp has VSO.
And did you notice that they're called subject
instead of "first object" and "second object"? The asymmetry of single-dispatch is built into nearly all
Hell, I like
the elegance of Lisp's scheme but that doesn't change the fact that it's less natural, more difficult to learn and think in. Especially to most of the world's population which has been taught from birth to think in a different
And that's only a trivial issue.
The question of learning a new language is far from trivial. It is critical
since it doesn't matter how powerful, elegant and useful your language is if nobody will learn it.
- Meaning not everybody, which is substantially different from nobody. Not everybody will learn VHDL, nor Prolog, nor will they learn Category Theory or LinearLogic. Not everybody is expected to. The quest for the philosopher's stone that will solve all problems in the world has long been abandoned. Who cares if Richardkulisz can't read AlgebraOfProgramming because he's allergic to math ? All he can do is to whine about functions feeling "unnatural" to one RK.
And one of the most powerful means of getting people to learn your language is to make it seem
easy to learn, make it seem that they understand the language just by looking at it. Because if you can make people think
they understand your language, that delusion will carry them through to the point where they actually do
understand your language.
So how do you do that? If you want to teach someone a natural language, you give them a big huge vocabulary of nouns to memorize. Very quickly, they'll think they understand conversations around them. And to a large extent, they'll be right. This works because you can compose thoughts
using only nouns. This does not
work for only verbs.
When learning Smalltalk, the student holds the delusion that they know the language just by reading it. That's a ClassBrowser
? Yeah, I know what that is. That's an Integer? Yeah, I know what that is. That's an OrderedCollection
? Yeah, I know what that is too. And on and on and on. The critical thing is that Smalltalk does nothing to break that delusion and pretty soon the student actually does
understand the language.
Lisp doesn't do that because it's based on functions. The first thing you have to learn is what a function is, which is quite unnatural. Then what a lambda is, and that's beyond
unnatural. Then what a higher order function is. Then what a generic function is. Eventually you get to an object. And then you have to ask yourself how the hell
you got an object
from a bunch of functions, cause it sure as hell is beyond you how you'd get a noun out of a composition of verbs.
So let's recap. I want a higher paradigm that treats verbs on the exact same level as nouns. That has all of the power of verbs and nouns. But in order to be natural, that paradigm must have nouns at the lowest level. It doesn't need to have only
nouns at the lowest level, but it needs to have enough of them that someone can delude themselves into learning the language by looking only at the nouns. Power comes from FP, naturalness comes from OO, and I'm not willing to compromise on either
Then again, maybe it's just a question of having to learn Lisp upside down, from the top down. So you learn all about CLOS and objects and classes before you even touch lambdas. I don't know
that this would work, but it has a lot better chance than the way Lisp is currently taught. -- rk
[Although I generally agree with the indented commentary above (which got deleted in the meantime due to the ongoing rk/cc war), and I think that you're overrating the naturalness of noun-centric thinking, these are areas that are very subjective, and you may be right for a large number of programmers -- it's hard to know. My personal experience, learning programming strictly from procedural languages before OO was mainstream, was that this wasn't particularly difficult. The addition of objects later on seemed wonderful, but it took me years to realize exactly what
about them was wonderful -- and it had more to do with polymorphic calls than anything else. But anyway...
You keep pointing out how hard it would be to define objects starting only from functions, but I have just as hard a time imagining teaching them about functions (in which I include methods) if all they know are objects. In fact, I can't imagine teaching "just objects", because what would you do with them if you have no code? So you must be talking about starting with objects and their methods
, and I submit that the differences between an object method and a more general function are truly, truly trivial. Functions (or methods, or some sort of method of performing calculations and transformations) has
to be taught together with data structures (objects), regardless of whether the two things are arranged together in an object or sit next to each other defined in the source code. Interestingly, declarative programming might be an exception -- I suppose there you would teach first about relationships
, and then wave your hands about the fact that the language system itself propagates changes that guarantee that the relationships remain true.
Your last comment, regarding teaching Common Lisp from CLOS outwards, may in fact be a very good thought, and I think I've seen it mentioned in Lisp circles. On Cliki, I've seen at least one wish for the built-in types and functions to be more comprehensively integrated with CLOS.
Now, the difference between methods and single-dispatch multimethods really is trivial, and I actually have no problem with the idea of a language that allows such to be defined and invoked in a more OO-traditional manner, if that really does feel more convenient or "natural" to some programmers. As long as the full power of multimethods is there, too, that would be just fine. It would mean that there are two ways of expressing the same concept, but that's not a tragedy by any means, especially when the different expressions differ so little.]
As far as I can figure out, the difference between methods and functions isn't trivial but non-existent. It seems the word was coined as part of an effort to make talking about Smalltalk impenetrable to C++ programmers, an objective I fully support.
- A method is a kind of function, one associated with a class and/or object.
Objects without code can still perform assignment and return data. They do so in Self.
There is a critical difference between Smalltalk's objects + functions, and Lisp's functions + objects. Even when you're just beginning to learn the language, the functions you can create and call in Smalltalk can be anything
short of lambdas and higher order functions.
In contrast, when learning Lisp, the objects you can store and manipulate are bloody pathetic, just the built-in structures and the like. Lisp's objects are considered too advanced a topic to teach in an introductory course to Smalltalk programmers
, to people who already know all about objects.
- Smalltalk programmers as a category becomes more and more uninteresting these days.
- The basics of OO in Lisp is trivial:
(defclass rectangle ()
(defmethod area ((x rectangle))
(* (slot-value x 'height) (slot-value x 'width))
- ...pretty trivial; 4 lines to define a class and a method, and if you know how Lisp functions work, understanding these 4 lines is also trivial.
- You may be thinking of Lisp's MetaObjectProtocol, which is indeed too complex to teach in an intro class. But then, few other languages have an equivalent to it. Certainly Smalltalk does not, short of GreenSpunning.
The pattern just repeats itself in more and different ways at higher levels. The very first thing I typically want to know at a high level is what a class' name, superclass and subclasses are. Not what functions it has.
And to put the final nail in the coffin, it's a chestnut in OOP circles that structure-centric organization is generally vastly superior to procedure-centric organization. And that this was true long before OOP was ever a gleam in anyone's eye. That in fact it was the cause
of OO's genesis. And unfortunately, Lisp was full-grown before this was realized.
- May we know what "OOP circles" are you talking about ? Nevermind yet another distorition of the history of programming idea to suit your purposes.
I understand why naturalness doesn't matter to you. I mean, you're a programmer or a language designer or whatever. You're only concerned about power or elegance. But that's not all there is to it. There's also the way that human beings use something, the way they interact with it. And that's my
area of study, it's what I do day in and day out. It's what's important to me. So I think I know a fair deal more about naturalness than you do. Not because it's a subjective issue on which we can disagree, but because it's my area of expertise
. -- rk
["Objects without code can still perform assignment and return data. " Well, they can be
data, anyway. But these two abilities alone aren't going to get anyone very far along the path to programming. :-)
"it's a chestnut in OOP circles that structure-centric organization is generally vastly superior to procedure-centric organization." There's some truth to this, although I don't know about "vastly". Certainly in some places that I worked, it was considered good style to organize code so as to put together functions with the declarations of structures that they manipulated -- when
there was a clear association between the two. But there isn't always
such an association.
" ... Lisp was full-grown before this was realized." There seems to be a common misconception regarding Lisp's status as a corpse, and an old one at that. Although Lisp is the second-oldest high-level programming language, and existed in a variety of dialects from early on, CommonLisp
wasn't standardized until much, much later. OO for Lisp arose somewhere in between, closer to the standardization activity, and the CLOS designers were certainly very familiar with extant OO conventions. CLOS was based on two of the four major Lisp object systems that existed at the time, and was added to the draft standard in 1988. (See http://www.cs.umbc.edu/331/resources/papers/Evolution-of-Lisp.pdf
) The ANSI draft for Common Lisp wasn't completed until 1992.
Regarding "naturalness", I'm certainly willing to defer to others as knowing more about this. But I think that NaturalHumanThought
sums it up rather nicely; although certain modes of thought may come more naturally to people, complex problems are invariably solved by inventing and applying new ways of thinking about things. When talking about ways of expressing complicated technical topics, naturalness is a fine secondary
goal to have; but the first
goal has to be to find notations that actually make discussing (or coding) the relevant concepts tractable. ]
Not particularly. I'm not interested in my own background so why would I be in anyone else's? I just assumed you don't have any interest in human-computer interaction. It's a very rare person that does so it's a safe assumption.
(If you're interested in a brief synopsis of my background, interests, and what I do for a living, it' on my home page.)
- Maybe I skimmed too fast, but looking at it again, all that leaps out is databases, a bunch of programming languages, and microprogramming (presumably with AMD 29000 based systems, which puts a lower limit on your age ;-) -- dm
Historically, the concept of a function as in functional programming didn't evolve from GOTO, it evolved from the long tradition of mathematical functions (that go back way before anybody thought of any GOTO, there wasn't any program counter around), and from lambda abstraction of the work of AlonsoChurch?
in lambda calculus which had nothing whatsoever to do with GOTOs. Additionally, objects were begotten some decade earlier than ADT, by the work of KristenNygaard
, and even SmallTalk
came along before any concept of ADT was even talked about.
Say, who coined the term "abstract data type" and when was some first or seminal paper published on the topic? I don't have a strong sense of when this happened, but I would've thought it was somewhere around 1970-1975 or thereabouts.
I think the term appeared first in a paper by Barbara Liskov, Stephen N. Zilles: Programming with Abstract Data Types. SIGPLAN Notices 9(4): 50-59 (1974), and the seminal paper is considered to be John Guttag "Abstract Data Types and the Development of Data Structures" that proposed the algebraic specification of data types. liskov and Guttag wrote later a book on the subject in 86.
- Interesting, thanks. -- dm
If classes don't subsume ADTs, it should be easy to prove this by producing a counter-example. An ADT that CANNOT be turned into a class by a trivial operation. Just because there's a distinction between them (see AbstractDataTypeExamples
) doesn't imply that one doesn't subsume the other.
Similarly, the difference between "gotos inspired functions" (which is absurd) and the more precise "gotos were outcompeted and replaced by functions" is a minor one to anyone who knows anything about the history of LISP, or the creative mental process for that matter! The imprecision hardly merits the repeated venom CC responds with.
[RK: I have a long standing interest in seeing a wide-ranging formal synthesis of ADT and object theory, because to me it seems possible (skipping the question of which object theory). But I haven't seen much that looked like they'd really gotten somewhere on the subject. I haven't looked hard, either, I admit, but still, on this page it seems to me that there should be a difference between what might someday be accomplished versus what has been accomplished to date. I don't think it's been done yet. Neither does that mean it will never be done. If you've some research papers to cite, I'm interested. -- dm]
Both ADTs and object theory are a lot more formal than I'm interested in being.
As far as I'm concerned, ADT just refers to a subset of an object's interface. This seems especially clear to me with the post/pre-conditions in EiffelLanguage
. Just add invariants and you're done.
And that's that
version of ADTs, because the one I was initially introduced to way back when was a lot more primitive and useless as I vaguely recall. So anyways, I'm really
not interested in ADTs. And I'm even less interested in whether they were a backformation as CC claims or whether they were actually obsoleted. -- rk
[It comes up in language design. Yeah, I've been keen on invariants in all languages for ages; first heard about them in programming from CLU, before Eiffel, but I like having the compiler aware of them. -- dm]
Which is precisely why I don't like them. I'm not keen on doing anything
for the compiler's sake. And if you actually need pre/post-conditions and invariants then you probably want FormalMethods
, not some ad hoc junk hacked into an otherwise clean language.
Incidentally, the way I understood ADTs was as Java-style interfaces. Seeing them as part of formal methods puts a slightly different spin on them; ADTs are the formal methods associated with classes. -- rk
[Hmm. Do you have a pointer to something that shows examples of any of that? Maybe I've got a mental block, but it's not ringing a bell.]
Sorry, no I don't. I know even less about formal methods than ADTs. Any interest I had in the subject evaporated when I realized how painful it was.
Note to the other contributors on this page: RK got into the nasty habit of DisagreeByDeleting
. It's fun up to a point, but wiki is not the proper place where his opinionated rants can go unchallenged. Therefore if you notice somehow that in the process of responding RK conveniently deletes my text, please refrain from responding as I might be unable to preserve your text, in the process of reverting his deletion.
RK was offered private wiki space by BenKovitz
where he could rant all day long. However maybe it is worth reminding him that this is WardsWiki