C++ sucks for games

G

Gerry Quinn

C++ method call: foo.munge(bar);
Equivalent Lisp call: (munge foo bar)

The C++ function specializes on the first argument, that is to say "foo".
The language doesn't support multi-methods, so if you want to specialize on
bar as well, you'll have to do it by hande.

In other words, the statement "The body of a method in Lisp is not in
some special scope in which the symbols denoting the variables of a
class are magically bound to those slots." is garbage because it implies
the existence of a language feature in C++ that doesn't exist. [And
isn't needed.]

- Gerry Quinn
 
G

Gerry Quinn

It sounds like you're claiming that encapsulation is a integral part of
"object orientation". This comes up a lot in discussions of CLOS.

That's part of it. But my main point is that "object orientation" means
more than "allowing objects". You have to be oriented towards classes.
If you are oriented towards functions, or macros, you are not object-
oriented.

- Gerry Quinn
 
G

Gerry Quinn

No, I am not manipulating strings or data, I am manipulating code.
Although C macros work on strings, Lisp macros do not, despite the
fact that the Lisp source code does reside in a file. This is because
the Lisp reader parses the expressions for me and hands my macro a
data structure. This particular example is rather simple, but there
are plenty of other uses of macros in which a code 'tree' is
traversed, examined and transformed. This is far more powerful than
simple string substitution as C has.

There is no firm dividing line between data and code. Data is
structured code. Code is executable data. Your first example looks
more like data to me, your second looks more like self-modifying code.
But in any case, this kind of stuff can be dealt with in any high-level
language.
However, there are those who feel that defining new syntax is too
powerful a feature for a language, they should stay clear of this sort
of thing.

And their are those who are more interested in 'clever' programming than
in producing useful software - they will doubtless love it.

- Gerry Quinn
 
G

Gerry Quinn

newsmailcomp5 said:
You are describing a program-generating program as self-modifying.

Not unless the output of the generated program is an expected part of
output of the original program.
Using your discription every compiler which can execute its generated
code would be self-modifying (like a Common Lisp compiler). I think

Not if there is a division between the outputs, as there is in this
example. A compiler is not self-modifying code. It modifies the code
of a distinctly different program.
many people (including myself) will disagree with you, e.g. see:
http://en.wikipedia.org/wiki/Self_modifying_code
I have only heard the term self-modifying in the context where the
program will modify the some of its following instructions. The
purpose is to implement adaptive algorithms and to save program
memory. Self modifying code has been known to cause problems with the
CPU instruction cache. However, self-modifying programs are not so
common since memory is cheap and almost all CPU's have instruction
caches where one would like to keep a high hit-ration as possible.

Surely the insistence that there must be some original code to be
written over is purely arbitrary and irrelevant? When code generated by
the program is executed, it is completely irrelevant whether it was
written in a portion of memory that contained some original source.

// Program A:

PUT_CODE_HERE:
NOP
NOP
NOP
NOP
GenerateCodeAt( PUT_CODE_HERE );
ExecuteCodeAt( PUT_CODE_HERE );

// Program B:

void* putCodeHere = (void*)( new opSizeItem[ 4 ] );
GenerateCodeAt( putCodeHere );
ExecuteCodeAt( putCodeHere );

They are both self-modifying, aren't they?


- Gerry Quinn
 
G

Gerry Quinn

Oh really? So you shouldn't use imperative code in an OO application?
Interesting.

You should write it in its place, and not elsewhere.
Yes, we're not true cultists, sorry. We don't follow the One True Way of
typopace (type/scope/namespace) object orientation in every line of our
code. We'd rather write each section of code in a way that allows that
code to make as much sense and be as maintainable as possible. We're
horrible people.

You can be oriented to objects, or oriented to something other than
objects. Your choice. What you can't do is say "here's the OO language
feature, we're not going to use it much but just because it's there our
programs must be object-oriented."

- Gerry Quinn
 
G

Greg Menke

Gerry Quinn said:
That's part of it. But my main point is that "object orientation" means
more than "allowing objects". You have to be oriented towards classes.

If you are oriented towards functions, or macros, you are not object-
oriented.

This statement is confusing to me- C++ is plenty oriented towards all
those things. As is every other language that claims to be
"object-oriented"- leaving aside a precise definition of that for a
moment. Lisp's model of datatypes and code makes everything a
first-class object, which seems to me to make it more thoroughly
oriented towards objects than something like C++.

Gregm
 
P

Pascal Costanza

Gerry said:
But my main point is that "object orientation" means
more than "allowing objects". You have to be oriented towards classes.
If you are oriented towards functions, or macros, you are not object-
oriented.

