"A lot of us thought in the 1990s that the big battle would be between
procedural and object oriented programming, and we thought that object
oriented programming would provide a big boost in programmer
productivity. I thought that, too. Some people still think that. It
turns out we were wrong. Object oriented programming is handy dandy,
but it's not really the productivity booster that was promised. The
real significant productivity advance we've had in programming has
been from languages which manage memory for you automatically. It can
be with reference counting or garbage collection; it can be Java,
Lisp, Visual Basic (even 1.0), Smalltalk, or any of a number of
scripting languages. If your programming language allows you to grab a
chunk of memory without thinking about how it's going to be released
when you're done with it, you're using a managed-memory language, and
you are going to be much more efficient than someone using a language
in which you have to explicitly manage memory. Whenever you hear
someone bragging about how productive their language is, they're
probably getting most of that productivity from the automated memory
management, even if they misattribute it."
I think he normally writes good stuff, but if you read on from the
quoted part his point is vitiated by the fact that he does not know, or
at least acknowledge, that MFC, a C++ wrapper for the Windows API, has
been available for a decade or so, obviating the neccessity for stuff
like the following:
BEGIN QUOTE
"Often I've written the same code, once in C++ calling the Windows API
and once in Visual Basic, and C++ always took three or four times as
much work. Why? Memory management. The easiest way to see why is to look
at the documentation for any Windows API function that needs to return a
string. Look closely at how much discussion there is around the concept
of who allocates the memory for the string, and how you negotiate how
much memory will be needed. Typically, you have to call the function
twice=3Fon the first call, you tell it that you've allocated zero bytes,
and it fails with a "not enough memory allocated" message and
conveniently also tells you how much memory you need to allocate. That's
if you're lucky enough not to be calling a function which returns a list
of strings or a whole variable-length structure. In any case, simple
operations like opening a file, writing a string, and closing it using
the raw Windows API can take a page of code. In Visual Basic similar
operations can take three lines."
END QUOTE
The use of an OO language like C++ to create appropriate classes can in
fact obviate the majority of manual memory management, including pretty
much all of the messing about he talks about above. For some purposes
you will still be passing around pointers to blocks of allocated memory,
but for most tasks you shouldn't need this.
- Gerry Quinn
> ...Object oriented programming is handy dandy,
> but it's not really the productivity booster that was promised. The
> real significant productivity advance we've had in programming has
> been from languages which manage memory for you automatically...
Thinking hard about a good design slows us down?
Being a slob, and leaving dead objects strewn around memory, speeds us up?
When I code C++, the only thing I miss from Ruby is block closures. Because
I practice simple RAII, and always understand my object model's shape in
memory, I don't miss Ruby's garbage collection.
--
Phlip
http://industrialxp.org/community/bin/view/Main/TestFirstUserInterfaces
I've never seen anything so ridiculous as this claim.
Great programmers before automated memory management existed
instinctively used the electronic equivalent of "leave no trace"
wilderness camping. That is, just as in the wilderness you clean up
after yourself great programmers knew enough to accurately scope
variables and do what was necessary to get rid of resources attached
to those variables at the instant they passed out of their real
dynamic scope, which is to say when they are no longer needed.
In a language with automated garbage collection it becomes in fact
more and not less necessary to "get rid" of resources accurately and
in a timely fashion. This is because when the task is left to the
garbage collector, the garbage collector has no way of knowing when a
variable is in reality "dead".
Furthermore, the issue is recursive. If any object allocates private
objects that occupy space in the heap, and they allocate objects down
to an arbitrary level, the garbage collector can be miss tons of
blocks that are in reality garbage, but attached to something that is
still referenced...because its user is to lazy to explicitly dispose
it.
To compare automated memory management to OOD is to compare apples to
oranges, or apples to the stems of apples, for automated memory
management is logically a part of OOD.
The reification here fetishizes, in a spirit reminiscent of the cargo
cult, one part of the whole which is thought to be understood.
And I believe it is made because of a refusal to accept the radical
novelty of OOD.
Furthermore, this little gem defines the whole issue as one of
"programmer productivity", a concept which on examination turns out to
be deskilling and to ignore the need for correctness. It is a metaphor
which transforms employees who should be (but are not in most
instances) partners with management into field hands producing what
Massah wants on demand, without any ability to contribute to the truth
of what is produced...as if ANY specification is not found to have
bugs on implementation.
A much abbreviated version of the lucid, clear explanations of the modern
third-world pseudo-programmer which makes one wonder why outsourcing is
not more popular in the rapidly-growing Insane Asylum Management Software
industry.
--
Randy Howard (2reply remove FOOBAR)
"The most amazing achievement of the computer software industry is its
continuing cancellation of the steady and staggering gains made by the
computer hardware industry..." - Henry Petroski
Aw c'mon phlip.
You don't see how easy it is to program something when you don't have to
worry about deallocation?
Sure, you can bind up periodically. But having to worry a few times about
GC congestions is certainly a great trade for not having to worry about
every little allocation.
Think of all the potential bugs that can occur from a tirade of malloc's,
not from being a dope, but from being human.
I /don't/ worry about deallocation myself... I use a variety of smart
pointer classes to do the worrying for me. But if I find myself missing
the whole manual allocation/deletion process I at least have a choice :>
> Sure, you can bind up periodically. But having to worry a few times about
> GC congestions is certainly a great trade for not having to worry about
> every little allocation.
In C++ at least this needn't be a problem. We've come a long way since
malloc :>
> Think of all the potential bugs that can occur from a tirade of malloc's,
> not from being a dope, but from being human.
Think of all the potential bugs that can occur from circular referencing
and all that jazz under an automated garbage collector :)
--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur!"
Easy to come up with wrong answers, and/or memory hogs?
>
> Sure, you can bind up periodically. But having to worry a few times about
> GC congestions is certainly a great trade for not having to worry about
> every little allocation.
"God is in the details" - Mies van der Rohe
Entirely too many programmers want to program in a semiconscious mode.
>
> Think of all the potential bugs that can occur from a tirade of malloc's,
> not from being a dope, but from being human.
I agree, having said the above, that malloc is primitive.
And I agree that automatic memory management is a good thing.
However, it is part of OOD and OOD implies knowing when to get rid of
an object.
Relatively primitive languages, such as Visual Basic prior to .Net,
forced the implicit allocation, or at a minimum declaration, of the
object or value at the entry to the procedure.
Whereas more modern languages, including VB.Net and C sharp, do the
allocation at block entry (yes Virginia, there are blocks in VB.Net).
This means its possible to declare a name Just In Time and more
closely associate it with the code.
However, the ideal is not yet here. This would be to be able to
destroy the object so as to make it go out of static and dynamic scope
cleanly, while perhaps and behind the scenes cluttering the heap with
dead soldiers until the garbage collector comes by.
Of course, you can do this as regards dynamic scope but the object's
name remains valid in static scope and this basically sucks and blows.
<snipped>
>
> You don't see how easy it is to program something when you don't have to
> worry about deallocation?
>
> Sure, you can bind up periodically. But having to worry a few times about
> GC congestions is certainly a great trade for not having to worry about
> every little allocation.
>
> Think of all the potential bugs that can occur from a tirade of malloc's,
> not from being a dope, but from being human.
The problem, from my viewpoint, is not whether or not GC is a
good thing to have (it is, right?), but whether the programmer
who /needs/ it is a good one to hire.
The are more resources that a single program must manage
than just memory. Memory allocation/deallocation just happens
to be the easiest to manage.
Cleaning up after yourself (especially if writing a library)
cannot be stressed enough. Unfortunately, reliance on GC for
new programmers just means that they never get any experience
managing resources properly. No language should /force/ the
programmer to rely on GC as this just means that programmers
will get forgetful about resource management.
all memory allocated must be deallocated.
all files opened must be closed.
all network connections opened must be terminated.
all threads/tasks started must be ended.
all temporary files must be deleted.
It goes even further when you are managing physical
resources, as then you would have to manage creating
and deleting queues (think printer spools), or
even as far as multiplexing a single ADC channel
between n inputs (think about the latency inherent
in switching a piece of wire between various
sources, and taking the capacitance into account).
Not managing memory is the slippery slope of the thin
end of the wedge. The programmer who does not learn
to manage memory efficiently is not much use other
than as a code grunt. When all we have left are languages
that dont let the new programmer learn some very important
concepts (which hopefully wont be soon), then we must
not complain when we get second-rate programmers.
goose,
/flamebait
Not really. Destructors can be badly written. :)
> > Think of all the potential bugs that can occur from a tirade of
malloc's,
> > not from being a dope, but from being human.
>
> Think of all the potential bugs that can occur from circular referencing
> and all that jazz under an automated garbage collector :)
Circular referencing is only a consideration when you do reference counting,
which is a /HORRIBLE/ technique. Java, for instance, uses mark-and-sweep,
which isn't susceptible to that at all.
As, of course, can anything. However destructors aren't really the
important thing here, since we're talking about easing the allocation
cycle. It's a simple enough thing in C++ to create an allocator class
which handles scoped destruction of objects. It's a little less trivial
to create a full shared pointer implementation, but fortunately the nice
guys over at boost.org have already done the work for that.
C++ doesn't force the programmer to use a conventional new...delete
cycle implicitly. Instead it has the flexibility to allow the
programmer to encapsulate that cycle in a generic fashion. The whole
smart pointer thing.
So no, I don't worry about my objects not being deallocated. They'll
die of when I tell them to or when they're no longer needed, and I know
exactly when that's going to happen.
>>>Think of all the potential bugs that can occur from a tirade of malloc's,
>>>not from being a dope, but from being human.
>>
>>Think of all the potential bugs that can occur from circular referencing
>>and all that jazz under an automated garbage collector :)
>
> Circular referencing is only a consideration when you do reference counting,
> which is a /HORRIBLE/ technique. Java, for instance, uses mark-and-sweep,
> which isn't susceptible to that at all.
Just so long as the programmer knows when things will be destroyed
automatically and when (if ever) they need to be freed manually, there's
no problem :)
<snip>
>>>GC congestions is certainly a great trade for not having to worry about
>>>every little allocation.
>>
>>In C++ at least this needn't be a problem. We've come a long way since
>>malloc :>
>
>
> Not really. Destructors can be badly written. :)
Ideally you wouldn't need a destructor at all. The compiler would
generate a destructor for you, so that your average class like
struct X
{
string name, address;
auto_ptr<Data> data;
BigClass more_data;
};
has an implicit destructor that will clean up each member recursively,
so it is very hard to fsck up. If you insist on using new and delete,
you run the risk of things going wrong, but to be honest the C++
containers often obviate the need for new and delete.
Calum
Interesting... I think that there is a generational thing going on here:
any tool that makes life "too easy" is not "proper programming". I
expect people who have used card feeders smirk at how easy us people
with hard disks have it.
Personally I feel very lucky to have been able to program on a ZX81 with
a wobbly RAM-pack, or to scratch my head over random segmentation faults
in C. Kids of today have it far too easy! (and I'm only 30 ;-) It
makes you realize how much you can achieve with so little by not
squandering resources. I too feel that people who have not experienced
this have missed out, are not so careful with resources, and have no
motivation or ability to write tight code.
The down-side is to not accept new technologies when they do offer
improvements. Making life easy is a good thing. Make kids learn C,
since then they'll actually see how a language executes, and then
they'll appreciate the newer language features. Unfortunately you
really need to get your hands dirty to really get to grips with a
language, so the art of programming as we romantically remember it may
be a dying art.
But like snaring rabbits or building a dry-stone wall, these skills may
not be necessary in the future??
Calum
Indeed, since C++ gained the STL tools, structs that "just hold data"
rarely need to be supplied with a destructor, assignment operator or copy
constructor. The ones that the compiler supplies work just fine.
I'll still usually provide a default constructor that provides for sensible
defaults and a convience constructor that fills in the data values.
Bill, "Why can't someone else do it"
I never said nor implied that. Read above where I said that the language
should not /force/ one to use GC.
> I
> expect people who have used card feeders smirk at how easy us people
> with hard disks have it.
>
> Personally I feel very lucky to have been able to program on a ZX81 with
> a wobbly RAM-pack, or to scratch my head over random segmentation faults
> in C. Kids of today have it far too easy! (and I'm only 30 ;-) It
> makes you realize how much you can achieve with so little by not
> squandering resources. I too feel that people who have not experienced
> this have missed out, are not so careful with resources, and have no
> motivation or ability to write tight code.
>
> The down-side is to not accept new technologies when they do offer
> improvements. Making life easy is a good thing. Make kids learn C,
> since then they'll actually see how a language executes, and then
> they'll appreciate the newer language features. Unfortunately you
> really need to get your hands dirty to really get to grips with a
> language, so the art of programming as we romantically remember it may
> be a dying art.
>
> But like snaring rabbits or building a dry-stone wall, these skills may
> not be necessary in the future??
>
I really doubt that resource management is not necessary for the future.
/Just maybe/ we can get away with having automatic memory management,
but the whole point of using a machine to do hundreds of calculations
and lookups per second is to streamline our resources.
Programmers who think that they need not have any ability managing
resources are going to be just as piss-poor at writing software as those
that think that theres no need to learn arithmetic.
Once again, I dont think that GC is bad (anymore:-), I think that a
language that *forces* one to use GC (and there are quite a few of those)
is going to have naturally poor programmers.
goose,
I used to think that, but it occurred to me that such things are not
necessarily crutches.
Consider that maybe
Knowing how to program without using a GC
only allows this quality:
Knowing how to program without using a GC.
This is an A begets A for A results situation.
Some months ago I was part of several threads that had similar theses. I
said something to the effect of:
Things are too easy for programmers these days.
When they are able to say "It's difficult to figure out
what size array I need, so heck, I'll allocate 100,000",
it leaves me wondering if all engineers should have
programmed back when Things Were Rotten, like
I did.
I believe this to be a sane statement, give or take. Because there are many
things learnable by programming with vastly limited resources that you just
don't get on an uberPC of uberGHZ with uberMB. Does GC fall into that
category? I'm not so sure.
There was also a similar thread in comp.object, I think by a someone named
Campbell(I think?) who pointed out <huge miss-paraphrase claxon going off/>:
Statically formed types (of statically typed languages)
only solve problems created by statically formed
types.
That was a long thread, involving much "but...but...but...how do you get
type safety???" but I actually turned 180° around and agreed with him,
realizing that type safety only solves its own problem. More or less.
I see arguments of this form often.
...[thwack]...
> Statically formed types (of statically typed languages)
> only solve problems created by statically formed
> types.
>
> That was a long thread, involving much "but...but...but...how do you get
> type safety???" but I actually turned 180° around and agreed with him,
> realizing that type safety only solves its own problem. More or less.
My question is: but isn't that a good problem to solve?
--
Somewhere in the Midwest...
Chris Sonnack <Ch...@Sonnack.com> in Training...
http://www.Sonnack.com/
No, that's just it. The problem doesn't exist unless you have types to
begin with.
So, say I want to deal poker hands from a deck of cards. I think I will
have to deal with cards, and with numbers of cards.
Looks like I've got types, even if a sloppy language doesn't help
distinguish them.
- Gerry Quinn
>>> with him, realizing that type safety only solves its own problem.
>>> More or less.
>>
>> My question is: but isn't that a good problem to solve?
>
> No, that's just it. The problem doesn't exist unless you have types
> to begin with.
My experience is that your data has a type at some point, even if
the "container" is type-blind or type-mutable or whatever.
My sense--and I don't claim any authority here at all--is that typeless
lanaguage tend to defer problems until runtime when types clash (and
my sense is they often do).
Static type checking does help you get one sort of issue right (more
or less! :-) during development. I'm not sure I agree with the idea
that that makes a developer overly-confident about program correctness
(which seems a big bullet point in the no-types platform :-).
Personally, I don't have any strong feelings one way or the other on
this issue.
They're called "dynamically typed languages" and are what I'm talking about.
Compile-time type safety from staticly defined types just aren't saving you
from what you think they are. At least I've now been "converted" to think
so, even though I'm a strong advocate of java, for example, a staticly typed
language.
>
> My sense--and I don't claim any authority here at all--is that
> typeless lanaguage tend to defer problems until runtime when types
> clash (and my sense is they often do).
I used to think so, but do not any longer. When I really thought it
through, and I /really/ have, the type safety that I was so concerned about
just wasn't really an issue.
Sure, /dynamically/ in a dynamically typed language, and statically so in a
statically typed language.
> even if a sloppy language doesn't help
> distinguish them.
>
> - Gerry Quinn
Dynamically typed languages are not "sloppy", nor inferior, they're just not
statically typed.
This was quite an adjustment for me to accept, I don't expect others to
accept it quickly, or ever in many cases. The odd thing is that I just
don't use dynamically typed languages any longer. I'm almost entirely java
now for years, so this isn't a religious thing for me at all.
> This was quite an adjustment for me to accept, I don't expect others to
> accept it quickly, or ever in many cases. The odd thing is that I just
> don't use dynamically typed languages any longer. I'm almost entirely java
> now for years, so this isn't a religious thing for me at all.
[grin] You speak exactly as religious converts do. Let's check back with
you in a few years after your conversion has had a chance to operate in
the real world for a while.
Watch your tone. I have been in the "real world" for a long time with both
statically and dynamically typed languages and know how to temper argument
with experience.
And no, religious converts say something to the effect of:
I used to do it this way, and loved it, but now I have
been doing it this other way instead, and have found
it to be superior.
What I'm saying is:
Although I am a pundit of a statically typed language,
(java), and do not use dynamically typed languages,
I recognize now that both my and other's common
arguments against dynamically typed languages were
not sound.
You gotta remember that when people expound their opinion about
programming, they usually speak from their own personal experience. I
think all that's going on here is that Joel has difficulty avoiding
memory leaks or double freeing or whatever in C/C++. And so this
probably shapes his thinking on the issue. If he got his
malloc/free's new/delete's matched up properly all the time, he
probably wouldn't be so obsessed with this.
Of course, I'll echo his main sentiment that OOP is not the panacea
that solves all programming problems. For my own biases, I notice
that: 1) It does not make the code execute any faster, 2) It does not
make the code any more explicit and 3) It does not improve the problem
of code maintenance. In fact, I would argue that, at least in C++, it
makes it worse in all 3 cases.
Garbage collection lets you get away with not writing destructors.
And if you think about it, this in fact is the least creative, most
restricted, and often can be the source of the most bugs in OOP. So
its a fair point to observe the natural advantage of GC over RAII. On
the other hand, for things like sockets or files, for example, you
almost always definately want it to explicitely close once you are
done with it. This is kind of the disadvantage of GC -- you generally
don't have the option of simply forcing an object to really finish in
those cases where you would want it to.
This makes an argument for wanting to have both. I.e., C++'s RAII for
resources that are not memory, and GC for actual memory. This leads
us to the one known solution that gives us exactly this:
http://www.hpl.hp.com/personal/Hans_Boehm/gc/
The Boehm garbage collector. I think most people can live with the
limitations of the above. (Unfortunately, I'm not one of those
people.) It allows you to write code as leaky as you like for memory,
while letting you close your files/sockets, killing your threads, etc,
exactly when you want/need to.
--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
This post of yours is sound and makes sense right up until and then after
this paragraph.
> 1) It does not make the code execute any faster,
"the code"? This statement is as if you can throw OO at an existing program
to see if it will run faster or not.
OO code executes in an OO fashion. PP code in a PP way.
> 2) It does not
> make the code any more explicit and
Explicit means that the code does more what it says and less is hidden? In
my opinion, this makes no sense. A procedural chunk of code is procedurally
explicit. An OO chunk is explicit in an object way.
> 3) It does not improve the problem
> of code maintenance.
Yes it does, but guaging such a thing is nearly impossible. It's like
trying to find a single comparative metric for measuring both the width of
an apple, and the weight of an orange.
In fact, I would argue that, at least in C++, it
> makes it worse in all 3 cases.
In the case of C++, I'd have to agree with #3, since to me C++ seems filled
with syntactic man holes missing covers, just waiting for the careless to
walk across. But for any OOP, #1 and #2 just don't make sense.
>> [grin] You speak exactly as religious converts do. Let's check back
>> with you in a few years after your conversion has had a chance to
>> operate in the real world for a while.
>
>
> Watch your tone.
What, the [grin]? [grin]
> I have been in the "real world" for a long time with both statically
> and dynamically typed languages and know how to temper argument
> with experience.
From what you wrote it sounded like your conversion was fairly recent.
It also sounded like you haven't used typeless languages to the extent
you've used typed languages.
> What I'm saying is:
>
> Although I am a pundit of a statically typed language,
> (java), and do not use dynamically typed languages,
> I recognize now that both my and other's common
> arguments against dynamically typed languages were
> not sound.
You've presented an opinion that seems to indicate the choice is clear
cut once you "get converted". The fact that some very, very astute
people argue the type/typeless issue endlessly indicates to me that the
issue is not so clear cut at all.
By "religious" I was referring to your implication (expressed again
in the para above) that the view is clear cut.
Typeless languages suffer from, well, in Smalltalk is the infamous
"Method not Found" runtime error. In general, typeless languages are
prone to runtime errors that statically typed languages aren't.
This doesn't mean one is better than the other, it just means you need
to be aware of the issues in either environment.
Go USE a typeless language in a production environment for as long as
you have used Java (so you get a chance to really explore the language
in all sorts of contexts and requirements) and see if you still think
it's so clear cut.
I wasn't really trying to be contentious, so much as suggesting you
seem to be in the blush of newly gained opinions, which are always
strong and fresh.
> Compile-time type safety from staticly defined types just aren't
> saving you from what you think they are.
They aren't saving me from type errors?
> At least I've now been "converted" to think so,..
HEY, DON'T DRINK ANY KOOLADE!!!!!
Huh? Everything is clear once someone gets converted to the point where
everything is clear. But that's not me.
What we have here is called a disagreement, with the added point that you
are making all the same arguments I used to make until I changed my mind.
That doesn't invalidate them of course. It's just where we are on this.
>The fact that some very, very astute
> people argue the type/typeless issue endlessly indicates to me that
> the issue is not so clear cut at all.
No kidding. Those very, very astute people don't get accused of sounding
like religious converts.
>
> By "religious" I was referring to your implication (expressed again
> in the para above) that the view is clear cut.
No implication. Not clear cut. Difficult as hell for most anyone bred on
statically typed languages.
>
> Typeless languages suffer from, well, in Smalltalk is the infamous
> "Method not Found" runtime error. In general, typeless languages are
> prone to runtime errors that statically typed languages aren't.
>
> This doesn't mean one is better than the other, it just means you need
> to be aware of the issues in either environment.
>
> Go USE a typeless language in a production environment for as long as
> you have used Java (so you get a chance to really explore the language
> in all sorts of contexts and requirements) and see if you still think
> it's so clear cut.
Never SAID it was clear cut---you are conveniently putting words in my
mouth.
Besides, I've been in java since the damn thing started. Beta version, pre
1.0, 1995.
Does that mean that I'm going to have to be using a dynamically typed
language for 9 years to be allowed to form an opinion of merrit? Or the 20
years including C (both statically typed)? Have you lost your mind?
I've used such languages before in production environments---usually as a
CGI interface, python to sql, or some other glue layer. I understand the
dynamic type issues well.
All that's happened is that I've devalued my former (and your current it
seems) arguments.
> I wasn't really trying to be contentious, so much as suggesting you
> seem to be in the blush of newly gained opinions, which are always
> strong and fresh.
And in saying so you are implying that I haven't thought this through for a
very long time? That takes an awful lot of nerve.
And here's where you're WAY off base. The need and beauty of statically
typed languages are an argument that I have formed since my personal dawn of
time. The argument has proven (to me) to be a weak one. That happened
within the last year or so. The debunking of the original argument is less
than a year old, but it is linked to the original argument which goes back
nearly forever.
Only a fool would disallow himself to change his mind.
Okay, but now that I have them, I'd like the language to work with me on
this!
> > even if a sloppy language doesn't help
> > distinguish them.
>
> Dynamically typed languages are not "sloppy", nor inferior, they're just not
> statically typed.
Let's forget I said 'sloppy' - but I have a big problem with languages
that don't let me define types, or squeal when I forget which is which.
I've got two types now: 'number of cards' and 'card'. The former can be
represented by an integer of some sort, signed or unsigned - usually
that's a type that's ready for use in any language. The latter might be
represented by an integer, or it might contain a pointer to a bitmapped
image, or it might have stuff I haven't thought of. To me the natural
approach is object orientation, in which this is a type with a set of
appropriate functions, some of which I don't know yet. [If I'm going to
be doing AI, I may also introduce a 'card index' that really is an int,
but that is by the way...]
Given that every time I introduce a variable, it represents something
that will be such a type, what earthly benefit accrues in allowing me to
subsequently change that, except along polymorphic lines such as
"AnimatedCard derives from Card". If I replace a Card by a number, or a
number by a Card, I have surely become muddled in my thinking, and the
compiler should help me out with a friendlyy warning.
If I were forced to use an untyped language (I think this is a better
description than 'dynamically typed' - we don't say a football is
dynamically kickable, we say we can kick it anywhere on its surface) I
would certainly be using Hungarian-type notation to make up for what I
would consider deficiencies of the compiler.
What does 'dynamic typing' or more exactly 'lack of typing' give the
programmer except a lot of options to blunder? What typing gives you is
a warning when you make certain conceptual blunders.
- Gerry Quinn
My point was to explain how personal biases leads one to focus one's
assessment of OOP in certain ways. I am concerned about different
aspects of programming that Joel is with different emphasis and it
leads me to see OOP in a different way. Anyone who wants to take OOP
down a peg can find any number of alternative reasons for doing so,
and I was just providing my own concerns as an example.
> > 1) It does not make the code execute any faster,
>
> "the code"? This statement is as if you can throw OO at an existing program
> to see if it will run faster or not.
That's because you do not see performance in the same way that I do.
After more than a decade of C programming and compiler analysis, its
clear to me that changes in the language are required to remove the
remaining inefficiencies between C and assembler. C++ or any of the
new OOP programming languages had a perfect opportunity to do this,
yet failed to do so. So just like Joel complains that OOP doesn't
help his memory matching problems, I am complaining that OOP does
nothing for performance.
> > 2) It does not make the code any more explicit and
>
> Explicit means that the code does more what it says and less is hidden?
Yes, that's precisely what I mean. Much of how programs behave is
dependent on platform specific details, or even program specific
details that are often not trivial to derive from looking at the raw
source code. This is just a more general way of thinking about
portability. Actually Java and Python substantially remove this
problem, however its not due to their OO features.
> > 3) It does not improve the problem of code maintenance.
>
> Yes it does, but guaging such a thing is nearly impossible. It's like
> trying to find a single comparative metric for measuring both the width of
> an apple, and the weight of an orange.
No, there is a simple measure for this. How easily can one developer
debug code written by another developer? To do so a developer has to
understand what another developer has done. Because OO generally adds
a very large number of ideas and features, this increases the skill
level bar for understanding other's code. C++, specifically, takes
this problem to the extreme.
> What does 'dynamic typing' or more exactly 'lack of typing' give the
> programmer except a lot of options to blunder? What typing gives you is
> a warning when you make certain conceptual blunders.
>
> - Gerry Quinn
One thing dynamic typing gives you is a simple way to do generic
programming, similar to templates in C++. Many algorithms, for example
quicksort, are the same regardless of data type.
Ok, fair enough.
>
>>> 1) It does not make the code execute any faster,
>>
>> "the code"? This statement is as if you can throw OO at an existing
>> program
>> to see if it will run faster or not.
>
> That's because you do not see performance in the same way that I do.
> After more than a decade of C programming and compiler analysis, its
> clear to me that changes in the language are required to remove the
> remaining inefficiencies between C and assembler. C++ or any of the
> new OOP programming languages had a perfect opportunity to do this,
> yet failed to do so. So just like Joel complains that OOP doesn't
> help his memory matching problems, I am complaining that OOP does
> nothing for performance.
What changes in C are required to remove remaining inefficiencies from it
and assembler?
>>> 2) It does not make the code any more explicit and
>>
>> Explicit means that the code does more what it says and less is
>> hidden?
>
> Yes, that's precisely what I mean. Much of how programs behave is
> dependent on platform specific details, or even program specific
> details that are often not trivial to derive from looking at the raw
> source code. This is just a more general way of thinking about
> portability.
Only if you think that procedural programming is somehow "closer" to
assembly.
> Actually Java and Python substantially remove this
> problem, however its not due to their OO features.
You can perform OO programming in assembler. You can perform PP programming
in assembler.
If you write an OO program in assembler, it is clear in an OO way.
If you write a PP program in assembler, it is clear in a PP way.
I believe that one of the roots of your argument might be the falsehood that
OO is "layered" upon Procedureal Programming in some way. It is not.
Having procedures (methods) within objects is not procedural programming.
>>> 3) It does not improve the problem of code maintenance.
>>
>> Yes it does, but guaging such a thing is nearly impossible. It's
>> like
>> trying to find a single comparative metric for measuring both the
>> width of
>> an apple, and the weight of an orange.
>
> No, there is a simple measure for this. How easily can one developer
> debug code written by another developer? To do so a developer has to
> understand what another developer has done. Because OO generally adds
> a very large number of ideas and features,
Not to the degree you think, but this opinion of yours is commonplace.
That's what I'm trying to point out. You're making the very common mistake
of looking at OO as a superset of PP. It is not. It only seems that way,
because we so often equate procedural programming with programming with
procedures.
Here's where your argument wins a little:
Does a procedural programmer have to understand inheritance? No.
Does an object oriented programmer have to understand the way in which a
complete program operates in a procedural fashion: that is to say breaking
the primary tasks down to sub-tasks etc from the begining of the program to
the end? /Probably/, but not to the degree you think.
> this increases the skill
> level bar for understanding other's code. C++, specifically, takes
> this problem to the extreme.
{Author chucks as if to say "yeah gross"}
Here you're almost right, in that you're picking on C++. C++ is in a
different category. I'd call it the "horrible" category. :) It is a
hybrid language which tries to please differing worlds and ends up often
pissing the purists in both worlds off.
> Gerry Quinn wrote:
>
> > What does 'dynamic typing' or more exactly 'lack of typing' give the
> > programmer except a lot of options to blunder? What typing gives you is
> > a warning when you make certain conceptual blunders.
> >
> > - Gerry Quinn
>
> One thing dynamic typing gives you is a simple way to do generic
> programming, similar to templates in C++. Many algorithms, for example
> quicksort, are the same regardless of data type.
Those familiar with qsort() or std::sort might not recognize it as a
variation of the Execute Around Pattern.
In a dynamically typed language with block closures, one passes a block into
the sort method to do the comparison.
I don't understand why block closures don't show up in statically typed
languages more often.
--
Phlip
http://industrialxp.org/community/bin/view/Main/TestFirstUserInterfaces
>>> Watch your tone.
>>
>> What, the [grin]? [grin]
Wish vocal tones conveyed... You'd realize how tongue-in-cheek I'm being.
>> You've presented an opinion that seems to indicate the choice is clear
>> cut once you "get converted".
>
> Huh? Everything is clear once someone gets converted to the point where
> everything is clear.
That's exactly the problem IF the reality is that the choice is NOT so
clear cut.
>> The fact that some very, very astute people argue the type/typeless
>> issue endlessly indicates to me that the issue is not so clear cut
>> at all.
>
> No kidding. Those very, very astute people don't get accused of
> sounding like religious converts.
Actually, the ones that present the case as clear cut often do.
> Never SAID it was clear cut---you are conveniently putting words in
> my mouth.
"Conveniently"? No, I apparently mis-read your intent. Relax. Have
a beer. It's NBD.
> Besides, I've been in java since the damn thing started. Beta version,
> pre 1.0, 1995.
>
> Does that mean that I'm going to have to be using a dynamically typed
> language for 9 years to be allowed to form an opinion of merrit?
Yes. (-: Well, you asked.
Seriously, a couple years of serious production work would make your
opinion carry a great deal of weight (with me). At this point, it
seems TO ME you are operating from conversion, not experience.
> Have you lost your mind?
No, it's backed up on tape. (I've waited YEARS for someone to feed me
that straight line.... thanks!!)
> All that's happened is that I've devalued my former (and your current
> it seems) arguments.
Mostly I'm playing Devil's Advocate to get you to go into detail about
your perceptions and change of heart. Most of the conversation has
been pretty high-level and vague thus far with you APPARENTLY (and I
may well be wrong) getting slightly defensive about this.
I'm REALLY not attacking you or even opposing you other than to give
you a platform for debate.
>> I wasn't really trying to be contentious, so much as suggesting you
>> seem to be in the blush of newly gained opinions, which are always
>> strong and fresh.
>
> And in saying so you are implying that I haven't thought this through
> for a very long time? That takes an awful lot of nerve.
Geeze, you're kind of a prickly SOB, ain'tcha. R*E*L*A*X! (-:
I got the impression this was a recent conversion. If I was wrong, I
apologize.
> And here's where you're WAY off base. The need and beauty of statically
> typed languages are an argument that I have formed since my personal dawn of
> time. The argument has proven (to me) to be a weak one. That happened
> within the last year or so.
Ah, I was right, it was recent.
> The debunking of the original argument is less than a year old, but it
> is linked to the original argument which goes back nearly forever.
Okay. Well, my only real argument SO far was that static typing prevents
a certain class of error that WILL occur at runtime in dynamically typed
languages. It's not about beauty or need, just about a way to eliminate
one class of error.
What is the typeless response that blows this away?
> Compile-time type safety from staticly defined types just aren't saving
> you from what you think they are.
I think they save me from making type errors. How is that not so?
One thing that interests me about Ada is its extreme type safety. If
you, for example, define a "pounds" integer type and a "Celsius" integer
type, Ada won't let you (casually) use them together.
>> My sense--and I don't claim any authority here at all--is that
>> typeless lanaguage tend to defer problems until runtime when types
>> clash (and my sense is they often do).
>
> I used to think so, but do not any longer. When I really thought it
> through, and I /really/ have, the type safety that I was so concerned
> about just wasn't really an issue.
With respect, sir, so far your answers are vague hand-waving. Can you
cite some hard cases, facts or examples?
>>> Compile-time type safety from staticly defined types just aren't
>>> saving you from what you think they are.
>>
>> They aren't saving me from type errors?
A question asked several times now without answer.
> Only a fool would disallow himself to change his mind.
Absolutely. And only a fool allows his mind to be changed for no
good reason (meaning me, not you).
...[thwack]...
>> Never SAID it was clear cut---you are conveniently putting words in
>> my mouth.
>
> "Conveniently"? No, I apparently mis-read your intent. Relax. Have
> a beer. It's NBD.
"Errrrrrrrrhhhh! Errrrrrrrrhhhhh! WHERE'S MY DOCTOR????"
-Baron Vladimir Harkonnen
>
>> Besides, I've been in java since the damn thing started. Beta
>> version,
>> pre 1.0, 1995.
>>
>> Does that mean that I'm going to have to be using a dynamically typed
>> language for 9 years to be allowed to form an opinion of merrit?
>
> Yes. (-: Well, you asked.
>
> Seriously, a couple years of serious production work would make your
> opinion carry a great deal of weight (with me). At this point, it
> seems TO ME you are operating from conversion, not experience.
Hmmm.... Lessee.
5 years heavy postscript (don't laugh. c'mon, stop laughing!)
1 year using perl to control an entire telephony system (with java at the
front end)
1 year using python (to sql+) to control the extraction of genetic "slices"
from a massive human genome. Basically a couple gig+ of dna pair
information.
That not enough to form an opinion of merit?
...[thwack]...
Have you been trapped under something heavy during all this? It /has/ been
answered. Several times by me with the following paraphrase.
The type errors you talk about are largely formed
from the type checking to begin with. There is
some advantage that seems at the surface: you
get compile-time feedback when you use a type
incorrectly. But that just doesn't seem to really be
that much of an advantage.
This is all I've stated. This is the extent that I can argue.
I've been using statically typed languages for freaking ever. I know what
they do and how they work and I've got a lot of experience doing enormously
complicated things with them. And I'm now of the opinion that most of what
type safety accomplishes is to enforce type safety.
Put it another way:
Accumulate all the time that establishing type safety in java takes. All
the extra effort to establish types, and use them carefully, etc. Let's
call that T1.
Accumulate all the time that you spend in smalltalk chasing down bugs that
occur from not having said type safety handled at compile time. Let's call
that T2.
You're claiming the common claim among the statically typed crowd:
T1 < T2
But if you talk to the most of the smalltalk guys (spend some time in c.l.s)
you'll get arguments that support:
1. T1 > T2
2. And you still get all the extra flexibility to boot.
I am not a smalltalk guy, but the argument has presented cogently enough for
me to be one of the few statically typed language pundits to agree with the
dynamically typed crowd.
My current conclusion is that all arguments taken together, it seems that
static types solve problems created by static types to begin with.
...[thwack]...
> 5 years heavy postscript (don't laugh. c'mon, stop laughing!)
> 1 year using perl to control an entire telephony system (with java
> at the front end)
> 1 year using python (to sql+) to control the extraction of genetic
> "slices" from a massive human genome. Basically a couple gig+ of
> dna pair information.
>
> That not enough to form an opinion of merit?
The PS is pretty restricted (and I don't know enough about it to
comment about its typelessness), but the rest... okay, NOW you've
convinced me that opinion may have weight.
So, getting back to my specific questions.... ;-)
And the type errors are largely there because of type safety.
> One thing that interests me about Ada is its extreme type safety. If
> you, for example, define a "pounds" integer type and a "Celsius"
> integer type, Ada won't let you (casually) use them together.
REALLY? Wow...
>
>>> My sense--and I don't claim any authority here at all--is that
>>> typeless lanaguage tend to defer problems until runtime when types
>>> clash (and my sense is they often do).
>>
>> I used to think so, but do not any longer. When I really thought it
>> through, and I /really/ have, the type safety that I was so concerned
>> about just wasn't really an issue.
>
> With respect, sir, so far your answers are vague hand-waving. Can you
> cite some hard cases, facts or examples?
Don't call /ME/ sir LOL
It's intended to not be black and white statements, because the concept is
not black and white. If you wish to call that "vague hand-waving" then so
be it. The guys in c.l.s and c.o are much better versed in this argument.
No one has asked yet what a dynamically typed language offers. Much of what
I believe to be impressive is that it supports the long-standing OO (purist)
believe system:
Polymorphism is more important than Inheritance
Because dynamically typed languages allow for polymorphism /WITHOUT/
inheritance.
You need to temper this with my /other/ safety first attitudes. I am an
extreme pundit of "safe" language constructs. It's the biggest reason that
I believe Java to be so superior to C++. I think that when engineers hail
the "power" of their language, they are merely establishing why you should
NOT use the language for serious development at all. For example, I'm a
complete junkie of what I call "the golden handcuffs" offered by java:
No MI
No pointers (as such)
No arbitrary goto
Boolean as a non integer type
etc.
It's just that I no longer believe type safety to be all that it's cracked
up to be. IMO the majority of the type safety hoops you must jump through
in statically typed languages accomplishes nothing. And I've lived with
type safety for a very long time.
Again: I cannot make this a black and white statement. It's purposefully
gray. Mostly because I don't believe that type safety is useless.
Enough of this. I've made my case using gray colors. You want black and
white. I cannot offer that. We should be done.
How?
> (and I don't know enough about it to
> comment about its typelessness), but the rest... okay, NOW you've
> convinced me that opinion may have weight.
You can be very insulting. Why /should/ I have to established this at all?
We don't seem to be demanding /YOUR/ resume.
> So, getting back to my specific questions.... ;-)
I think I did it elsethread a minute ago. If not, I give up.
>> A question asked several times now without answer.
>
> Have you been trapped under something heavy during all this?
Well, yes, sort of. I'm in a two-week class learning a major and
complex EAI application. (And I don't really appreciate your
sarcasm in what's trying to be a serious conversation. Lighten
up, please, and give me a break--I've been operating on 4-5 hours
of sleep for about three weeks now.)
> The type errors you talk about are largely formed
> from the type checking to begin with. There is
> some advantage that seems at the surface: you
> get compile-time feedback when you use a type
> incorrectly. But that just doesn't seem to really be
> that much of an advantage.
>
> This is all I've stated. This is the extent that I can argue.
Well, I guess I don't that a very satisfying answer. It seems rather
circular and vague. I'll try to think of an example where type checking
is helpful...
The other issue I've raised is that, don't dynamically typed systems
also have "type" errors, but they occur at runtime when a programming
mistake turns out to be impossible for the objects involved to handle?
Really all I can see are two different ways of doing something, each
having strengths and weaknesses. No clear winner.
> Accumulate all the time that establishing type safety in java takes. All
> the extra effort to establish types, and use them carefully, etc. Let's
> call that T1.
>
> Accumulate all the time that you spend in smalltalk chasing down bugs that
> occur from not having said type safety handled at compile time. Let's call
> that T2.
>
> You're claiming the common claim among the statically typed crowd:
>
> T1 < T2
I don't believe I have ever claimed such a thing.
> But if you talk to the most of the smalltalk guys (spend some time in c.l.s)
> you'll get arguments that support:
>
> 1. T1 > T2
> 2. And you still get all the extra flexibility to boot.
What concerns me in a production environment is catching errors BEFORE a
system goes out the door, so compile-time checks seem helpful.
I'd tend to believe that T1 and T2 are approximately equal considered
across all types of systems.
> My current conclusion is that all arguments taken together, it seems that
> static types solve problems created by static types to begin with.
Okay. My sense is that that's not necessarily a bad thing.
>> The PS is pretty restricted
>
> How?
Can it do: a device driver? a user GUI? a decent quicksort?
>> okay, NOW you've convinced me that opinion may have weight.
>
> You can be very insulting.
I don't mean to be. Thomas, I don't know you, and--per what you've
WRITTEN--some of your opinions seem emotionally weighted, so I'm
simply not inclined to accept it sans a quality check. No offense
is intended.
> Why /should/ I have to established this at all?
Just shows your background and adds weight to your views.
> We don't seem to be demanding /YOUR/ resume.
You're certainly welcome to if you doubt my veracity.
I'd like to see these answered, actually.
You probably can't do a device driver in PS, but a marginally useful GUI
might be possible, depending on if PS can take some form of user input.
A decent quicksort, why not ? You can do several fractal generators in PS,
including the mandelbrot set and some kind of snowflakes (to name two
examples that I have actually seen in action), so why not quicksort ?
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
>> Can it do: a device driver? a user GUI? a decent quicksort?
>
> I'd like to see these answered, actually.
Me, too!
> You probably can't do a device driver in PS, but a marginally useful GUI
> might be possible, depending on if PS can take some form of user input.
>
> A decent quicksort, why not ? You can do several fractal generators in PS,
> including the mandelbrot set and some kind of snowflakes (to name two
> examples that I have actually seen in action), so why not quicksort ?
{Ignorant (of PS) Answer} Quick sort would require data structures of
some sort. I know the Mandlebrot can be calculated on the fly as can
many other fractals. Don't know if that matters...
# {Ignorant (of PS) Answer} Quick sort would require data structures of
# some sort. I know the Mandlebrot can be calculated on the fly as can
# many other fractals. Don't know if that matters...
Postscript is like C. It is equivalent to a Turing machine and it
can do anything you provide a library interface for. The usual Postscript
implementations are oriented toward print file rasterisation, but
the language is general enough to be used for whatever else you
want.
--
SM Ryan http://www.rawbw.com/~wyrmwif/
So....that would make Bethany part black?
No language I know of is good for implementing state machines. In C, the
typical way to do it is to have a switch() wrapped by a while loop. However
this makes each transition *dynamic* (i.e., the switch variable is tested, then
the indirect jump is performed) when for just about any state machine I have
ever encountered, state transitions are fixed (or at least not determined by a
simple state variable). The performance penalty paid for this is *enormous*.
What should be nearly 0 cost direct branches end up being the equivalent of 15+
clock branch mispredictions. Its pretty pathetic.
I am not aware of languages that allow you to build code on the fly that get
compiled, then executed. (Actually, Lisp and its ilk may have this, but Lisp
is wholly objectionably for entirely other reasons.) This is important because
very often you have a complicated inner loop that can actually be substantially
optimized at *runtime* because of many parameters becoming constant (so
convoluted branches or switches on the inner loop become trivial).
Many many modern processors are now coming with SIMD instruction sets. This
follows the idea that there has been an aweful lot of redundancy in the effort
in instruction decoding bandwidth in CPUs versus actual computation. Many C
compilers now come with "intrinsics" for accessing these primitives, but they
are non-portable, and can be viewed as little more than "slightly nicer
assembly language". For example why can't I simply take two arrays of the same
type (say double a[10],b[10]) and pairwise multiply them with the simple
expression a * b?
Most languages have a tendancy to produce predictable and bit accurate floating
point. That's fine and ordinary a good idea, however it has to be put into
perspective. It turns out that there is *no* fair way to specify bit-precise
transcendental functions (sin, exp, etc) that wouldn't favor one kind of
architecture over another. Because of this IEEE-754 does *not* specify that
such functions have to be absolutely correct rounded to all bits. What this
means is, that there are a large class of FP calculations that cannot be made
reliably portable and/or bit accurate. The creators of Java found this out the
hard way when they tried to propose a bit accurate floating point model (based
on Sun's trascendental libraries, of course.) What this *should* mean is that
languages should expose a mode of operations where FP mathematics can be
assumed to have "ideal" accuracy, and allow massive reordering, simplifying etc
as dictated by performance/architecture of the platform. This would allow
compilers to schedule for latency and use special non-IEEE supported operations
like Multiply-Add. As it is, its typically not possible to make floating point
heavy code both portable and high performance.
> >> 2) It does not make the code any more explicit and
> >>
> >> Explicit means that the code does more what it says and less is
> >> hidden?
> >
> > Yes, that's precisely what I mean. Much of how programs behave is
> > dependent on platform specific details, or even program specific
> > details that are often not trivial to derive from looking at the raw
> > source code. This is just a more general way of thinking about
> > portability.
>
> Only if you think that procedural programming is somehow "closer" to
> assembly.
No, no, no. That's not what I mean. For example the result of a = b ? c : d
depends not only on the size of each parameter, but the default compiler
details about data type promotion. The result of a right shift depends on the
platform details, structures are packed according to padding strategies that
are platform depdendent and so on.
There was a famous issue that id software had when they tried to port Quake to
the Alpha processor. Everything worked fine except that the program would
occasionally dump out with a divide by 0 error. It turns out that the x86 C
compiler they were using just uses the IEEE mode which allows a divide by 0 to
result in an "inf" result, but the Alpha's C compiler did not.
It stuff like this, that you wish was somehow much more explicit at the
programming language level so that it wouldn't bite you in the butt later.
> [...] Does an object oriented programmer have to understand the way in which
> a complete program operates in a procedural fashion: that is to say breaking
> the primary tasks down to sub-tasks etc from the begining of the program to
> the end? /Probably/, but not to the degree you think.
Debugging *requires* complete understanding. OO is good for black boxing,
which would be great if it were not for the fact that bugs are inevitable.
I don't know who said this, but I must have him blocked because I didn't see
his message, but I'll answer with the following:
The term "restricted" has to do with language feature restrictions, not
things-you-cannot-implement.
The conversation centered on the restrictions of type safety in statically
typed languages.
That has nothing to do with whether or not I could implement a device
driver, a user gui, or chess program in it.
Sorry. I'm expecting my first child in august. I'm bracing myself for
dismal sleep as well.
You sort of are if you think that statically typed languages are a win
because they save you in the end.
I dunno. I'm tired of this subthread. I bet you are too even more so.
> beli...@aol.com wrote:
>> I think Joel Spolsky writes good stuff. At
>> http://www.joelonsoftware.com/articles/APIWar.html he says that
>> automatic memory management does more to boost programmer productivity
>> than OOP (of course you can have both). Comments?
>>
>> "A lot of us thought in the 1990s that the big battle would be between
>> procedural and object oriented programming, [...] Whenever you hear
>> someone bragging about how productive their language is, they're
>> probably getting most of that productivity from the automated memory
>> management, even if they misattribute it."
>
> You gotta remember that when people expound their opinion about
> programming, they usually speak from their own personal experience. I
> think all that's going on here is that Joel has difficulty avoiding
> memory leaks or double freeing or whatever in C/C++. And so this
> probably shapes his thinking on the issue. If he got his
> malloc/free's new/delete's matched up properly all the time, he
> probably wouldn't be so obsessed with this.
>
> Of course, I'll echo his main sentiment that OOP is not the panacea
> that solves all programming problems. For my own biases, I notice
> that: 1) It does not make the code execute any faster, 2) It does not
> make the code any more explicit and 3) It does not improve the problem
> of code maintenance. In fact, I would argue that, at least in C++, it
> makes it worse in all 3 cases.
>
> Garbage collection lets you get away with not writing destructors.
> And if you think about it, this in fact is the least creative, most
> restricted, and often can be the source of the most bugs in OOP. So
> its a fair point to observe the natural advantage of GC over RAII. On
> the other hand, for things like sockets or files, for example, you
> almost always definately want it to explicitely close once you are
> done with it. This is kind of the disadvantage of GC -- you generally
> don't have the option of simply forcing an object to really finish in
> those cases where you would want it to.
>
> This makes an argument for wanting to have both. I.e., C++'s RAII for
> resources that are not memory, and GC for actual memory. This leads
> us to the one known solution that gives us exactly this:
>
> http://www.hpl.hp.com/personal/Hans_Boehm/gc/
>
> The Boehm garbage collector. I think most people can live with the
> limitations of the above. (Unfortunately, I'm not one of those
> people.) It allows you to write code as leaky as you like for memory,
> while letting you close your files/sockets, killing your threads, etc,
> exactly when you want/need to.
>
> --
> Paul Hsieh
> http://www.pobox.com/~qed/
> http://bstring.sf.net/
Paul Hsieh wrote:
> Of course, I'll echo his main sentiment that OOP is not the panacea
> that solves all programming problems.  For my own biases, I notice
> that: 1) It does not make the code execute any faster, 2) It does not
> make the code any more explicit and 3) It does not improve the problem
> of code maintenance.  In fact, I would argue that, at least in C++, it
> makes it worse in all 3 cases.
Please tell me what the advantage of OOP is then. I thought that OOP made it
easier to write large programs because it enabled you to build the program
with small independent parts, also making it more manageable. Is this not
true?  Please tell why I should use OOP.
> beli...@aol.com wrote:
>> I think Joel Spolsky writes good stuff. At
>> http://www.joelonsoftware.com/articles/APIWar.html he says that
>> automatic memory management does more to boost programmer productivity
>> than OOP (of course you can have both). Comments?
>>
>> "A lot of us thought in the 1990s that the big battle would be between
>> procedural and object oriented programming, [...] Whenever you hear
>> someone bragging about how productive their language is, they're
>> probably getting most of that productivity from the automated memory
>> management, even if they misattribute it."
>
> You gotta remember that when people expound their opinion about
> programming, they usually speak from their own personal experience. I
> think all that's going on here is that Joel has difficulty avoiding
> memory leaks or double freeing or whatever in C/C++. And so this
> probably shapes his thinking on the issue. If he got his
> malloc/free's new/delete's matched up properly all the time, he
> probably wouldn't be so obsessed with this.
>
> Of course, I'll echo his main sentiment that OOP is not the panacea
> that solves all programming problems. For my own biases, I notice
> that: 1) It does not make the code execute any faster, 2) It does not
> make the code any more explicit and 3) It does not improve the problem
> of code maintenance. In fact, I would argue that, at least in C++, it
> makes it worse in all 3 cases.
>
> Garbage collection lets you get away with not writing destructors.
> And if you think about it, this in fact is the least creative, most
> restricted, and often can be the source of the most bugs in OOP. So
> its a fair point to observe the natural advantage of GC over RAII. On
> the other hand, for things like sockets or files, for example, you
> almost always definately want it to explicitely close once you are
> done with it. This is kind of the disadvantage of GC -- you generally
> don't have the option of simply forcing an object to really finish in
> those cases where you would want it to.
>
> This makes an argument for wanting to have both. I.e., C++'s RAII for
> resources that are not memory, and GC for actual memory. This leads
> us to the one known solution that gives us exactly this:
>
> http://www.hpl.hp.com/personal/Hans_Boehm/gc/
>
> The Boehm garbage collector. I think most people can live with the
> limitations of the above. (Unfortunately, I'm not one of those
> people.) It allows you to write code as leaky as you like for memory,
> while letting you close your files/sockets, killing your threads, etc,
> exactly when you want/need to.
>
> --
> Paul Hsieh
> http://www.pobox.com/~qed/
> http://bstring.sf.net/
OOP breaks things down into "black boxes".
All you need to know to maintaining a piece of software is what the
objects do and you don't need to concern yourself with _how_ they do it.
My view is that OOP extends the idea of "black box" funtional
programming to encapsulate data as well.
In a large project with good documentation, good encapsulation can allow
extending a piece of software without the need to look at any existing code.
--
Ben M.
> Postscript is like C. It is equivalent to a Turing machine and it
> can do anything you provide a library interface for.
Interesting. (Although using a non-language library is cheating! :-)
> The term "restricted" has to do with language feature restrictions, not
> things-you-cannot-implement.
>
> The conversation centered on the restrictions of type safety in statically
> typed languages.
>
> That has nothing to do with whether or not I could implement a device
> driver, a user gui, or chess program in it.
I seem to have opened a can of worms. Perhaps a better word might have
been "special purpose" or something similar. And what I was getting at
is that PS programmers wouldn't (I imagine) be doing much general purpose
programming, so I was (mildly) questioning its relevance.
I suppose the real question should be what KIND of programming one did in
PS....
You can't write device drivers in ANS C without memory-mapped I/O.
ANS C doesn't include I/O port read/write/query instructions. It's
not that hard to add a inb and outb pseudo-functions in C, nor would
it be that hard to add them to a Postscript iinterpretter. Perhaps some
printers already have.
My understanding is that Postscript started with Evans and Sutherland
where it was a more general purpose language; it's essentially FORTH
with anonymous procedures and type tagged values.
--
SM Ryan http://www.rawbw.com/~wyrmwif/
One of the drawbacks of being a martyr is that you have to die.
Like writing Perl -- C++ code is easier to *write*. Its not easier to
maintain. Its harder to comment definitively on other OOP languages,
because they don't have an obvious analogue that's not OOP.
(Certainly python is easy to understand and maintain regardless or
perhaps in spite of being somewhat OO, for example.) OOP provides
obvious advantages in terms of application design when being object
based is a logical way to design it (which is common). But software
development includes more than just the ability for a single
programmer to spit out code.
> I'm expecting my first child in august. I'm bracing myself for
> dismal sleep as well.
And you'll definitely be getting it! (-:
CS> The other issue I've raised is that, don't dynamically typed systems
CS> also have "type" errors, but they occur at runtime when a programming
CS> mistake turns out to be impossible for the objects involved to handle?
CS>
CS> Really all I can see are two different ways of doing something, each
CS> having strengths and weaknesses. No clear winner.
>>
>> [snip]
>>> You're claiming the common claim among the statically typed crowd:
>>>
>>> T1 < T2
>>
>> I don't believe I have ever claimed such a thing.
>
> You sort of are if you think that statically typed languages are a win
> because they save you in the end.
Please to note CS> quoted part. ALL I'm saying is that there are good
and bad points to both and no clear winner. EOT!
For example, isn't dynamic typing slower at runtime? Isn't static
typing more supportive of proving program correctness? I believe the
answers are yes and yes (but... I'm not certain).
> I dunno. I'm tired of this subthread. I bet you are too even more so.
No, actually this is a subject that interests me. I've sat on the
sidelines of several of those debates, and have come away with the
opinion I've expressed above (good/bad/no winner). Because I DO
respect your abilities and views, I've been curious about exactly
why you came away "converted".
Thus I've been trying to drive the conversation beyond the somewhat
zen-ish "type systems solve the problems type systems create".
Is it possible that the type problem exists (in that raw data can
have a definite type), and type systems *help* mitigate it?
But, if you're tired and 'great with child', I'll understand. (-:
Please compare Perl's "tainting" to ordinary strong typing. I.e.,
rather than having strings that had "taint" or "non-taint" dynamically
assigned to them, imagine you simply had two types or strings. One
trusted and one not trusted.
The clear advantage there is that strong typing gives you compile time
determinations of bugs, while Perl necessarily can only give you
runtime determination of bugs. So strong typing can be used to help
you avoid certain kinds of semantic traps.
One could easily flip the statement around and say:
Dynamically formed types just save you from writing declarations;
they rarely serve a truly polymorphic need (and it could be solved
with operator overloading instead.)
Here's a good article I found on the subject:
http://www.fact-index.com/d/da/datatype.html
At the end it gives the pros and cons of both approaches.
--
Ben M.
OOP has brought maintability and extensibilty that were completely
missing in Procedural. Yes, you could argue that using structures and
functions you could simulate OOP but is it maintainable in the long
run.
I am not saying do completely away with procedural for certain
applications procedural is just a faster way of getting things done.
But for a long term project with teams of programmers OOP is the best
solution. It allows for resuability and extensibilty of code that
procedural cannot provide. But yes there is catch, the programmers
must think and program OO and not think procedural and try to program
OO.
The other point about automatic memory management, I love the feature
as it takes away the pain of forgetting to deallocate memory and
making a program leak memory like a sieve. But it also has a big
problem in terms of no control.
This must sound paradoxical but I want to control my automatic memory
manager. There are times when I do not want it to kick in especially
if I am programming in a memory limited environment or situations when
the slightest degradation of perfomance cannot be tolerated. One
reason why Java is not the de facto language to program games or do
hard-core systems programm.
Maybe I want the best of both worlds...........but I will say this OOP
if used properly can generate time savings that are just mind-blowing
> Here's a good article I found on the subject:
> http://www.fact-index.com/d/da/datatype.html
>
> At the end it gives the pros and cons of both approaches.
Pretty good basic overview, although it started off looking like
it was written by Smeagol (with "objectss" and "variabless" :-).
>> (Although using a non-language library is cheating! :-)
>
> You can't write device drivers in ANS C without memory-mapped I/O.
But you certainly can in C-- (i.e. less strictly-ANSI C :-).
While you can do a good number of things in strict ANSI C, most OS and
driver stuff requires stepping outside the standard. Which is fine, as
you are usually targeting only a specific system and don't need to worry
about the platform independance ANSI C helps buy you.
Point is, you certainly can write a device driver in raw C, sans libs.
Is it possible in PS under identical conditions.
> ANS C doesn't include I/O port read/write/query instructions. It's
> not that hard to add a inb and outb pseudo-functions in C, nor would
> it be that hard to add them to a Postscript iinterpretter. Perhaps some
> printers already have.
Well, then that answers my question. PS *can* access specific addresses
in memory.
> My understanding is that Postscript started with Evans and Sutherland
> where it was a more general purpose language; it's essentially FORTH
> with anonymous procedures and type tagged values.
Interesting. Maybe I'll just add PS to my medium-sized list.... sorta
thought about it over the years...
Thanks!
the usefulness of OO is that it provides a clear deliniation of
responsibilities for your program. classes help to explain what does
what. particularly for the programmers involved, many projects are like
the back of their hand.
but as soon as you start trying to integrate your project, or integrate
other projects into yours, the first major feature you add three years
down the road: these are all cases where OO becomes useful again.
if your project is of moderate size, truly stands alone, and will never
be modified, OO might not be the right tool.
as for memory management, much depends on the coder. does your testing
harness use valgrind (open source memory debugger)? not using a memory
debugger is much akin to extended periods of coding without some
intermittent compiling: you are merely compounding your errors and
problems. the difference between compiler errors and runtime errors is
somewhat artificial.
good coding practice is everything.
Myren
.....not really....
http://www.prepressure.com/ps/history/history.htm
>
> Interesting. Maybe I'll just add PS to my medium-sized list.... sorta
> thought about it over the years...
Don't forget that NeXT actually foisted "display postscript" upon the world.
A VERY nifty idea. /THAT/ should have been what HTML is today....
I think the closest I can come is the T1 T2 relatationship. It's so hard to
compair the width of a tree to the temperature of a ball bearing...
Sure, but at what trade off in time consumption. And how much of those bugs
/really/ surface? The smalltalk guys (and many of them come from or
straddle the statically typed world) don't seem to be wowed by it.
I completely agree.
I've said this before in other threads, and this topic arises here every
other minute or so. But I really /tried/ to not be swayed into the OO
paradigm. I just saw it as a passing fad.
Until I was in it up to my eyeballs. After 6 months to a year it hit me:
One serious software system after another were nearly gluing themselves
together in front of me at blazing speed. Is that an exaggeration? Sure.
But it's what it felt like.
I thoroughly enjoyed seeing coworkers able to come up with "things" that
could be used by other "things" in intriguing ways. Far more impressive
than mere procedures being called by other procedures in the PP world. I
loved knowing that I could make an entirely new type of GUI button with an
LED drawn on it (for example) and use that button everywhere else a
"regular" button could be used. I can honestly say now (I've been in OO ~8
years, and PP for ~12 years before that) that I'm horrified at the thought
of someday having to program procedurally again.
I'm uncomfortable with an apples/oranges comparisons, but what I /can/ say
is that my very first, instinctive, and most comfortable reaction to every
new project is to view it's development in OO terms.
I was not just simply referring to memoey leaks, yes I agree a memory
debugger is essential. My point however was that the benefit of OOP is
not automatic memory management but more in terms of the extensibility
it gives us.
For example Java has the greatest garbage collector around, when I am
programming for a platform with abundant memory. Say, I want to do
game programming or hard-core systems programming using Java, then I
do not like the fact that I cannot control when the garbage collector
kicks in. I like full or atleast a partial-control based on certain
parameters I set in terms of the load-balancing I want (I have a
dicussion up on just this fact).
Automatic Memory Management is great but not the greatest benefit of
OOP.
Aren't they completely independent things, seperate of each other?
--
Ben M.
I wouldn't worry about it. I've been learning PHP for about an hour in
total and already I feel qualified to make criticisms.
Bill, should say by the way that you're acting today, can tell by the sigh
in your eye.
I am commenting on the original statement
"I think Joel Spolsky writes good stuff. At
http://www.joelonsoftware.com/articles/APIWar.html he says that
automatic memory management does more to boost programmer productivity
than OOP (of course you can have both). Comments? "
As far as the OOP and memory management being seperate, yes but the
original thread finds a connection based on the advent of a new crop
of OOP languages that almost inevitabely provide auto memory
management the best example Java
-S
QUOTE.
(at least part of).
THE.
PRIOR.
POST.
Very often a reply is either 1. in the middle of a hugely indented thread
that makes it hard to figure out whom upstream you're talking to if it isn't
immediate above you, and 2. many people have crummy usenet retention
(persistence) on their ISP's.
>
> Automatic Memory Management is great but not the greatest benefit of
> OOP.
I'm uncomfortable even saying that it IS a benefit of OOP. Cannot
theoretically a PPL employ start-of-structure-only pointers (like java's
references) where everything is accessed by indirection?
Ah...should've read through further before replying to your upstream post.
I see.
Does ANYONE know of a procedural programming language that implements
start-of-structure-only references like java, has that as the only way to
access a structure, and therefore has similar GC?
Bounded arrays would be manditory I presume.
Huh? Strongly typed languages are usually faster because of it (they
are usually compiled.) Its not a trade off, its a win-win for the
strongly typed languages. Dynamic typing just saves you physical
typing (and the language architect from designing a type system).
> [...] And how much of those bugs
> /really/ surface? The smalltalk guys (and many of them come from or
> straddle the statically typed world) don't seem to be wowed by it.
I don't know or care about Smalltalk. However, I have dabbled quite a
bit with Python. Quite simply, dynamic typing introduces a whole new
class of "runtime type mismatches". It can manifest by functions
which return marginal values (such as error messages) that are of a
different type than what it usually outputs. In the consuming
functions you, maybe neglect to do the type discrimintation, and thus
you don't notice the problem until its too late, and it is in the
middle of a run.
Also languages like python let you very quick re-architect code. This
is like fly paper for inadverent dynamic type mismatch problems. You
switch from a list to an associative array because you realize that
you need more information from a certain structure -- but you forget
to fix some auxilliary function that dealt with the old output.
There is no analogue to this in the strongly typed world. And there
is no reliable way to ferret out this class of problem without doing
some kind of exhaustive testing of your code (i.e., where you prove
that every possible permutation of types for every entry point, and
every possible control condition is tested). Its just a compile time
error in the strongly typed world.
I'm not saying dynamically typed languages are without their benefits,
but this issue is the clear trade off which reflects not only my own
experience, but that of others that I have talked to about such
languages.
Please, for the love of Usenet, quote the relevant parts of the previous
post. I had to paste it in for you.
Back to the thread, if they're totally seperate (as you yourself agree)
then how is automatic memory management at all a benifit of OOP?
Isn't that like saying seat-belts are a benifit of air-bags, since there
is a connection based on the advent of new cars which inevitably provide
both?
(BTW, I'm a supporter of OOP and think that C++ provides memory
management features that have much of the advantages of a GC and none of
the major disadvantages.)
--
Ben M.
Not talking about run time efficiency, I'm talking about the amount of time
it takes to create a project, and maintain it.
> Its not a trade off, its a win-win for the
> strongly typed languages. Dynamic typing just saves you physical
> typing (and the language architect from designing a type system).
That "physical typing" you state is misleading IMO. No one just turns their
brain off and clacks at the keyboard and then compiles (well, there are a
couple in some of these ng's that I'm sure do. :) )
If there's anything to physically type, then there is considerable amount of
thought going into it, much of it you don't have to worry about at all with
dynamic typing.
As I pointed out before, with dynamic typing, you don't need inheritance at
all for polymorphism, as an example.
Among the primary advanges of the java GC is that your team of engineers
cannot @#$%up the memory management stuff like they might in C++.
> Ben Measures <saint_abr...@removehotmail.com> coughed up the
> following:
>
>>
>>(BTW, I'm a supporter of OOP and think that C++ provides memory
>>management features that have much of the advantages of a GC and none
>>of the major disadvantages.)
>
>
> Among the primary advanges of the java GC is that your team of engineers
> cannot @#$%up the memory management stuff like they might in C++.
>
>
Just to add fuel to the fire from personal experience:
What happens if there's a bug in the GC and it
doesn't clean up everything it's supposed to?
This happened to us about a year ago. It was an
obscure bug for which I don't have the details handy.
The Java programmers had little or no experience
tracking down memory leaks. The C or C++ programmers
had little or no Java expertise so they couldn't
really help. Granted, this is an extreme example,
but it does happen. Sun promised a "fix in the next
release" but that didn't cut the mustard with our
client. JVM restarts every week were not an option
for them.
No diatribes meant at anyone or any language, just relating an
experience.
NPL
--
"It is impossible to make anything foolproof
because fools are so ingenious"
- A. Bloch
Well, it basically sucks. :)
Bit what happens when your compiler produces code that treats
1.040 > 1.04
...like I documented elsegroup...
compilers @#$%up. Fact o' life.
...meant to say /things/ @#$%up.
Absolutely true. /things/ , whether
compilers or GC's are written by humans
(at least I hope so), and are subject
to the same faults as any other software.
You have to weigh the pro's and con's
for every decision. (Debug *your* software,
or file a trouble report with the vendor).
There is a different tradeoff for almost
every project.
>
>
>>>This happened to us about a year ago. It was an
>>>obscure bug for which I don't have the details handy.
>>>The Java programmers had little or no experience
>>>tracking down memory leaks. The C or C++ programmers
>>>had little or no Java expertise so they couldn't
>>>really help. Granted, this is an extreme example,
>>>but it does happen. Sun promised a "fix in the next
>>>release" but that didn't cut the mustard with our
>>>client. JVM restarts every week were not an option
>>>for them.
>>>
>>>No diatribes meant at anyone or any language, just relating an
>>>experience.
>>>
>>>NPL
>
>
>
Google has 11 hits for "Execute Around Pattern". Google groups has
6 hits, all posts of yours.
I think I just recognized your post as being a variation of the
Pretentious Nonsense Pattern.
Christer Ericson
Sony Computer Entertainment, Santa Monica
The removal of aliasing, partially addressed by the addition
of "restrict" in C99.
> (BTW, I'm a supporter of OOP and think that C++ provides memory
> management features that have much of the advantages of a GC and none
> of the major disadvantages.)
I am not a C++ expert, and I would like to know more about this
claim. You are also not the only one in this group making similar
claims.
It think it was Paul Wilson (an expert in memory management) who put
it this way "liveness is a global (and thus not a modular) property"
meaning, in a modular program, you essentially cannot know whether an
object is referenced from a different module or not, without breaking
the modular abstraction barriers.
If Paul Wilson is right, the consequences are that you have a choice
between modularity and correct memory management, but you cannot have
both.
The way I often see C++ programmers solving this problem is either by
* using reference counters. Each module independently increments
and decrements the reference counter. An object is reclaimed
when its reference count goes to zero. It is well known that
this method cannot handle cycles, although with some tricks this
problem can sometimes be compensated for. Worse, now an
assignment which should only take half a cycle on a modern
processor requires accessing the contents of the object and
incrementing or decrementing a field. Decrementing also requires
a test to see whether the counter now is equal to zero. One can
easily lose an order of magnitude in performance by this method.
* systematically copying objects. This method guarantees that each
copy has a reference count of 1, so that it can be deleted when
no longer needed locally. The problem, however, is performance,
because now an assignment requires copying the entire object
representation, invoking a copy constructor, etc. The penalty
can easily be one or two orders of magnitude,
In the past, I have seen claims in this group that the liveness
problem can be solved with smart pointers. I know how smart pointers
work (or at least I thought I did), but I fail to see (no doubt
because I am not an expert) how they can solve this problem. I would
appreciate if you (or someone else) could tell me more about this
subject.
For instance, suppose you have a (directed) graph of objects. Let's
say there are no cycles. At some stage of the computation, an arc
from one object to the other should be removed. How do you decide
whether to delete the target of the arc? If you delete it too and it
happens to be referenced by some other object, then you have deleted a
live object. If you do not delete it, and it happens not to be
referenced by any other object, you have a memory leak.
How can smart pointers or any technique other than automatic memory
management solve this problem?
Perhaps the graph example seems artificial, but it is actually quite
common. In a word processor, for instance, words may be referenced
from both the "model" and the "view" to use MVC terminology. In an
information system, objects can be simultaneously contained in
different containers in different modules of the system, etc.
Also, one of the major disadvantages of traditional GC technology is
that it introduces unbounded pauses. If this is one of the
disadvantages of GC that you refer to, I would like to know how C++
programmers deal with avoiding such pauses. Whether you use smart
pointers, copying, or reference counters, it seems to me that the
number of objects that can be reclaimed by a single destructor
invocation is unbounded as well, which would mean that pauses are
inevitable even without a GC. Now, garbage collectors can be written
to avoid such pauses, and can in fact be written for hard real-time
applications. The price to pay is that at any point in time there
will typically be unreferenced objects that have not yet been
reclaimed. However, trying to make sure an application using manual
memory management has no pauses would require a technique where
reclaiming objects would sometimes be deferred in order to put an
artificial bound on the number of objects to be reclaimed at once.
Doing so will introduce the same problem as with GC, namely the
existence of unreferenced but not-yet-reclaimed objects.
To summarize, I would like to know in what way the liveness problem
can be solved in a modular way without a GC, and how the disadvantages
of a GC (pauses, working set) are solved in a system without one.
--
Robert Strandh
---------------------------------------------------------------------
Greenspun's Tenth Rule of Programming: any sufficiently complicated C
or Fortran program contains an ad hoc informally-specified bug-ridden
slow implementation of half of Common Lisp.
---------------------------------------------------------------------
Dynamic typing doesn't mean there are no types, just that they are
determined at runtime. If anything, you need to worry more about typing
with dynamic typing.
Here's an example of one of the typing problems you get with dynamic
typing (and not static typing):
(from http://www.fact-index.com/d/da/datatype.html)
For example, would the result of the following code be 9 or "54"?
var x = 5;
var y = "4";
x + y;
> As I pointed out before, with dynamic typing, you don't need inheritance at
> all for polymorphism, as an example.
Only for parametric polymorphism - if you want different behaviour
you'll certainly need inheritance. Through its template features, C++
provides for parametric polymorphism without needing inheritance, just
like a dynamically typed language can.
For a more detailed overview of typing and polymorphism, take a look at
http://www.objectfaq.com/oofaq2/body/typing.htm .
--
Ben M.
goose said it earlier in the thread better than I can:
http://tinyurl.com/3g4g8
--
Ben M.
In both statically typed as well as dynamically typed environments,
this fully depends on the implementation of the '+' operator.
As such the 'problem' has nothing to do with static vs. dynamic typing.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
In a statically typed language you can make clear your intentions so
that the compiler can pick up on, for example, if you've got the
operands the wrong way around.
In a dynamically typed language it's entirely possible to accidently get
the wrong result, and this can be difficult to debug.
--
Ben M.
There are other ways to achieve different behaviour, like first class
functions. To achieve different behaviour in a modular way, you need
some kind of dynamic dispatch. This is ortogonal to inheritance.
Unfortunately most widely used programming languages supporting OOP make
you believe that they are inseparable.
> Through its template features, C++ provides for parametric
> polymorphism without needing inheritance, just like a dynamically
> typed language can.
C++ templates give more than parametric polymorphism - templates don't
have to behave uniformly.
Best regards,
Tom
--
.signature: Too many levels of symbolic links
Nothing to maintain (since you can't productize something you can't compiler)
versus a degree of maintainability whose accessibility is equivalent to the
halting problem?
Remember this is a narrow point -- and you can't weasle or talk your way
around it. Run time dynamic type mismatches are for real in dynamically typed
languages; they are very annoying and they don't exist in strongly typed
languages. You can be objective and realize this as the primary fundamental
trade off or you can be blinded by typical language adherence fanatacism.
> > Its not a trade off, its a win-win for the
> > strongly typed languages. Dynamic typing just saves you physical
> > typing (and the language architect from designing a type system).
>
> That "physical typing" you state is misleading IMO. No one just turns their
> brain off and clacks at the keyboard and then compiles (well, there are a
> couple in some of these ng's that I'm sure do. :) )
When typing declarations? Calculations/computations and how they map to the
algorithm I have in mind is what dictates my implementations. The
declarations are the "fill in the blanks" that I very often do after I've
decided what the inner loop is supposed to look like. Seriously, often when
I am being lazy I'll write an inner loop and if I forget the variables I
needed to declare, I'd just run it through the compiler, copy the error
messages into the code and whack in declarations as necessary.
> If there's anything to physically type, then there is considerable amount of
> thought going into it, much of it you don't have to worry about at all with
> dynamic typing.
>
> As I pointed out before, with dynamic typing, you don't need inheritance at
> all for polymorphism, as an example.
Yes, but you also have to deal with *inadvertent* polymorphism.
> "Thomas G. Marshall" wrote:
> > Not talking about run time efficiency, I'm talking about the amount of time
> > it takes to create a project, and maintain it.
>
> Well on this very narrow point, what I am saying is that a compiler error that
> tells the programmer about an error before the program runs is better than a
> program that doesn't tell you about the error until it runs some specific
> scenario and there isn't necessarily a developer around to fix it.
While this might seem like an obvious statement, things are not quite
that simple. Obviously, if everything else stays the same, then it is
better to have errors caught at compile time than at runtime.
However, if the ability to catch errors at runtime influences other
aspects of the development process negatively, things are not
necessarily just positive.
As Thomas hinted, if the ability to catch some errors at compile time
influences the time it takes to create the project, you might be faced
with a situation of catching errors at compile time in a project that
will not finish on time, or that will be canceled from running out of
funding, whereas if you give up on that ability, you might finish the
project.
> Remember this is a narrow point -- and you can't weasle or talk your way
> around it. Run time dynamic type mismatches are for real in dynamically typed
> languages; they are very annoying and they don't exist in strongly typed
> languages.
Of course they exist, even in statically ("strongly") typed languages.
The fact that you cannot declare a variable of type "positive even
integer", and the existence of divide-by-zero runtime errors is proof
of the presence of type mismatches. In order for a type system to be
decidable, some approximations have to be made. The claim is that, in
order to be decidable, such approximations necessarily have a negative
impact on development time and, more generally, on the kind of correct
programs that can be expressed.
> You can be objective and realize this as the primary fundamental
> trade off or you can be blinded by typical language adherence fanatacism.
Of course it is a fundamental trade off, but the trade off is not
between catching all type errors at compile time, or not catching
them. The trade of is between on the one hand catching some type
errors at compile time at a the cost of not being able to express some
correct programs and of making development time longer, and on the
other hand of not catching some of those errors (that may not exist
anyway) in an expressive language that allows very rapid development.
I had to read that paragraph several times - I couldn't believe my eyes.
Are you really suggesting that I can finish my project sooner if I chose
a compiler that accepts faulty code? This is how I read it:
"you might be faced with a situation of a project that will not finish
on time, whereas if you give up on that ability [catching errors at
compile time], you might finish the project."
>>Remember this is a narrow point -- and you can't weasle or talk your way
>>around it. Run time dynamic type mismatches are for real in dynamically typed
>>languages; they are very annoying and they don't exist in strongly typed
>>languages.
>
>
> Of course they exist, even in statically ("strongly") typed languages.
> The fact that you cannot declare a variable of type "positive even
> integer", and the existence of divide-by-zero runtime errors is proof
> of the presence of type mismatches.
Sorry, I don't follow - I don't see how your examples are related to
type mismatches, much less proof of it. To me, that just looks like
range-checking - something that can be done AFAIK in all languages
(through inbuilt features or setters/getters).
--
Ben M.
> > As Thomas hinted, if the ability to catch some errors at compile time
> > influences the time it takes to create the project, you might be faced
> > with a situation of catching errors at compile time in a project that
> > will not finish on time, or that will be canceled from running out of
> > funding, whereas if you give up on that ability, you might finish the
> > project.
>
>
> I had to read that paragraph several times - I couldn't believe my
> eyes. Are you really suggesting that I can finish my project sooner if
> I chose a compiler that accepts faulty code?
In an exaggerated kind of way, yes, that is the claim. Or to put it
more positively: If you use a more expressive language (which
unfortunately means that you have to give up on some compile-time type
checking of the kind that most current languages enforce), then you
can have more time to finish the project, including sufficient testing
to make sure there are no type errors.
But as was already pointed out, every compiler accepts some faulty
code, or else your language is not universal. You seem to suggest
that only compilers for dynamically typed languages accept faulty
code. That is obviously not the case.
> This is how I read it:
>
> "you might be faced with a situation of a project that will not finish
> on time, whereas if you give up on that ability [catching errors at
> compile time], you might finish the project."
Right. Now, that does not mean that the code you give the compiler IS
NECESSARILY faulty.
> > Of course they exist, even in statically ("strongly") typed
> > languages.
> > The fact that you cannot declare a variable of type "positive even
> > integer", and the existence of divide-by-zero runtime errors is proof
> > of the presence of type mismatches.
>
> Sorry, I don't follow - I don't see how your examples are related to
> type mismatches, much less proof of it. To me, that just looks like
> range-checking - something that can be done AFAIK in all languages
> (through inbuilt features or setters/getters).
The probable reason you do not follow is that you seem to think that
the only valid type systems are those that compilers of current
statically-typed languages have decided to enforce. Range checking is
just type checking that has to be done at runtime even in those
languages.
The classic PHB approach. In typical development code spitting out is
not the long pole. Its just the long pole that the PHB sees.
Testing/debugging usually takes at least as much time as initial
coding. Swapping coding time for testing is rarely a good idea,
because all your talent usually goes into the initial coding time.
Your testers will be less skillfull and will not be able to deal with
these new halting-problem class problems that come from dynamic
typing.
> > Remember this is a narrow point -- and you can't weasle or talk your way
> > around it. Run time dynamic type mismatches are for real in dynamically
> > typed languages; they are very annoying and they don't exist in strongly
> > typed languages.
>
> Of course they exist, even in statically ("strongly") typed languages.
> The fact that you cannot declare a variable of type "positive even
> integer", and the existence of divide-by-zero runtime errors is proof
> of the presence of type mismatches.
You don't know much about C++ do you? Make a positive even integer
class. Define all the operators for it. There you go.
> [...] In order for a type system to be decidable, some approximations have
> to be made.
What are you talking about? The finiteness of the machine factor
leading to "approximations".
> [...] The claim is that, in
> order to be decidable, such approximations necessarily have a negative
> impact on development time and, more generally, on the kind of correct
> programs that can be expressed.
I've tried it both ways. Each has its problems -- both cause program
scaling problems.
> > You can be objective and realize this as the primary fundamental
> > trade off or you can be blinded by typical language adherence fanatacism.
>
> Of course it is a fundamental trade off, but the trade off is not
> between catching all type errors at compile time, or not catching
> them. The trade of is between on the one hand catching some type
> errors at compile time at a the cost of not being able to express some
> correct programs
Excuse me? There you step over the line. What correct program cannot
be expressed in a strongly typed language?
> [...] and of making development time longer,
That point is debatable. Initial coding time may be decreased, but
debugging time may go up. Perl is the extreme example there, just as
C++ is the extreme example on the other end.
> [...] and on the
> other hand of not catching some of those errors (that may not exist
> anyway) in an expressive language that allows very rapid development.
They exist. Believe me. And not having state of the art visual
debuggers kind of hurts the dynamic language world here.
> The classic PHB approach. In typical development code spitting out is
> not the long pole. Its just the long pole that the PHB sees.
> Testing/debugging usually takes at least as much time as initial
> coding. Swapping coding time for testing is rarely a good idea,
With dynamic languages it is common to code "bottom up" and to test as
you go along. Despite this, advocates of such languages claim that
programmer productivity is higher.
> > Of course they exist, even in statically ("strongly") typed languages.
> > The fact that you cannot declare a variable of type "positive even
> > integer", and the existence of divide-by-zero runtime errors is proof
> > of the presence of type mismatches.
>
> You don't know much about C++ do you?
It is true I do not know much about C++.
> Make a positive even integer
> class. Define all the operators for it. There you go.
I realize that is possible. What I had in mind was an arithmetic type
for which the compiler could prove that its value is always greater
then zero.
>
> > [...] In order for a type system to be decidable, some approximations have
> > to be made.
>
> What are you talking about? The finiteness of the machine factor
> leading to "approximations".
I suspect you know what I am talking about, but I'll try it anyway.
I type is a set of values such as "all integers", "all integers
greater than or equal to zero", "all prime numbers", "all bicycles".
"all lists where the first element is a number and the second is a
string".
Because of the universal nature of most programming languages,
determining that the value of a variable is of a certain type is
undecidable. For that reason, current type systems use decidable
approximations of the more general concept of a type, such as
requiring that all elements of a list be of the same type or
making the sqrt function always return a floating point number, even
when given the square of an integer.
> Excuse me? There you step over the line. What correct program cannot
> be expressed in a strongly typed language?
Something like this :
int
fun(int x)
{
return f(x) == 11 ? 22 : "abc";
}
which is correct if f(x) always return 11. Most statically typed
languages will reject such a program because the compiler cannot prove
(because it is undecidable) that f(x) always returns 11.
> > [...] and of making development time longer,
>
> That point is debatable.
Of course it is debatable. I was explaining what is claimed by
advocates of dynamic programming languages. But I have no proof
either way, and I think nobody else does either.
> They exist. Believe me. And not having state of the art visual
> debuggers kind of hurts the dynamic language world here.
Are you saying that no dynamic language has any implementation which
supplies a state-of-the-art visual debugger?
If you create a class that only accepts values > 0 then it can only
contain values > 0. This can be proved at source-code level, and thus at
compile-time.
>>>[...] In order for a type system to be decidable, some approximations have
>>>to be made.
>>
>>What are you talking about? The finiteness of the machine factor
>>leading to "approximations".
>
> I suspect you know what I am talking about, but I'll try it anyway.
>
> I type is a set of values such as "all integers", "all integers
> greater than or equal to zero", "all prime numbers", "all bicycles".
> "all lists where the first element is a number and the second is a
> string".
It would be impossible to foresee and provide inbuilt types for all
possible objects (such as your examples). Instead, a few basic types are
defined (such as integer, floating-point numbers, and characters) and
from these programmers build up whatever other types the situation requires.
Have yourself a peek at type theory:
http://www.cs.cornell.edu/Info/Projects/NuPrl/book/node47.html
> Because of the universal nature of most programming languages,
> determining that the value of a variable is of a certain type is
> undecidable.
A value can belong to infinitely many types. For example, 5.0 is an
integer as well as a floating-point number (and is a real number, a
rational number, a real irrational >=0, etc).
I would be entirely correct to say that 5.0 is a floating-point number,
regardless of whether that type has the smallest cardinality or not.
>>Excuse me? There you step over the line. What correct program cannot
>>be expressed in a strongly typed language?
>
> Something like this :
>
> int
> fun(int x)
> {
> return f(x) == 11 ? 22 : "abc";
> }
>
> which is correct if f(x) always return 11. Most statically typed
> languages will reject such a program because the compiler cannot prove
> (because it is undecidable) that f(x) always returns 11.
Wrong. Statically typed languages reject it because the statement
return f(x) == 11 ? 22 : "abc";
has the possibility of returning a string when you explicitly specified
a return type of int:
int fun(int x)
--
Ben M.
> If you create a class that only accepts values > 0 then it can only
> contain values > 0. This can be proved at source-code level, and thus at
> compile-time.
No it can't in general. The value accepted can be the result of a
function that only returns values > 0, but the compiler might be
unable to prove that.
> >>Excuse me? There you step over the line. What correct program cannot
> >>be expressed in a strongly typed language?
> > Something like this :
> > int
> > fun(int x)
> > {
> > return f(x) == 11 ? 22 : "abc";
> > }
> > which is correct if f(x) always return 11. Most statically typed
> > languages will reject such a program because the compiler cannot prove
> > (because it is undecidable) that f(x) always returns 11.
>
> Wrong. Statically typed languages reject it because the statement
> return f(x) == 11 ? 22 : "abc";
> has the possibility of returning a string when you explicitly specified
> a return type of int:
> int fun(int x)
No, it does not have the possibility of returning a string if f(x)
always returns 11. The point is that to know that, the compiler might
have to solve the halting problem. To avoid that, the type system
uses a decidable approximation that (in this case incorrectly) assumes
that f(x) can return values other than 11.