Kuro5hin.org: technology and culture, from the trenches
create account | help/FAQ | contact | links | search | IRC | site news
[ Everything | Diaries | Technology | Science | Culture | Politics | Media | News | Internet | Op-Ed | Fiction | Meta | MLP ]
We need your support: buy an ad | premium membership

[P]
Re-evaluating the "you can do OO in any language" myth

By glaurent in Technology
Mon Mar 26, 2001 at 01:31:45 AM EST
Tags: Software (all tags)
Software

A very common claim regarding OO programming is that it doesn't actually require an OO programming language. This article attemps to show the limitations of this claim.


This draws heavily from a post of mine on Advogato, following up this article.

Language evolution

Languages have always been evolving towards higher levels of abstraction, (assembly, C, C++, Java, C# - see this article). As a language is used, people start expressing similar patterns, or styles, which evolve in a fully fledged programming paradigm. Usually the need for a new language directly supporting this paradigm appears, because it will be more efficient on all counts : the language gains in expressivity, so the programmer has less to do to make himself understood and will write faster, with less mistakes. I'll try to illustrate how programming paradigms, and Object Oriented Programming in particular, are much more efficiently implemented at the language level.

Claiming that you can do just the same without direct language support is basically reversing the very process which brought these features into the language in the first place. You will always gain from implementing a paradigm in a language not natively supporting it, but it will not be as effective as directly using a language which does.

A side note: you can recognize that a new programming paradigm has appeared to two unmistakable signs :

  • It has extremist proponents (e.g. "goto being harmful", or that old joke "What's difference between a terrorist and an OO programmer ? - Try negociating with an OO programmer." which certainly has some real-life experience to it)
  • It has extremist detractors, who claim either that it's just bloat or that it's nothing new and they can do just the same with their old language.
Features through syntax

In general, implementing "large" features through syntax conventions can work, but it's mostly up to the programmer to enforce the required code structure, instead of the compiler. Some actually like it and say "so I just have to be careful, big deal", or "we've got added flexibility". However, in practice what seems like "a little bit more verbosity" quickly gets in the way of the readability of the code. This Advogato diary entry from Nathan Myers puts it better than I could.

Another side note: Emotion usually prevails on factual reasoning when appreciating a programming language. If you like a language, you will happily suffer through its quirks and shrug at them, and each of its features will look absolutely essential. If you don't like it, you will consider its features useless or outright bad, and even the tiniest oddity will look fatal.

Impleting features in a language stems from the same reasoning process which makes you write a function to wrap an often-recurring sequence of actions. Or more generally which makes people create new words for new concepts as soon as that concept is used often enough. We don't say "portable tape player with headphones", we say "walkman", it's more efficient and easier to understand. Likewise, it's more efficient to type

class Foo : public Bar { ... };

or

class Foo extends Bar { ... };

than

typedef struct Foo { Bar _bar; ... }

and then having to do all the OO housekeeping work (ctor/dtor calling, type checking) instead of letting the compiler do it for you.

On the specific case of C++, on will note that it doesn't really relieve the programmer of the burden of ctor/dtor calling. This is true. However, it still does a better job than any non-OO language, which doesn't do it at all :-). Another problem is memory management. C++ does not provide a global solution for it, and let the programmer implements solutions on a case-by-case basis. See std::string, or Qt's object model (parent destroys children) for good examples of this. However, this is clearly a shortcoming of C++ compared to GC'ed languages like Java, at least for applications where memory management can be left to the language (which is more and more often the case).

See this interview for a similar reflection on features through syntax, taking object properties as an example :

"But going back to these key component concepts, there's been a lot of debate in the industry about whether languages should support properties or events. Sure, we can express these concepts by methods. We can have naming patterns like a "get" block or a "set" block that emulate the behavior of a property. We can have interfaces and adapters that implement an interface and forward to an object. It's all possible to do, just as it's possible to do object-oriented programming in C. It's just harder, and there's more housekeeping, and you end up having to do all this work in order to truly express your ideas. We just think the time is right for a language that makes it easier to create components."

An example of features through syntax : C++ and Qt

We have a perfect illustration of Mr. Hejlsberg's point with C++ and Qt :-). Qt implements properties on objects. This is a very nice and incredibly useful feature. But with C++/Qt, this requires :

  1. mandatory single inheritance of QObject
  2. if multiple inheritance (from one QObject class and one or several non-QObject ones), the QObject parent has to be listed first
  3. the use of the Q_PROPERTY macro in the class def
  4. the use of the moc preprocessor

The reliance on moc and the various "extensions" to C++ syntax which all Qt programmers are familiar with are usually pointed out when criticising Qt. When I was part of the Gtk-- development team, I certainly pointed that argument out as well. In practice it turns out that it's not that bad. The extensions are fairly unobtrusive, and KDE provides a development framework in which all the Makefile-related problems which moc brings are solved. But given the steady trickle of messages reporting moc-related problems on the qt and kde mailing-lists, no one would argue that this feature has a strictly positive impact on the developper.

