Skype UI Fail
"On Understanding Data Abstraction, Revisited" referenced
- Lambda the Ultimate
- Jonathan Aldrich's Classic Papers
- Éric Tanter's Object-Oriented Programming Languages: Application and Interpretation
- Kevlin Henney's It Is Possible to Do Object-Oriented Programming in Java
- Guy Steele on Why Object-Oriented Languages Need Tail Calls (Discussion on Lambda-the-Ultimate)
- Michael Bayne's samskivert
- Tommy McGuire's Mad science, abstract data types, and objects
- stackoverflow: How does one declare an abstract data container type in Haskell?
- stackoverflow: Data types compared to OOP objects
- Stuart Sierra on Objects Are Not Abstract Data Types
- Robert Simmons on What does focusing tell us about language design? (Discussion on Lambda-the-Ultimate)
- Yin Wang on ADTs and Objects
- Kurt Schelfthout FORTY SIX AND TWO
- stackexchange: FP and OO orthogonal?
- LShift Frank Shearar Conditional statements, the lambda calculus and early/late binding
- Object-Oriented Programming in ML
- On Not Understanding...
- David Albert Paper of the Week: On Understanding Data Abstraction, Revisited
- Examples from Section 3 in Standard ML by Robert J. Simmons
- Onward! Most Notable Paper Award 2019 for 2009
Emails with Bob Harper
Dell service call... slow, confused.. but gets the job done
is a log of your session. Please save the log for your records.
| 04:05:15 | Session Started with Agent |
| 04:05:22 | William: "Hi" |
| 04:05:23 | Agent: "Thank you for contacting Dell XPS Premium Support. My name is XXXX and my rep ID number is #####. How may I help you today?" |
| 04:05:43 | William: "I was just talking with tech support about my XPL laptop." |
| 04:05:56 | William: "They tried to connect me to hardware support, but the connection failed" |
| 04:06:09 | William: "we are having trouble communicating, so I thought I'd try chat" |
| 04:06:25 | Agent: "I appreciate the opportunity to assist you with this issue." |
| 04:06:31 | Agent: "Please allow me 2 to 3 minutes to pull up your account information. In the meantime, May I have an alternate contact number and the best time to reach you if we have to follow up on the case?" |
| 04:06:52 | William: "the phone number I gave on the login screen here is good. Do you have it?" |
| 04:07:10 | Agent: "Yes." |
| 04:08:55 | Agent: "I see that you are contacting us regarding your XPS L401X , which has windows 7 as the Operating System. Am I correct?" |
| 04:09:12 | William: "yes" |
| 04:09:44 | Agent: "Okay." |
| 04:09:57 | Agent: "May i know what exactly is the issue?" |
| 04:11:13 | William: "THe computer started being slow... VERY slow. opening a folder window took 5 minutes" |
| 04:11:27 | William: "then i reinstalled the operating system.. but it hung during installation and did not complete" |
| 04:11:39 | William: "I ran diagnostics and got a disk error" |
| 04:11:59 | William: "2000-0146" |
| 04:12:13 | William: "it cannot boot at all" |
| 04:12:52 | Agent: "Okay." |
| 04:12:52 | William: "another diagnostic gave DTS Self-test Read error with number 0F00-065D" |
| 04:13:04 | William: "i'm getting tired of repeating this problem over and over again to different people" |
| 04:14:25 | Agent: "I will make sure that this would be the last time you the explain the issue , i will resolve it my the end of the chat." |
| 04:15:04 | Agent: "If you got 146 error we need to run the extended test on hard drive." |
| 04:15:12 | Agent: "Are we chatting from the same computer?" |
| 04:15:27 | William: "no (its broken :-)" |
| 04:16:12 | William: "how do I run the test?" |
| 04:17:05 | Agent: "Turn on the computer and keep on tapping f12 key on the keyboard." |
| 04:17:33 | William: "ok" |
| 04:17:42 | Agent: "I understand that but we need a code in order to replace the hard drive without which it cannot be processed." |
| 04:17:52 | William: "its fine" |
| 04:18:20 | William: "i've done the f12 step.. have the "please select boot device" screen. Please go as quickly as you can" |
| 04:20:36 | Agent: "Sure." |
| 04:20:42 | Agent: "Select diagnostics." |
| 04:21:00 | William: "there is no option named "diagnostics"" |
| 04:21:17 | William: "it has "har drive" "Cd drive" "Network" "Enter PSA+" and "Enter Setup"" |
| 04:21:58 | William: "the last person asked for "diagnostics" too. It annoys me that you do not know the options in your own product" |
| 04:22:33 | Agent: "William by default it should have the option." |
| 04:22:50 | William: "well.. it doesn't" |
| 04:22:53 | William: "i haven't done anything to the computer" |
| 04:23:08 | William: "PSA+ is "pre-boot system assesement" test" |
| 04:23:28 | Agent: "But as the hard drive has issue it is not displaying it select Psa++" |
| 04:24:59 | William: "if you say so" |
| 04:26:04 | Agent: "So once you select that it will run the test and give you the error 146 and after that it will asks you to continue the test or nor select continue." |
| 04:26:07 | William: "it is doing tests now.." |
| 04:26:18 | William: "yes, that is right" |
| 04:26:50 | William: "i've been waiting foryou to tell me what to do then" |
| 04:28:01 | Agent: "select continue and it will continue the test and give you some options let me know what are they?" |
| 04:28:37 | William: "it is continuing with memory test... it wil take about 5 minutes i think. there is no way to skip that test and get to the advanced options... so we must wait" |
| 04:28:59 | Agent: "Yes." |
| 04:34:35 | William: "ok.. it is done" |
| 04:34:48 | William: "it says "do you want to run the remaining tests?"" |
| 04:34:55 | William: "it will take 30 minutes or more" |
| 04:35:08 | William: "but i think these tests are different from the on-disk diagnostis" |
| 04:35:09 | Agent: "Select no." |
| 04:35:14 | William: "ok" |
| 04:35:21 | Agent: "And the it will give you options." |
| 04:35:25 | William: "booting utility partition" |
| 04:35:41 | William: "options: test memory/ test system/ exit" |
| 04:36:55 | Agent: "Select test system." |
| 04:37:09 | William: "ok.. its going" |
| 04:37:56 | William: "express test/ extended test/ custom test/ symptom tree" |
| 04:38:18 | Agent: "Select custom ." |
| 04:39:41 | William: "ok" |
| 04:39:45 | William: "(can you go faster?)" |
| 04:40:18 | Agent: "Sorry we need to run the tests then only we can see the error." |
| 04:40:30 | Agent: "Have you select custom?" |
| 04:40:47 | William: "yes. I already said "ok"" |
| 04:40:59 | Agent: "OK." |
| 04:41:05 | William: "I just want you to respond more quickly. I am waiting a long time between each message" |
| 04:41:21 | Agent: "Oh i am sorry you felt so." |
| 04:41:24 | Agent: "Sure." |
| 04:41:56 | Agent: "Now it will start the test and this test will take around 30 min." |
| 04:42:15 | Agent: "So if you want i can stay or i will give you a call." |
| 04:42:15 | William: "which tests should I select in the custom area?" |
| 04:42:35 | Agent: "Hard drive." |
| 04:42:59 | William: "hmm.. you did not say that before" |
| 04:43:23 | William: "which tests?" |
| 04:43:42 | Agent: "Hard drive extended test." |
| 04:43:52 | William: "that's not an option" |
| 04:43:55 | William: "it has" |
| 04:43:58 | William: "confidence" |
| 04:44:04 | William: "device quick check" |
| 04:44:09 | William: "derive self-test (short)" |
| 04:44:13 | William: "drive self-test (long)" |
| 04:44:16 | William: "read test" |
| 04:44:18 | William: "seek test" |
| 04:44:22 | William: "SMART test" |
| 04:44:25 | William: "Verify test" |
| 04:44:42 | Agent: "Drive self test long is know as extended test." |
| 04:44:46 | Agent: "So please select it." |
| 04:44:57 | Agent: "Known*" |
| 04:45:07 | William: ""known as" doesn't help me, since you are not using the same words as I'm seeing." |
| 04:45:26 | William: "just that one? nothing else?" |
| 04:45:26 | Agent: "It will take 30 min to complete this test ." |
| 04:45:38 | Agent: "Only that one." |
| 04:45:49 | William: "ok.. its running" |
| 04:45:56 | Agent: "Perfect." |
| 04:46:03 | William: "estimted completion time 113 minutes" |
| 04:46:20 | William: "ahh.. it failed already" |
| 04:46:33 | William: "0F00-075D" |
| 04:46:39 | Agent: "Okay what is the error message?" |
| 04:46:44 | William: "that is the error code" |
| 04:47:00 | William: "Msg: DISK -DST Sefl-test Read error" |
| 04:47:13 | William: "continue testing?" |
| 04:47:26 | Agent: "Yes." |
| 04:48:31 | Agent: "Is it running?" |
| 04:48:40 | William: "oh.. it seems to have stopped the test" |
| 04:48:49 | William: ""continue testing" seems to mean "select another test to run"" |
| 04:49:06 | William: "there is an "X" on that test, since it failed" |
| 04:49:34 | Agent: "In this case we will replace the hard drive." |
| 04:49:56 | Agent: "Are you comfortable in replacing the hard drive?" |
| 04:50:38 | Agent: "This is not to rush you, please respond if we are connected." |
| 04:50:47 | William: "ye" |
| 04:50:47 | William: "yes" |
| 04:51:00 | Agent: "Okay." |
| 04:51:21 | William: "yes, i can probably replace it, if its not too difficult" |
| 04:51:27 | William: "i have done things like this before" |
| 04:51:30 | Agent: "So i will send you the hard drive which will reach your place within 2 to3 business days." |
| 04:51:30 | William: "on computers" |
| 04:51:40 | William: "ok" |
| 04:51:42 | Agent: "Okay that really great." |
| 04:53:50 | Agent: "Thank you." |
| 04:54:44 | Agent: "You will also get a call from dell to check if the issue is resolved or not after 3 days ." |
| 04:54:53 | Agent: "And would there be anything else that I may assist you with today?" |
| 04:55:51 | Agent: "It was pleasure assisting you ." |
| 04:56:48 | William: "thanks" |
| 04:57:12 | Agent: "You are welcome." |
If you require further assistance, please visit us at support.dell.com
Talk at MSR on Batches
Batches are a new approach to relational database access, remote procedure calls, and web services.
A Remote Batch statement combines remote and local execution: all the remote code is executed in a single round-trip to the server, where all data sent to the server and results from the batch are communicated in bulk. Batches support remote blocks, iteration and conditionals, and local handling of remote exceptions. Batches are efficient even for fine-grained interfaces, eliminating the need for hand-optimized server interfaces.
Batch services also provide a simple and powerful interface to relational databases, with support for arbitrary nested queries and bulk updates. One important property of the system is that a single batch statement always generates a constant number of SQL queries, no matter how many nested loops are used.
A few more messages about Ensō
In the short term, I think we need to focus on specialized executable specification languages.
Form-based code and Airport boulevard
The Irrationality of the American Home Buyer