If you are oriented towards classes, you are class-oriented, not
object-oriented. (I am only half-joking.)

In Common Lisp, functions, macros, classes etc., are also objects. Go
figure. ;)


Pascal
 
K

Kenneth Tilton

Gerry Quinn said:
And their are those who are more interested in 'clever' programming than
in producing useful software - they will doubtless love it.

You cannot dismiss a powerful feature of a programming language by
disparaging the motivations of those who use the feature. The feature is
powerful, and that is that.

As for those who use the feature, it is always about producing software.
Great athletes do not make fancy moves to show off*, they do it to fake
the fullback out of his jockstrap on their way to the goal.

If you check that Lisp newbie survey, you will find a whole category for
folks who, before they discovered Lisp, had crudely re-invented some
unusual capability of Lisp, precisely because they were reaching for the
expressive power it promised.

Does every programmer feel held back by Java/C++/whatever? No. We once
discovered a consultant had cut and pasted fifteen lines of Vax Basic
twenty times; changing each time the three variables to make the code
work in the new context, rather than create a function with three
parameters.

But any good programmer is certainly held back by lesser languages. I
found Lisp because, well, there is another category in the survey, for
those who went on an active search for a better way before they even
knew there was a better way, simply because they sensed that they were
being held back by their languages.

kenny
 
P

Philippa Cowderoy

That's part of it. But my main point is that "object orientation" means
more than "allowing objects". You have to be oriented towards classes.

There are a number of classless OO languages whose creators would beg to
differ.
 
P

Philippa Cowderoy

You can be oriented to objects, or oriented to something other than
objects. Your choice. What you can't do is say "here's the OO language
feature, we're not going to use it much but just because it's there our
programs must be object-oriented."

Nobody's said that. They've said the /language/ is OO. C++ doesn't have
much of a better claim beyond the fact the type system needed explicit
extension to add OO to it.
 
J

Jon Boone

Thanks again for the information.
My habit is to start a class definition with:

class MyClass
{
public:
// member data
protected:
// member data
public:
// member functions
protected:
// member functions
};

(only without the comments). Ideally the first category should be
empty, and typically the fourth is biggest. Often I move stuff around
during development.

Very interesting. Thanks for sharing this information.

In CLOS, as others have already pointed out, you'd make the
distinction as follows (code below the body of the text):

1. define a package
2. within the package scope, define the class

*this is basic definition stuff*

3. export from the package those things that you want to have
visible from the outside.

*this adds public status* - for use by folks outside of the
package - but is only a _suggestion_ at this point

4. if you want to completely remove access to a symbol, unintern it
after the methods that use it are defined (obviously, it can't be
:exported either)

*this adds protected status wrt methods defined while the symbol
was interned* - in other words, they will be able to access it,
but no one else will

*this adds private status wrt methods defined after the symbol
has been uninterned* - all methods after the (unintern ...), as
well as those external to the package will not be able to use it


I can't think of how to trivially support the friend semantics.
One minor dilemma I often encounter is whether to use accessor
functions to get at protected data. Ideally, I suspect, a class
should have its own internal accessors, but that is too much
typing, so it remains conceptual! I do sometimes implement it in a
small way, i.e. with a public const accessor, and a protected
non-const accessor/mutator.

In CLOS, you can get at slots by using (slot-value obj 'slot-name)
Since this returns a *place*, you can (setf ..) it for a mutator.
If you want, you can specify the name of an :accessor (or a :reader
/ :writer) function that CLOS will create to hide the (slot-value
..) bit.

(defpackage "my-package"
:)use "COMMON-LISP")
:)export my-package::person))

(in-package "my-package")

(defclass person ()
((name :accessor person-name :initarg :person-name :initform "Bonzo")
(age :writer person-age :initarg :person-age :initform 15)
(height :reader person-height :initarg :person-height :initform 70)))

(defclass person2 (person)
((weight :initarg :person-weight :initform 180)))