Yet another side note : Experience shows that Qt's C++ extensions have at least two redeeming features :

  1. the extensions make up for very readable code, and are very easy to use. A template-based equivalent is usually more complicated.
  2. Slots and signals are manipulated through plain char* (connection is made with

    QObject::connect(const QObject * sender, const char * signal, const QObject * receiver, const char * member).

    This is great for dynamic GUI generation. Processing code like :

    <Connect source="abutton" signal="clicked()" target="awidget" slot="dosomething()" />

    is totally trivial.

Scalability

The other problem with the feature-through-syntax approach, aside of the added strain on the programmer, is that however well done the framework is, it's heavier than the equivalent feature built in a language. This means both mem/cpu and plain code typing overheads. And a programmer is very unlikely to use a feature if it's not easy to get working.

Because of this, a programmer is much less likely to create classes in a non-OO language with an OO framework added than in an OO language. Typically, he will end up having a relatively few number of very large classes.

Also, such a framework tends not to be very scalable both up and downwards. To implement things like OO Design Patterns is quite hard. To implement very small classes like a string or vector class (which are huge assets in a programmer's toolbox) is not worth it, because of the framework's overhead.

Taking a step down the abstraction ladder : a theoretical example

To further illustrate my point (especially to C buffs :-), suppose a language called C-- which has only if, goto, gosub and return keywords, no loops, no functions, and only global variables. Then someone says he has implemented loops and functions through a framework of macros and syntactic conventions on which the compiler can't perform any checks. It's just up to you to be careful, and to do all the typing, something like

/* This is a function */
MY_FUNC:
/* get arguments */
int my_func_local_1 = int_stack_1;
int my_func_local_2 = int_stack_2;

/* return results */
int my_func_res = my_func_local + my_func_local_2;
return;

/* ... a function call : */

PUSH_ARGS(12, 13);
CALL_FUNC(MY_FUNC);
/* do something with my_func_res */

Now would you consider using it rather than C ?

I believe that even if C was less portable than this imaginary C--, and would produce bigger executables, most of us would still take C any time :-).

Sponsors

Voxel dot net
o Managed Hosting
o VoxCAST Content Delivery
o Raw Infrastructure

Login

Related Links
o Also by glaurent


Display: Sort:
Re-evaluating the "you can do OO in any language" myth | 64 comments (50 topical, 14 editorial, 0 hidden)
You really need to attack this one again. (3.40 / 5) (#1)
by Speare on Thu Mar 22, 2001 at 06:02:40 PM EST

Interesting topic, but you only show the C vs C++ case. Your thesis is, "A very common claim regarding OO programming is that it doesn't actually require an OO programming language," but you don't prove that.

Sure, a compiler that supports OO in its syntax will be easier and perhaps clearer, but that's not saying that a compiler that has no OO support makes it impossible. Two very different statements.

Start again. Consider other no- or weak-OO-support languages like Perl or Python, and see if you still agree that OO is impossible.


[ e d @ h a l l e y . c c ]
Not trying to show it's impossible (4.00 / 1) (#22)
by glaurent on Fri Mar 23, 2001 at 04:39:45 AM EST

I'm not trying to demonstrate it's impossible, just that it's not "as good as" using OO with a language which supports it natively. The claim I'm trying to disprove is "OO in C is just as good as OO in C++/Java/Python". Yes, you can do OO in any language, no, it won't be as efficient.

[ Parent ]
This is the cardinal problem with your essay (4.00 / 2) (#33)
by Anonymous 242 on Fri Mar 23, 2001 at 10:05:58 AM EST

I'm not trying to demonstrate it's impossible, just that it's not "as good as" using OO with a language which supports it natively. The claim I'm trying to disprove is "OO in C is just as good as OO in C++/Java/Python". Yes, you can do OO in any language, no, it won't be as efficient.
The problem I have with your essay is that it is too general. You take a few specific cases where your point is (arguably) on good footing and extrapolate those cases to be the generality.

I will be the first to admit that in many cases you are correct. In many situations a language that facilitates OO design and implementation will be more efficient in some aspects. That said, there are also times when OO design and implementation will be more efficient in languages that do not faciliate OO in some aspects.

Take routines written in assembler. For a certain universe of problems assembler continues to be the single most effecient solution. It is quite possilbe that in many of these cases, the OO design philosophy and implementation is also the most efficient manner of programming in assembler. In these cases, not only can one use a non-OO language to implement an OO design, but one should use a non-OO language to implement an OO design.

The other thing I think you miss in your essay is the distinctions between programmer efficiency, computational efficiency, software efficiency, efficacy and effectiveness. In many (if not most) situations the best decision is to trade computational and software efficiency for programmer efficiency. In most cases faster hardware is cheaper than faster programmers. In some cases, faster hardware is not available. In these cases it bears paying attention to the fact that (arguably) implementations in languages designed to facillitate OO are virtually always slower than languages that do not. (Eiffel, when used in a very large program, may be an exception.)

Criticisms aside, I do think that your essay has much merit. Personally, I would like to see it modified so that the scope is reduced. I think that if you restrict your generalities to specific classes of problems that (1) your arguments will carry much more weight and (2) your ideas will receive much more acceptance.

As a side note, it is perhaps an interesting statement that most (not all) OO languages start(ed) life as a C preprocessor.

[ Parent ]

I agree... (none / 0) (#34)
by glaurent on Fri Mar 23, 2001 at 11:34:04 AM EST

You're right, I should have at least noted the exceptional cases you cited, or specified that I had (relatively) large application development in mind.

[ Parent ]
C vs. C++ speed (3.00 / 1) (#36)
by Per Abrahamsen on Fri Mar 23, 2001 at 12:23:28 PM EST

I'd expect the C++ implementation of an OO design to be at least as fast (execution speed) as the C implementation.

While sometimes front-end optimizations are implemented in C before C++ (because C is smaller and more used in benchmarks), I'd expect the compiler to do a better job optimizing the explicit OO features in C++ than the simulated OO in C.


[ Parent ]
But there is also much more overhead in C++ (1.00 / 1) (#38)
by Anonymous 242 on Fri Mar 23, 2001 at 12:36:57 PM EST

For example, structs in C have little overhead compared to structs in C++, which are really classes. While a C++ compiler might very well have optimization techniques specifically tailored to OO constructs, a simpler language like C typically (not always) will compile down to a faster executable because it has less overhead.

Perhaps as compilers improve in their ability to optimize, this will change.

[ Parent ]

A C struct and a C++ struct are identical (4.00 / 2) (#39)
by Per Abrahamsen on Fri Mar 23, 2001 at 12:43:27 PM EST

completely. This is why you can link C and C++ code together, if structs were different that would be impossible.

There only come a difference when you start using the OO features, in that case the struct gets a single extra pointer to a function table. This happens to be the same way one typically would implement OOP in C, the difference is that the C++ compiler does it for you.

Basically, features you don't use don't cost anything in C++. And if you use the feature, there is a good chance the compiler can implement it more efficient that you can emulate it yourself in C.


[ Parent ]
Absolutely not (4.00 / 2) (#41)
by glaurent on Fri Mar 23, 2001 at 01:11:50 PM EST

A C struct is a C++ class and has the exact same size. You can even derive it and add methods to it, it will still have the same size, as long as the methods you add are not virtual. Calling a non-virtual method is strictly equivalent to calling a function.

[ Parent ]
No overhead unless requested. (none / 0) (#56)
by ucblockhead on Mon Mar 26, 2001 at 05:02:00 PM EST

Unless the compiler is broken, a C++ program should compile down to exactly the same thing as the equivalent C program. C++ was specifically designed only to add overhead when OO features were used.


-----------------------
This is k5. We're all tools - duxup
[ Parent ]

OO language as C preprocessor (4.00 / 1) (#40)
by Per Abrahamsen on Fri Mar 23, 2001 at 12:45:26 PM EST

As a side note, it is perhaps an interesting statement that most (not all) OO languages start(ed) life as a C preprocessor.
I think you mean "compiled to C". This is not specific for OO languages, most new compiled languages generate C in their first implementation. C is basically considered portable assembler by modern language designers.

The older languages, Simula-67 and Smalltalk compiled natively, to a VM, or was interpreted. In the case of Simula-67 for the obvious reason that C did not exist yet!



[ Parent ]
True (none / 0) (#42)
by Anonymous 242 on Fri Mar 23, 2001 at 01:14:44 PM EST

I did qualify my statement with "most (not all)."
The older languages, Simula-67 and Smalltalk compiled natively, to a VM, or was interpreted. In the case of Simula-67 for the obvious reason that C did not exist yet!
I am fairly ignorant of Simula-67, but I know that more than one modern version of Smalltalk compiles to C. This is not entirely for the purpose of using C as portable assembler. One product (IIRC, Smalltalk MT) claimed its reasons for doing so were for performance. Given the blazing speed of most Smalltalk virtual machines, I can well believe it. (Remember the once popular slogan that ridiculed Java: Java: the syntactical clarity of C++, the blazing speed of Smalltalk</e>?)

[ Parent ]
OO in Scheme (2.50 / 2) (#4)
by rebelcool on Thu Mar 22, 2001 at 07:29:45 PM EST

is just plain nasty and ugly to try to implement.

COG. Build your own community. Free, easy, powerful. Demo site

Re: OO in Scheme (3.00 / 1) (#12)
by Mr. Piccolo on Fri Mar 23, 2001 at 12:02:37 AM EST

Certainly it can't be worse than OO in Prolog??!!

The BBC would like to apologise for the following comment.


[ Parent ]
huh? (4.00 / 1) (#15)
by jacob on Fri Mar 23, 2001 at 02:29:40 AM EST

Quick 'n' dirty (using <a target=_top target=_top HREF="http://www.plt-scheme.org" >PLT Scheme without PLT's built-in OO facilities):

(define (make-object)
(let
((property1 val)
(property2 val))
(lambda (func . args)
(case func
[(func1) ...]
[(func2) ...]
;; etc
))))

(No inheritence in this version, alas)

A better version, using PLT objects:

(define MyClass%
(class* object% ()
()

(public
[func1 (lambda () ...)]
[func2 (lambda () ...)])

(private
[property1 val]
[property2 val])

(sequence
(super-init))))

PLT objects in particular are just as easy to use as Java's, and much more so in some circumstances, owing to Scheme's permissive nature.

And if you're NOT using PLT scheme, you can extend Scheme to handle object in this fashion just by figuring out how to implement each feature and using functions or macros. It might not be easy, but you'd only have to do it once in a library and then JoeSchmoe Scheme would look as object-oriented as Java.

Scheme is a particularly bad language for proving the author's point, because a) the language can be extended with new features very easily and b) macros and plain-ol' functions are likely how the features that do exist actually ARE implemented (rather than being imbued with magical powers because of their 'built-in'-ness). PLT Scheme only has a few true primitives (where 'a few' is in the low teens, IIRC), and every other syntactic form you see is implemented as a macro.



--
"it's not rocket science" right right insofar as rocket science is boring

--Iced_Up

[ Parent ]
OO in Scheme is simple and elegant (4.00 / 2) (#23)
by Per Abrahamsen on Fri Mar 23, 2001 at 05:55:34 AM EST

Basically, closures is a more powerful abstraction than objects, and it is easy to implement an object abstraction on top of closures. It has been done to death.


[ Parent ]
What is Closure (in Scheme)? (none / 0) (#43)
by tnt on Fri Mar 23, 2001 at 01:17:25 PM EST

I've used functional languages before (ML and haskell), but I was wondering, what is closure? (I know what closure is in a mathematical sense, but I am guessing that that is not what you are refering to.)



--
     Charles Iliya Krempeaux, B.Sc.
__________________________________________________
  Kuro5hin user #279

[ Parent ]
closures (none / 0) (#44)
by hading on Fri Mar 23, 2001 at 01:46:40 PM EST

(I'm not an expert, so take this with that in mind.)

I think that "closure" refers to a specific implementation technique for doing the following sort of thing (please forgive my ML - I'm not an expert in that either).

fun adder x = (fn y => x + y);

The function returned by calling this is a closure over x - it sees the value of x when it is called, and that is maintained after x is no longer in scope, if x is rebound, etc. So one can create functions in a certain lexical context and they will continue to remember that lexical context even after it has been exited (because they have "closed" over it). I think that the word "closure" has become more generally associated with doing this sort of thing than the exact way of doing it, which may be where the word itself comes from. Perhaps someone else can give a more accurate explanation, but I think that's the basic idea.



[ Parent ]
OO in Lisp (none / 0) (#55)
by Xenophon Fenderson, the Carbon(d)ated on Mon Mar 26, 2001 at 03:49:46 PM EST

The problem is that one must implement an object system from scratch in Scheme---not impossible, but daunting all the same. This is probably the core of the whole CL-vs.-Scheme debate, with the Schemers calling Lisp "bloated", and the Lispers calling Scheme "useless". Personally, Scheme is a tad to spare for my taste, and the lack of certain standardized subsystems (such as usable macros and a decent object system) is a big mark against it, but other people seem to like it and get useful work done in it, incompatibilities aside.



--
Rev. Dr. Xenophon Fenderson, the Carbon(d)ated, KSC, mhm21x16, and the Patron Saint of All Things Plastic fnord
I'm proud of my Northern Tibetian heritage!
[ Parent ]
objects are a provided extension in many schemes (none / 0) (#58)
by hading on Mon Mar 26, 2001 at 06:23:24 PM EST

Many Schemes (e.g. mzscheme, MIT scheme) have an (implementation dependent) object system, so a programmer wouldn't typically have to roll his own just to use Scheme. Of course, since these are extensions and not part of the standard, they can be wildly different between implementations.

I rather agree with you that CL is to be preferred, and it's what I use, but let's not be too unfair to the Schemers.



[ Parent ]
Confusing "can" with "should". (4.50 / 4) (#5)
by ucblockhead on Thu Mar 22, 2001 at 07:33:28 PM EST

Of course you "can" do OO in any language, assuming the language is Turing complete. You "could" even do it in brainfuck if you were obsessive enough.

The author appears to be talking about whether or not you should try OO in a language with little or no OO support. But that's not the same as saying that you can't.

Hell, I've done it, done OO work in C. This was at a time and in a place where OO wasn't available, and I found writing in an OO fashion using C to be very useful. Not as useful as if I'd had a real OO language, but that was not then an option.


-----------------------
This is k5. We're all tools - duxup

Definations please. (3.50 / 2) (#6)
by tiamat on Thu Mar 22, 2001 at 08:17:47 PM EST

"you can do OO in any language"

What exactly does do mean? Is it just a question of defining something as an object, or are we talking about built in compiler support? There's a wide spectrum of options for a defination here. I for one don't know what would be best.

Blah. (3.40 / 5) (#9)
by gblues on Thu Mar 22, 2001 at 10:08:17 PM EST

A very common claim regarding OO programming is that it doesn't actually require an OO programming language.
That's right, it doesn't. OO is an abstraction, and wether or not a language meshes with that abstraction is largely irrelevant. If it's a compiled language, OO is largely meaningless.

Processors are not object-oriented. They aren't even procedural. They are sequential. Load a command, load the operand, run the command, increment the program counter, repeat.

Therefore the ability to implement OOP in a language not explicitly designed to help the programmer with OOP concepts is limited only by the amount of freedom the language gives the programmer.

Inherentance, polymorphism, etc. are concepts the computer does not understand. Their implementation in so-called OOP languages (a misnomer, OOP-centric might be more accurate) is a convenience for the programmer and are not enabling some mystical functionality of your PC that programmers 20 years ago didn't know about.

Nathan
... although in retrospect, having sex to the news was probably doomed to fail from the get-go. --squinky

You're totally missing my point... (3.00 / 2) (#17)
by glaurent on Fri Mar 23, 2001 at 02:39:16 AM EST

subject says it all. :-)

[ Parent ]
This article is about PRACTICAL, not POSSIBLE (4.42 / 7) (#13)
by MoxFulder on Fri Mar 23, 2001 at 02:16:53 AM EST

A number of comments have basically blown off this whole post by saying, "Well, as long as it's possible to do something in C, it doesn't really matter that it's a lot easier in C++." This is starting to get on my nerves, so let's set the record straight ... there is absolutely NO feature of any Object Oriented programming language which cannot in some way or another be imitated in a non-object oriented language!

Any Turing-complete programming language can do anything that any other Turing-complete language can do ... I'm pretty sure that it's a proven mathematical theorem!

I will attempt to demonstrate the difficulties of adapting a technique used in one programming paradigm to a language that isn't based on that paradigm. Here's an example:

Recently, a friend of mine claimed that, because C doesn't have an eval operator that allows C code to be evaluated at runtime, it is impossible to create a function that will return another newly created function, as the following Perl code does (sorry, I know that this looks even cleaner in Python, but I don't know Python very well):

sub make_addition_function {
   my ($howmany) = @_;

   return eval("sub { shift() + $howmany; }");
}

*add3 = &make_addition_function(3); # The &add3 function adds 3 to a number
*add5 = &make_addition_function(5); # The &add5 function adds 5 to a number

print &add3(6), " ", &add5(6), "\n";
In fact, it would be possible to do this in C, but it would be extremely cumbersome and it would require a custom function dispatcher which would be kludged into the language (much like OO methods in GTK+!) and would be ugly and incompatible with the standard C function calling syntax. glaurent calls this "features through syntax", but I would call it "features making a mockery of syntax". In any case, the difficulty of creating new functions at runtime would strongly dissuade any C programmer from implementing it.

Because this would be very difficult in C, a C programmer would adopt a different strategy: he or she would just use the built-in addition operator in this trivial example. However, one can easily imagine cases in which a programmer would tear his or her hair out trying to replicate the functionality of Perl in C. Try adding dynamically loaded library support to an older C compiler that doesn't support it ... I tried a few years ago and practically went nuts ;-)

So using a programming language like C is a strong deterrent to writing programs that augment their own code at runtime. Perl and Python make it easier, and functional programming languages like Lisp go even further.

To sum it up, I strongly agree with the author of the article: the choice of a programming language strongly constrains one's choice of a programming paradigm.

(By the way, I don't like using object oriented programming myself, since I am one of those programmers who prefers working on little nitty gritty low level problems rather than more abstract, big picture problems.)

"If good things lasted forever, would we realize how special they are?"
--Calvin and Hobbes


eval in c (2.00 / 3) (#21)
by delmoi on Fri Mar 23, 2001 at 03:58:10 AM EST

It wouldn't be that hard, as long as the function took a standard set of parameters. Just write the function to a c file and compile with gcc it as a dynamic library (.dll, or .so)

You'd need to have a copy of gcc on the target system though, probably not to portable.
--
"'argumentation' is not a word, idiot." -- thelizman
[ Parent ]
Turing complete (4.00 / 1) (#31)
by Per Abrahamsen on Fri Mar 23, 2001 at 09:58:42 AM EST

Any Turing-complete programming language can do anything that any other Turing-complete language can do ... I'm pretty sure that it's a proven mathematical theorem!
It is pretty much the definition of "turing complete", making a proof rather redundant.

[ Parent ]
Church-Turing (none / 0) (#49)
by plastik55 on Sat Mar 24, 2001 at 01:02:07 AM EST

Any Turing-complete programming language can do anything that any other Turing-complete language can do ... I'm pretty sure that it's a proven mathematical theorem!
It is pretty much the definition of "turing complete", making a proof rather redundant.
Actually it's only true if the Church-Turing thesis is true, which is unproven. If languages A and B are Turing-Complete, but language B has extra features which cannot se simulated by a Turing machine, and language A does not, then A cannot do the same things as B.

This can only happen if the Church-Turing thesis (that there is no computation than cannot be done by a Turing machine) is false.
w00t!
[ Parent ]

Strictly speaking (none / 0) (#62)
by Simon Kinahan on Wed Mar 28, 2001 at 10:46:48 AM EST

The Church-Turing thesis is that there is no computable problem whose answer cannot be computed on a Turing machine. There are problems, such as the reverse halting problem (testing a Turing machine program to ensure that it will *not* halt), that are incomputable.

Simon

If you disagree, post, don't moderate
[ Parent ]
Choice of paradigm (none / 0) (#32)
by Per Abrahamsen on Fri Mar 23, 2001 at 10:05:17 AM EST

To sum it up, I strongly agree with the author of the article: the choice of a programming language strongly constrains one's choice of a programming paradigm.
In practice, I think the problem and design in most cases are still more important for the choice of programming paradigm than the language. I'd certainly suggest using OOP for C GUI toolkits, as the problem so neatly lean itself toward that paradigm. I'd also suggest using another language, but keep the recommendation of an OO design and implementation even if another language was not a choice.

[ Parent ]
Specious argument. (none / 0) (#45)
by trhurler on Fri Mar 23, 2001 at 04:03:17 PM EST

Even if you gave me a library to do what you describe, I wouldn't use it. It is a stupid idea.

Why is it a stupid idea? Well, if the function "generated" doesn't come from the program, then it comes from an input. At that point, your program is trusting that input and running code embodied in it. This has implications for system security, program integrity, verifiability, and a lot of other things, and the real reason guys like you do it isn't because it is necessary or even the easiest way, but because you think it is "cool." "Cool" is not a sufficient reason to do something stupid in a program.

But, at any rate, it isn't cool. It is foolish. Furthermore, it is an invitation to be screwed over.

By the way, I can implement a crude version of it in C for a modern Unix in less than half a day. It isn't as hard as you say. Modern C implementations include dynamic linkage. From there, all you need is the ability to take input and pass it to the C compiler. That's pretty trivial. I suppose you could claim that dynamic linkage isn't a standard part of C, and similarly, I could point out that there IS no perl standard and then proceed to insist that Perl is whatever was present in version 2 from 1985 or whenever it was. Rather boneheaded, but no more boneheaded than you trying to define C to be some old compiler for a 360 mainframe from 1975 or something like that.

--
'God dammit, your posts make me hard.' --LilDebbie

[ Parent ]
Stupid? (none / 0) (#46)
by inpHilltr8r on Fri Mar 23, 2001 at 06:03:40 PM EST

Well, it seems to me that the man's described an IDE. I mean, it takes an input (your source), makes a function out of it (compiles it), and calls that function (runs it).

Doesn't even have to be a monolithic IDE, similar principle applies to any development system.

Eminently sensible idea if you ask me, and one that all software development relies on.

[ Parent ]
Not quite (none / 0) (#47)
by trhurler on Fri Mar 23, 2001 at 06:13:41 PM EST

First of all, not all development goes on in an IDE. I never use one given a choice.

Second, what you're probably thinking of is a "compiler," and it produces a runnable program in a file for you, rather than loading some code into its own address space and then running it, so even that doesn't do what we are talking about.

Third, such tools are generally written in C, so this guy's argument would be wrong if you were right. Actually, I think his argument is wrong anyway, as I've already said, but that's another matter.

--
'God dammit, your posts make me hard.' --LilDebbie

[ Parent ]
Quite (none / 0) (#52)
by inpHilltr8r on Sat Mar 24, 2001 at 08:04:57 PM EST

1: I never said all development did. Your own personal preferences are of no relevance.

2: The address space the code is loaded into isn't relevant. It is loaded, and called, that's enough.

3: That's the point. It's a c program that takes c as an argument, generates code from it, and calls it.

Personally I don't think he had an argument, more of a point...


[ Parent ]
function "generated" (none / 0) (#59)
by kubalaa on Tue Mar 27, 2001 at 02:00:06 AM EST

Why is it a stupid idea? Well, if the function "generated" doesn't come from the program, then it comes from an input...This has implications for system security...

If your program ignores the input---that is, if the input does not directly affect the output---it's worthless. It doesn't ultimately matter whether this is the result of using input to generate a function or doing something less direot. Perhaps this makes it easier to write an unsafe program, but it also makes it easier to solve certain problems. And there's always tainting.

[ Parent ]

What is the point? (3.00 / 3) (#24)
by Per Abrahamsen on Fri Mar 23, 2001 at 06:11:57 AM EST

If I get it right, the article can be summarized as follows:

It is easier to implement an object oriented design in a language that supports object oriented programming, than in a language that merely allows object oriented programming.
It this "insight" supposed to be surprising or even controversial?

The controversial part are title, which implies that you _can't_ implement an OO design with a language that doesn't support OO programming, a claim that is clearly false (that's Church's thesis).

Another controversial claim is incidental, that Java is a higher level language than C++, and C# is higher level than Java. I'd consider Java and C# essentially the same, with C++ and Java going in different direction (generic programming vs. reflection).

The last controversial point would be what "features" are part of OOP support. I would for example claim GC is an orthogonal point to OO, GC is much older than OO for one thing. Admitted, OOP tends to create more objects than structural programming, but the difference isn't that big.



Nitpick (3.50 / 2) (#25)
by zakalwe on Fri Mar 23, 2001 at 06:45:23 AM EST

The controversial part are title, which implies that you _can't_ implement an OO design with a language that doesn't support OO programming, a claim that is clearly false (that's Church's thesis).
I agree with your point, but Church's thesis has absolutely nothing to do with it. Church's thesis is about the things that can be computed - ie. there is nothing that can be accomplished in C++ that can't be accomplished in C. It says nothing about the method used. Depending on what exactly you mean by OO programming, it may indeed be possible to design a language where such a method is impossible (or at least counterproductive.) unlambda comes to mind, and it'd be pretty impossible in a language with no kind of structures.



[ Parent ]

I was careful with the words... (4.00 / 1) (#28)
by Per Abrahamsen on Fri Mar 23, 2001 at 08:56:41 AM EST

I said you could implement an OO design, not that you could do OO programming.

In any case, you can do OOP in the original FORTRAN and BASIC languages. Basically, create a huge array called "memory" to store all your objects to get dynamic memory and pointers. You can them simulate structures with accessor-functions(, and simulate functions with GOSUB in BASIC). To get late binding you need function pointers which can be simulated with assigned goto in FORTRAN, and long lists of IF-THEN statements in BASIC.

It sounds ugly, but it can easely be the cleanest way to implement something in the two languages. And with a lot of discipline, it can even be maintainable.

In the worst case, you can write an interpreter in the unsiutable language. I must admit that Church's thesis didn't directly claim that was always possible, though. Indirectly it does, assuming you can write an interpreter in at least one language.


[ Parent ]
"insight" (3.50 / 2) (#26)
by glaurent on Fri Mar 23, 2001 at 07:48:54 AM EST

No, it's certainly not surprising nor even controversial, to me at least. But I still quite often see people saying that OO is just syntactic sugar. So I felt like I could at least attempt to show how absurd this is.

About C# and Java, I agree, they are basically on the same level. The example was just a demonstration about a more general point of features through syntax.

Finally, I certainly didn't mean that GC is part of OO.

[ Parent ]

Syntactic sugar (4.00 / 1) (#29)
by Per Abrahamsen on Fri Mar 23, 2001 at 09:01:00 AM EST

> people saying that OO is just syntactic sugar

Well, they are right. Late binding in OOP is just syntactic sugar for function pointers, just like loops in structured programming is just syntactic sugar for conditional gotos.


[ Parent ]
Syntactic sugar (4.33 / 3) (#30)
by glaurent on Fri Mar 23, 2001 at 09:39:15 AM EST

What I'm trying to show is that this syntactic sugar (whatever the level you consider it, OOP or structured prog.) is actually the basis of all programming languages over '0' and '1', and that it is actually essential. And programming discipline is not a good substitute for it, because it puts on the programmer the burden which the compiler would take care of.

[ Parent ]
It is controversial... (none / 0) (#63)
by Brandybuck on Wed Mar 28, 2001 at 07:55:41 PM EST

It is controversial, in some quarters. Just mention c++ to a gnomie and they will launch into a half hour tirade on why it's easier to do OO in GTK than in Qt. Go figure...

[ Parent ]
Its `goto considered harmful`... (3.50 / 2) (#27)
by pallex on Fri Mar 23, 2001 at 08:28:11 AM EST

... and its not exactly an extremist viewpoint.


Better as part of the Language (5.00 / 1) (#35)
by tnt on Fri Mar 23, 2001 at 12:22:14 PM EST

I agree with you, alot of things are better as part of the language. Because (1) so you can get good error messages, (2) so the compiler can make optimizations to make things more effiicient, (3) so it is easier to write/code, and (4) so things look nicer! [Some might think (4) is the least important,... but to me, it is probably the most important reason.]

I wrote a `unit checker' in C++ using expression templates, for a project I am working on -- matterial -- and it works great,... but get an error, and good god you'll see cryptic template error messages that you wouldn't believe. (I understand them, but I pitty anyone else... especially anyone trying to learn it). [If you're interested in seeing the code I can provide links to the source and some articles explaining it,... it is GPL-ed.] Just in case it isn't clear what a `unit checker' is, this system I wrote lets you attribute stuff like miles per second, volts, kg · m/s, color, etc to variables, and automagically handles conversions and checks all calculations to make sure that the `units' are OK. (Like what you did by hand in Physics, Chemistry, and other Science and Engineering classes.)

In my opinion, being able to extend the very language you are using is necessary. (Language design/research is the topic I think I'll take when I go back for my Masters, in Comp Sci.)



--
     Charles Iliya Krempeaux, B.Sc.
__________________________________________________
  Kuro5hin user #279

OO languages as a C preprocessor (4.00 / 2) (#37)
by Per Abrahamsen on Fri Mar 23, 2001 at 12:29:32 PM EST

As a side note, it is perhaps an interesting statement that most (not all) OO languages start(ed) life as a C preprocessor.
I think you mean "compiled to C". This is not specific for OO languages, most new compiled languages generate C in their first implementation. C is basically considered portable assembler by modern language designers.

The older languages, Simula-67 and Smalltalk compiled natively, to a VM, or was interpreted. In the case of Simula-67 for the obvious reason that C did not exist yet!



Updated version (5.00 / 2) (#53)
by glaurent on Mon Mar 26, 2001 at 02:57:55 AM EST

Following up the comment I've got here, I've put an updated version of this article here. Thanks for all the valuable feedback.

Dynamic OO and C++, C# and Java. (3.00 / 1) (#54)
by qazwsx on Mon Mar 26, 2001 at 07:27:38 AM EST

Let's say you need to implement a whole new Object Structure in a running process. C++, C# and Java can't help you the same way that the compiler can do for you during the compilation.

Example: try to create a new widget using a user defined structure - particular inheritance, let's say - and make use of it using the normal ways of method calling.

So, I'd have to say that for some OO problems it would be better to use languages like Python, Smalltalk, etc. to help the development. If you had to do that with C++, you'd need to use a powerful dynamic object framework like the GTK one. :-)

OO in BASIC? (2.00 / 1) (#57)
by cr0sh on Mon Mar 26, 2001 at 05:34:45 PM EST

Some of the comments point out that if a language is Turing complete, you should be able to implement the functionality of that language in another TC language - Thus, you can do a sort of pseudo OO in C, as compared to C++ (from what I understand).

Is BASIC (and when I mean BASIC, I don't mean VB - I mean old skool Dartmouth with line numbers and such) TC? If is is, can anyone give me an example of OO programming using it.

To put it another way, let's say you are given a C=64 and are told you need to write a random number picker in BASIC, but in an object oriented fashion - can it be done? Can anyone post examples?

I have seen examples that rely on certain things available to such BASICs as QBasic 1.1 or QB4.5, but nothing using older BASICs - I am just curious about this...

Re: OO in Basic (none / 0) (#60)
by WWWWolf on Tue Mar 27, 2001 at 07:29:38 AM EST

To put it another way, let's say you are given a C=64 and are told you need to write a random number picker in BASIC, but in an object oriented fashion - can it be done? Can anyone post examples?

<evil-hacker>Fool! You asked for this, and now you got it! Muhahahahahahhahahaha....</evil-hacker>

Well, in Commodore 64, you'd probably end up doing that in Assembler - this is just due to fact that SID (sound chip) can't be controlled with BASIC. (You see, the coolest way to get random numbers is to set SID chip to output noise, and read the noise output register value. AFAIK, this produces more or less true random numbers. Eat that, PC folks =)

But to the topic: It might be possible to make OO-style RNG with C64 BASIC - though OO in BASIC is seriously overkill (and no, VB hasn't changed that a single bit =)

Basically, I would use one array to hold references to "objects", multi-dimensional arrays to store object fields, and subroutines (callable with GOSUB) to implement methods.

Basically, I would do this (exact syntax might be different, as I haven't touched C64 BASIC for some months, the book is on the top self and I'm too lazy to get my ass up from this most uncomfortable and thrououghtly broken chair):

10 REM GENERATE NEW RNG OBJECT
20 GOSUB 500
30 REM (THE RNG REFERENCE IS IN VARIABLE R(0))
40 REM CALL RNG, SET RNG TO BE CALLED
50 C = R(0)
60 GOSUB 550
70 REM READ RESULT
80 RS = CR
90 REM ... REST OF THE CODE FOLLOWS
100 REM RNG CODE STARTS FROM LINE 500, NOT HERE (I HAVE ONLY BAD MEMORIES
110 REM FROM THIS HORRIBLE EXCUSE OF BASIC INTERPRETER FROM MICROSOFT)

Variables used:

R(x)
Array of RNG objects
C
the RNG object to be called (since GOSUBs don't take arguments, everything needs to be passed via global variables - BASIC sucks, eh?)
CR
Function call return value (No, GOSUBs won't return anything either...)

I could implement automatic object reference handler... but I think I'm not insane enough to do that... or maybe it's just that I'm feeling lazy today, I'm definitely insane enough to do that, allright. =)

-- Weyfour WWWWolf, a lupine technomancer from the cold north...


[ Parent ]
Interesting... (none / 0) (#61)
by cr0sh on Tue Mar 27, 2001 at 01:53:29 PM EST

I may look into how this could be expanded - more as a mind exercise than anything else (I think you would run out of coding room on most older machines before you could implement any kind of real program - of course, maybe with a disk drive and the CHAIN command on some BASICs, it could be done).

Thanks for the example!

[ Parent ]

Why is it no uses OO Assembly? (none / 0) (#64)
by Brandybuck on Wed Mar 28, 2001 at 08:15:16 PM EST

Why is it no one uses Object Oriented Assembly?

After all, the common saying among GTK/GNOME developers is "since everything you can do in C++ can be done in C, it makes sense to do it in C instead". I want to explore this logic just a bit further. "Since, everything you can do in C you can do in assembler, it makes sens to do it in assembler. And since you can do OO in C, you can do OO in assembler, and it must the Right Thing to do!"

Of course the above argument is total crap. What I want to know why, is if you have a choice between doing OO in an OO language or doing OO in a procedural language, why in the hell would you choose the procedural language? Doing it in the OO language is going to be easier and more natural, period.

Re-evaluating the "you can do OO in any language" myth | 64 comments (50 topical, 14 editorial, 0 hidden)
Display: Sort:

kuro5hin.org

[XML]
All trademarks and copyrights on this page are owned by their respective companies. The Rest 2000 - Present Kuro5hin.org Inc.
See our legalese page for copyright policies. Please also read our Privacy Policy.
Kuro5hin.org is powered by Free Software, including Apache, Perl, and Linux, The Scoop Engine that runs this site is freely available, under the terms of the GPL.
Need some help? Email help@kuro5hin.org.
My heart's the long stairs.

Powered by Scoop create account | help/FAQ | mission | links | search | IRC | YOU choose the stories!