(Thanks Google!)
Note that it has huge stand-alone houses that almost completely cover the available space. The alleys are a nice touch, but they aren't very efficient in terms of space. The houses are so close together that you could almost reach out one window and touch the other building.
Consider this analogous random chunk of suburban London. The houses are touching! But that leaves more room for a back yard.

Maybe its just me, but I would rather have my house touch my neighbor's house and have some open space. Having the houses touch actually gives more room for windows that you want to look out. The American style might have more windows, but there is less view.
I am not sure exactly who to blame... It could be the American architects, planners, and builders. It is partly their fault. But in the end they build what American buyers want to buy. And those buyers are not very rational, I fear.
Is there anything we can do?
How to Teach, Write, and Deploy a Partial Evaluator to a Million People in 24 Hours
Working in Scheme, Ludovic Courtès finished the code that evening. He then checked it in to the code base of the GNU Guile compiler. I suspect that it needs a little more engineering to make it completely robust, but there is nothing that can't be taken care of with a little care.
This is a very fun example of practical impact: lecture to deployment in less than 24 hours. Thanks to everyone who attended, and to Ludovic for his extra efforts!
Facebook Insecurity
I recently found out that Facebook is incredibly easy to hack. It allows you to access the reset password page without any email confirmation, and it also does not let you modify your security question. Facebook had better do something about this, especially given that Google+ is now going after them. Please go to this Facebook FAQ page and tell that that the answer is not helpful.
We want to make sure that your account and the information in it stays safe, so once you set up a security question on your account there’s no way to update it. Sorry for the inconvenience.Facebook FAQs
Ensō Data
Enso Introduction
Ensō is a theoretically sound and practical reformulation of the concepts of model-driven software development. Ensō is based on first-class structural descriptions, invertable transformations, generic operations and interpretation.
Structures in Ensō are a specialized kind of graph, whose nodes are either primitive data or collections of observable properties, whose values are either nodes or collections of nodes. From a programming language viewpoint this may seem an odd choice for data representation. However, it is essentially the Entity-Relationship (ER) model, also known as Information Models, which is widely used in the design of relational databases and is also the basis for Class Diagrams in the Unified Modeling Language (UML), which describe the structure of networks of objects. The key point is that structures in Ensō are viewed holistically as graphs, not as individual values or traditional sums-and-products data structures.
A structural description, or schema, specifies some of the observable properties of structures. Schemas are used to check the consistency structures. Some properties can be checked while the structure is being created, but other can only be checked once the structure is complete. Ensō allows modification of structures, which is necessary to create cyclic graphs, but also allows valid structures to be sealed to prevent further changes.
Invertible transformations are used to map one structure into another kind of structure, such that mapping can be inverted to (partially) recover the original structure from the result. One common kind of transformation is called a grammar, which is an invertible transformation between structures and text. Text grammars are invertable because they can be used for parsing and also rendering. Other transformations include Diagram grammars, which map structures into diagrams, were edits on the diagram are reflected in the original structure. Grammars that describe the structure and behavior of user interfaces are used to generate very natural applications. Transformations are also used for querying, template processing, and serialization.
Operations can be guided by schemas or grammars, allowing highly generic operations to be defined for comparison, differencing, merging, projecting and otherwise manipulating cyclic structures. These operations are cyclic maps, which correspond to coinductive transformations. Since schemas and transformations are also structures, they can be merged and transformed using these same generic operations. Transformations on schemas can be applied to instances, to support upgrade and change management of data. The resulting system supports powerful modularity constructs, including feature modules, inheritance, and mixins.
Ensō is based on interpretation rather than code generation. While it is possible to define transformations that generate code in conventional languages, this is rarely (if ever) done in Ensō. Instead all structural descriptions and transformations are interpreted dynamically. Although the current incarnation of Ensō does not include it, we have previously demonstrated that partial evaluation can be applied to Ensō-style interpreters to automatically generate efficient code.
Type Inheritance
interface Stream<T> {
T current();
Stream<T> next();
}
interface BiStream<T> extends Stream<T> {
void insert(T item);
}
The reason is that after applying the "next" operation, the resulting streams do not have "insert" operations. In other words, this program does not type-check.
void pushNext(BiStream<String> s) {
s.next().insert("test");
}
In the literature on static typing of OO languages, what we need here are Self types. Some languages, including Eiffel and Scala, have self types.
Why would you care? Well, there are lots of cases where this kind of modification is useful. Its another concept that is difficult to think about in current languages. The OO example above is nice, but type inheritance also applies to algebraic types (See my "Data Abstraction Revisited" essay for a discussion of the differences). Consider this type, written using Haskell notation:
data Diagram
= Rectangle Int Int Int Int
| Circle Int Int Int
| Composite [Diagram]
If we want to extend this to a new data type, for example, to include polygons and fill colors, we want to say something like this:
data ExtraDiagram inherit Diagram
with Polygon [(Int, Int)]
| Fill Color ExtraDiagram
What this means is Diagram extended with new alternatives, such that the recursive references to Diagram are changed to ExtraDiagram. I've been suggesting a while that functional programming could benefit from inheritance. This is just another example.
Expanded thoughts
Here is one idea. Lets generalize the idea of grammars. A grammar is normally used to parse text to create a parse tree. But if you annotate the grammar with constructors then the parse tree can be instantiated create arbitrary information structures, which we can view as the semantics of the text. If you are careful, then you will find that there can be quite a bit of divergence between the syntax and the semantics; for example, while syntax is tree-based, the semantics may be a graph. We can also run the process backwards, where we take some semantic object and render it into the grammar to create a parse tree, which can then be written out to text. This amounts to putting some clothes onto the abstract semantic structure.
Text --parse(Grammar)---> ParseTree --instantiate(Factory)--> Semantic Structure
Semantic Structure --render(Grammar)--> ParseTree --------display----------> Text
Note that parse and render, which both use the Grammar, are not inverses of each other. Instead, they both output ParseTrees, but they do it from two different directions.
Now the interesting thing is that a Grammar is really just a ParseTree with added structure: to allow for alternation, repetition, and variable data. We don't need to add sequencing, because ParseTree already has that. That is, we can view a grammar as
ParseTreeGrammarStructure = Kleene(ParseTreeStructure)
This is probably not too surprising. The interesting thing is that once we make structural descriptions be values, then we can write the Kleene function, which "grammarizes" any structure. (Its called Kleene after the person who first formalized the idea of alternation, repetition, and sequencing.)
My new language lets me think about, and write down, the Kleene function. And use it in more general ways. For example, I can now contemplate constructing
DiagramGrammarStrucutre = Kleene(DiagramStructure)
This creates a semantic structure for the grammar of diagrams. I can then use it with my generic render routine to create diagrams of any semantic structure:
Semantic Structure ---render(DiagramGrammar)---> Diagram
This brings up the question of parsing diagrams. It turns out that we will edit them rather than parse them, but it will be the topic for a future post.
Smalltalk and the future
But there are few things about Smalltalk that I hate. The first is the idea of an "image". I cannot stand it when my program is tangled with the IDE. It makes it difficult to collaborate, do version control, or deploy final products. I'm also not a big fan of read-eval-print loops (REPL). I like to write code in files, compile them into programs, and deploy them to customers. My IDE should help me write and debug my programs, but stay out of my way otherwise. Perhaps I did too much C programming when I was young. Some people love images, but I don't get it.
The second one is model-view-controller (MVC). I love MV, but I can do without the C. I have always suspected that it is an artifact of the Smalltalk runtime model, which was written right on the metal and did its own bit rendering and mouse tracking. I have to admit I'm not as experienced at GUIs as I am at other kinds of programming, but I've done a few. More modern toolkits don't have separate controllers. The controllers are built into the views (widgets). That is fine with me. Every time I see a library that emphasizes its adherence to MVC (with a capital C) I cringe. For example, does it really help web apps to modularize where to go next from a page?
Other than that, I love Smalltalk. On the other hand, I'm convinced that OO has run out of steam, and should be best used as the foundation for the next dominant paradigm. What is the next paradigm? Models. Yes, that's it! Not UML. Not MDA. Not EMF/QVT. Not Rails. These are good hints about what is to come, but they are still not complete. Hence my current project, to create a Smalltalk of Modeling.
Ruby GUI
wxruby
I'm using ruby1.9 so I need the latest gem. But it is not compiled for 64bit architecture, so I have to build it from source. When I compile, I get an error:
SWIG version 1.3.31 is installed, minimum version required is 1.3.37.But when I used MacPorts to try to upgrade SWIG, it only lets me install version 1.3.31 or 2.0.3_0. But wxruby requires a version between 1.3.32 and 1.3.37 because "SWIG 1.3.39 introduced changes incompatible with swig/fixmodule.rb".
Update: after much pain I got wxruby to run. Here is the post that has the clue. The basic summary is:
1) configure ruby with " --with-arch=x86_64,i386" to get both architectures
2) use Gem to install wxruby-ruby19-2.0.1-x86-darwin-9.gem
3) when you run ruby, you have to say "arch -i386 ruby ...
As I said, I hate OSX every time I have to install software.
shoes
You have to run the shoes application. Its not a library, so I don't think I can use it. But I might have to try.
bowline
Looks interesting, and things seem to work until I try to launch the application:
no such file to load -- rubygemsJRuby/swing
./bowline_twitter/config/boot.rb:3:in `require'
./bowline_twitter/config/boot.rb:3:in `'
./bowline_twitter/script/init:2:in `require'
./bowline_twitter/script/init:2:in `'
I guess I might have to try it...
And all the others... I haven't heard much good about them.
Its at times like this that I pine for my Windows box. It may be ugly, but there is a much better change that things will "just work" than on Un*x or OSX.
New programming model
* Program with forests, not trees
The idea here is that all data/information should be represented explicitly as semantically integrated networks of typed values with attributes and relationships. There are two important aspects to this idea, which immediate distinguish our approach from both OO and FP. In contrast to OO, we declare structures on a larger level of granularity, to capture semantic integrity of collections of objects, rather than on individual objects. An OO programmer sees individual objects (the "trees") but cannot really see the "forest". Relative to FP, we allow explicit cycles, so that our representation is graph-based, rather than being based on trees as in FP. I know that lazy functional programs can express cyclic structures, but the cycles are not observable. We tend to call our forests "models" although it is best not to import too many assumptions from MDD or UML when we use the term.
*Support many languages. This means that we support domain-specific language. In effect, every information model you create is a language. It can have multiple interpretations. The distinction between textual and visual languages is unimportant, because text and graphics are just two different presentations of an underlying information structure.
*Dynamic checking
The structure of a model are described by other models, which represent structural and behavioral constraints. That is, all data is described by metadata. And the metadata can be more interesting than just structural types. At the top we use the typical self-describing models. However, since everything is a value, all checking is done dynamically.
* Generic operations
Because our "types" have lots of useful information in them, and can be manipulated just like any other value, its easy to write very generic operations, including equality, differencing, parsing, analysis, etc. We do extreme polytypic/generic programming, but don't worry about static checking. We'll worry about that later :-) Richer metadata (aka types or meta-models) means more powerful generic operations.
* Use code for transformations, but never generate code
We like code. Its great for projecting models onto models or computing analysis of models. We are developing a family of cyclic maps, which are like FP maps but they work on our circular structures. But you should never ever explicitly generate code. This is the big mistake of a lot of work on model-driven development. Instead, we use partial evaluation to generate code. Partial evaluation is great because it turns interpreters into compilers automatically (if you are careful!). Model to model transformations are fine and can be written in either code or as an interpretation of some other transformation language. But requiring all transformations to be models (not code), or generating code from models, is bad. I know others might disagree, but this is what we believe.
*Extreme feature-oriented modularity. That is, every idea should be written once. Allow mixins and inheritance/composition at all levels. These are very natural operations on models: to compose them and merge them. Its not easy, but we think we can make it work. You have to compose the syntax and the semantics cleanly. We are inspired by Don Batory's work here.
Our goal is to create "Smaltalk of Modeling". That is, a simple and elegant system that is based on models all the way down. It has a small well defined kernel and we are working on building real applications too, as we build the system. We are implementing in Ruby, although this is just because it is such a great language for this kind of reflective exploration. Our new system is not object-oriented, it is model-oriented. But we are looking for the key ideas in the modeling world, and not necessarily adopting any conventional wisdom. We are exploring!
Paul Graham on Objects in Arc
- "Object-oriented programming is exciting if you have a statically-typed language without lexical closures or macros." Smalltalk, Ruby, C#, Scala, and Python all have lexical closures, and their use of objects is quite exciting (lexical closures are being added to Java real soon now). All Smalltalk control structures are user-defined as well, although it doesn't have full macros. It is true that objects can be used as a stand-in for closures, so there is a little truth to this comment. On the other hand, object-oriented programming is quite popular in dynamically typed languages, so I'm not sure why Paul thinks OO is tied to static typing.
- "Object-oriented programming is popular in big companies, because it suits the way they write software." This is ridiculous. Smalltalk, Ruby, PHP, Python, and Lua (to name a few) are all quite popular but are not tied to "big companies". Lots of people like C++ too, at big and small companies. I think that Paul is showing a surprising lack of awareness of reality here.
- "Object-oriented programming generates a lot of what looks like work." Object-oriented programs are often more verbose than other styles. Partly its all the types, which means that Smalltalk, Ruby, Python etc are more concise than Java. But partly it is because OO languages encourage (require?) programmers to create modules and put in extensibility hooks everywhere, and these take up space. These hooks are called classes and methods. Haskell programs are usually concise, but are often not very extensible or interoperable.
- "If a language is itself an object-oriented program, it can be extended by users." "Overloading"? This has nothing to do with objects! What are you thinking, Paul? Overloading is about selecting an appropriate method based on its static type.
- "Object-oriented abstractions map neatly onto the domains of certain specific kinds of programs, like simulations and CAD systems." Yes, OO abstractions map very neatly into certain kinds of programs, like GUIs, operating systems, services, plugin architectures, etc. They are not good for everything, certainly, but they are good for lots of domains.
Here is a quick dictionary to translate OO names into Lispish descriptions.
- "Dynamic dispatch" is just calling an function value.
- "Polymorphism" is two different function values that have the same interface.
- "Objects" are just functional representations of data.
- "Classes" are just functions that create collections of first-class functions.
It is interesting to note that OO programs make more use of higher-order first-class functions (because all objects are collections of first-class functions) than most functional programs. This is another reason that OO is hard to grok. But Paul shouldn't have a problem with that.
As a small example, which do you think is a better approach to files? Here is the conventional approach without objects:
This is very limiting, because it requires a global read function that can understand how to read from every kind of stream! If I want to create my own kind of stream, I'm out of luck.(define (scan stream)
(if (not (at-end? stream))
(print (read stream)))
(scan (open-input-file "testdata.txt"))
Now here is the OO version:
This is very nice, because anyone can implement a function that understands the 'at-end? and 'read messages. Its immediately extensible!(define (scan stream)
(if (not (stream 'at-end?))
(print (stream 'read)))
(scan (open-input-file "testdata.txt"))
Remember Paul, that the lambda-calculus was the first object-oriented language: all its data is represented behaviorally as objects. Are you sure you aren't using objects?