(defmethod weigh-em ((the-victim person2))
(slot-value the-victim 'weight))

(let ((bonzo (make-instance 'person2)))
(format t "~A is ~A pounds.~%"
(person-name bonzo)
(weigh-em bonzo)))

(unintern 'weight)

(let ((bob (make-instance 'person2 :person-name "Bob" :person-weight 150)))
(format t "~A is ~A pounds.~%"
(person-name bob)
(weigh-em bob))
(format t "~A is ~A pounds.~%"
(person-name bob)
(slot-value bob 'weight)))

-------------------------------------------------------------
Upon loading, this yields:

CL-USER 1 > (load "~/Desktop/person.lisp")
; Loading text file /Users/ipmonger/Desktop/person.lisp
Bonzo is 180 pounds.
Bob is 150 pounds.

Error: The slot WEIGHT is missing from #<PERSON2 100B635B> (of class #<STANDARD-CLASS PERSON2 100AFD83>), when reading the value.
1 (continue) Try loading ~/Desktop/person.lisp again.
2 Give up loading ~/Desktop/person.lisp.
3 Try loading another file instead of ~/Desktop/person.lisp.
4 (abort) Return to level 0.
5 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed, or :? for other options

my-package 3 : 1 > :c 5


-------------------------------------------------------------

At the REPL you'd do (assuming it's already loaded):

CL-USER 4 > (use-package "my-package")
T

CL-USER 5 > (make-instance 'person)
#<PERSON 100D1AE3>

CL-USER 6 > (make-instance 'person2)

Error: PERSON2 is not the name of a class
1 (continue) Try finding the class PERSON2 again
2 (abort) Return to level 0.
3 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed, or :? for other options

CL-USER 7 : 1 > :c 3
 
G

Gerry Quinn

Most likely you wouldn't, but if you wanted it, that's how it would
look like. Maybe I should have just written f(a, b) / a.f(b) /
T::f(a, b), but I kind of wanted to go with the "rabbit jump" thing.

My diagnosis is that you don't actually know C++. Your function
"Rabbit::jump(rabbit, 3)" makes no sense whatsoever. If the rabbit is
being told to jump, it doesn't need to be told it's a rabbit. And if it
is jumping over another rabbit, the other rabbit should be passed as a
reference, not a copy.

- Gerry Quinn
 
G

Gerry Quinn

Gerry Quinn wrote:
There's an advantage of Lisp right there, then. It's very, very easy to
define accessor methods (or separate reader and writer methods, if that
fits better), and if you later change the contents of the slot (or remove
it), you can just remove the accessor declaration and define your own to
fit the new slot.

It's what I suspect you wanted to do, and the compiler is smart enough that
accessor calls don't neccessarily involve function calls, especially if you
use type declarations.

No, it's pretty easy in C++ too, just a bit of a chore. I doubt there
is any real difference.

- Gerry Quinn
 
G

Gerry Quinn

But any good programmer is certainly held back by lesser languages. I
found Lisp because, well, there is another category in the survey, for
those who went on an active search for a better way before they even
knew there was a better way, simply because they sensed that they were
being held back by their languages.

And if Lisp programmers were demonstrably more productive and effective,
I'd take such claims seriously. As, more importantly, would those who
tend to hire programmers.

[Likewise for 'agile' programmers, or 'test-driven' programmers, or
'generic' programmers, or any other of the many varieties of silver
bullet programmers.]

- Gerry Quinn
 
G

Gerry Quinn

Nobody's said that. They've said the /language/ is OO. C++ doesn't have
much of a better claim beyond the fact the type system needed explicit
extension to add OO to it.

The other thing is that people actually DO program C++ in an OO fashion.
Not always, but often enough. Correct me if I'm wrong, but Lisp-ers
give a distinct impression of preferring generic programming.

- Gerry Quinn
 
P

Philippa Cowderoy

The other thing is that people actually DO program C++ in an OO fashion.
Not always, but often enough. Correct me if I'm wrong, but Lisp-ers
give a distinct impression of preferring generic programming.

IM(limited)E, lispers code however they feel is best for the task.
Personally (as a non-lisper but with a related mindset) I often end up
with designs that look like OO designs in the large, I just don't find
traditional OO tools to be a useful means of doing programming in the
small (including the higher-level bits of code). Actually, I'll go a step
further - I don't find traditional OO tools to be a useful means of
analysing much (of my) programming in the small. I find they tend to offer
extensibility in all the wrong places, for example.

One thing I /do/ make a lot of use of is (sub)systems communicating in a
specified language. In fact, a current project has a setup that looks
suspiciously like threads-as-objects for pretty much that reason. Many of
my preferred constructs end up looking pretty close to the duals of OO
constructs, for that matter. Which makes a lot of sense if the traditional
OO constructs seem to be getting everything backwards.
 
G

Gerry Quinn

IM(limited)E, lispers code however they feel is best for the task.
Personally (as a non-lisper but with a related mindset) I often end up
with designs that look like OO designs in the large, I just don't find
traditional OO tools to be a useful means of doing programming in the
small (including the higher-level bits of code). Actually, I'll go a step
further - I don't find traditional OO tools to be a useful means of
analysing much (of my) programming in the small. I find they tend to offer
extensibility in all the wrong places, for example.
One thing I /do/ make a lot of use of is (sub)systems communicating in a
specified language. In fact, a current project has a setup that looks
suspiciously like threads-as-objects for pretty much that reason. Many of
my preferred constructs end up looking pretty close to the duals of OO
constructs, for that matter. Which makes a lot of sense if the traditional
OO constructs seem to be getting everything backwards.

'Dual' is a word that has occurred to me in this context. Certainly we
can imagine (broadly) a scheme in which generic functions act as a dual
for classes in OO programming.

But the Lisp-ers on this thread seem to be heading for the notion of
making everything first-class. Which can only be its own dual.

Of course I have sub-systems that communicate too, but they are objects.
Possibly the languages they use tend to be less sophisticated, but they
serve my purposes well enough.

- Gerry Quinn
 
K

Kenneth Tilton

Gerry Quinn said:
And if Lisp programmers were demonstrably more productive and effective,
I'd take such claims seriously.

Claims? What claims? Those are good programmers who answered my survey
by saying they went looking for a better way and found it. Do you think
that survey is a mass conspiracy to promote Lisp? If so, why have C++
guru's joined the conspiracy?:

http://www.mindview.net/WebLog/log-0025

Titled: "Thinking About Computing -- Bruce Eckel's Web Log"

Highlight film: "In recent years my primary interest has become
programmer productivity. Programmer cycles are expensive, CPU cycles are
cheap, and I believe that we should no longer pay for the latter with
the former.

How can we get maximal leverage on the problems we try to solve?
Whenever a new tool (especially a programming language) appears, that
tool provides some kind of abstraction that may or may not hide needless
detail from the programmer. I have come, however, to always be on watch
for a Faustian bargain, especially one that tries to convince me to
ignore all the hoops I must jump through in order to achieve this
abstraction. Perl is an excellent example of this...

"....This began with a 2-month love affair with Perl, which gave me
productivity through rapid turnaround. (The affair was terminated
because of Perl's reprehensible treatment of references and classes...

" After I had worked with Python (free at www.Python.org) for awhile a
language which can build large, complex systems I began noticing that
despite an apparent carelessness about type checking, Python programs
seemed to work quite well without much effort, and without the kinds of
problems you would expect from a language that doesn't have the strong,
static type checking that we've all come to "know" is the only correct
way of solving the programming problem.

" This became a puzzle to me: if strong static type checking is so
important, why are people able to build big, complex Python programs
(with much shorter time and effort than the strong static counterparts)
without the disaster that I was so sure would ensue?

" This shook my unquestioning acceptance of strong type checking
(acquired when moving from C to C++, where the improvement was
dramatic)...

" But deciding that [Java's] checked exceptions seem like more trouble
than they're worth (the checking, not the exception. I believe that a
single, consistent error reporting mechanism is essential) did not
answer the question "why does Python work so well, when conventional
wisdom says it should produce massive failures?"

The recurring theme here is much greater productivity (even in Perl)
when one can shed the syntactic strait jackets and find some other way
to get to program correctness. And that is what I am talking about when
I say some folks found Lisp because they knew there had to be a better
way, that they were being held back.

Gerry, the simple fact is that you would be much more productive in Lisp
than you are in C++. Python, too, but that is still pretty slow and a
bit of a hack as languages go. Here is another C++ guru:

http://www.artima.com/weblogs/viewpost.jsp?thread=4639

I will let Eckels summarize what you will find there (watch for the
phrase "could be much more productive"):

"Robert Martin is one of the long-time inhabitants of the C++ community.
He's written books and articles, consulted, taught, etc. A pretty
hard-core, strong- static type checking guy. Or so I would have thought,
until I read this weblog entry. Robert came to more or less the same
conclusion I have, but he did so by becoming "test infected" first, then
realizing that the compiler was just one (incomplete) form of testing,
then understanding that a weakly-typed language could be much more
productive but create programs that are just as robust as those written
in strongly-typed languages, by providing adequate testing."

As for how crazy this all sounds:

" Of course, Martin also recieved [sic] the usual "how can you possibly
think this?" comments. Which is the very question that lead [sic] me to
begin struggling with the strong/weak typing concepts in the first
place. And certainly both of us began as strong static type checking
advocates. It's interesting that it takes an earth-shaking experience
like becoming test-infected or learning a different kind of language to
cause a re-evaluation of beliefs."

kenny
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,667
Latest member
DaniloB294

Latest Threads

Top