473,529 Members | 3,568 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C++ sucks for games

Hey

Recently, I researched using C++ for game programming and here is what
I found:

C++ game developers spend a lot of their time debugging corrupted
memory. Few, if any, compilers offer completely safe modes.

Unsurprisingly, there is a very high failure rate among projects using
C++ for modern game development.

You can not even change function definitions while the program is
running and see the effects live (the ultimate debugging tool).

Alternatively, you can't execute a small portion of the program
without compiling and linking the whole thing, then bringing your game
into a specific state where your portion of the code is being executed.

The static type system locks you into a certain design, and you can't
*test* new ideas, when they come to you, without redesigning your
whole class hierarchy.

C++ is so inflexible, even those who do use it for games, have to
write their game logic in some other language (usually very slow,
inexpressive and still garbage collected). They also have to interface
the two languages.

C++ lacks higher-order functions. Function objects emulate them
poorly, are slow and a pain to use. Additionally, C++ type system does
not work well with function objects.

C++ programs can not "think" of new code at run-time, and plug that
new code into themselves in compiled form. Not easily, anyway.

C++ coding feels very repetitive, for example, when writing class
accessors, you often have to write const and non-const methods with
completely identical function bodies. Just look at STL.

When programming in C++ you feel like a blind person trying to draw
something. You don't _see_ the data structures that your procedures
will operate on. Lisp programming is much more visual.

Constructors and smart pointers make it hard to tell cheap operations
from expensive ones.

C++ lacks automatic memory management and so it encourages copying
objects around to make manual memory management manageable.
Reference-counting schemes are usually slower than modern garbage
collectors and also less general.

Most important, C++ syntax is irregular, and you often find yourself
typing repetitive patterns again and again - a task easily automated
in languages with simpler syntax. There are even books on C++
patterns, and some C++ experts take pride in being able to execute
those patterns with computer-like precision - something a computer
should be doing to begin with.

C++ programs are slow: even though the compilers are good at
micro-optimizing the code, programmers waste their time writing
repetitive patterns in C++ and debugging memory corruption instead of
looking for better algorithms that are far more important for speed
than silly micro-optimizations.

It's hard to find good programmers for C++ projects, because most of
the good programmers graduated to languages like Lisp or avoided C++
altogether. C++ attracts unimaginative fellows with herd mentality.
For creative projects, you want to avoid them like a plague.

It is my opinion that all of the above makes C++ a very bad choice for
commercial game development.
Jul 22 '05
761 28005
chris <ca*@cs.york.ac.uk> writes:
Maahes wrote:
Ordinary function call:
C++: jump(rabbit, 3)
Lisp: (jump rabbit 3)

C: rabbit_jump(rabbit, 3)
Method call:
C++: rabbit.jump(3)
Lisp: (jump rabbit 3)

C: rabbit_jump(rabbit, 3)
Class method call:
C++: Rabbit::jump(rabbit, 3)
Lisp: (jump rabbit 3)

What is this? are you saying that the class rabbit has a static member
function that takes a rabbit and a 3? I'm not sure why you would want
such a thing..

Also are you saying in lisp when I write (jump rabbit 3) it's
impossible to tell if I'm calling a member function of Rabbit that
takes a single parameter, or a general function that takes two
parameters? Is that really an advantage?


The function 'jump' is generic, for each class that cares about having
an action for jump, the programmer defines a function named that with
the parameters specialized accordingly so Lisp will call the proper
one. Its analagous to function/operator overloading in C++. In
general, you cannot have regular functions named the same as generic
functions, so there is no confusion about which function is going to
be called.

There are no "member functions" in Lisp, all functions exist outside
the definition of classes. That will sound strange to people only
familiar with the C++ style of OO, but it works very nicely once you
get used to it.

Gregm
Jul 22 '05 #351
The big lie with C++ is that the access specifiers actually enforce
access- its trivial to typecast an instance's pointer and arbitrarily
manipulate the object's members. Its more correct to say the access
specifiers provide some naive compile-time limits on how instances of
a class can be manipulated. If you need to protect your object
internals from other programmers, I think you'll need a more robust
technique.


Next you'll be complaining that TV isn't water-proof.

Putting stuff in the "private" or "protected" section is purely for ease of
use - it's *not* intended to "protect" the internals of the class.
-JKop
Jul 22 '05 #352
Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
In article <m3************@jcooper02.sagepub.com>, jo***@mail.com
says...
Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
I disagree - it is in fact rare for code to be changed per se. What
would be the point in writing code whose only purpose is to be written
over? Whether original code is erased or not is completely irrelevant
to the issue of whether code is self-modifying. The *program* is still
self-modifying.
Because I might get tired of typing something like:

(let ((addr-1 (get-html-value "addr-1"))
(addr-2 (get-html-value "addr-2"))

[--]
so I write a macro to transform some code and now I can
write thusly:

(with-form-values (addr-1 addr-2 city state zip (name "username")
(other-value "other" some-function))
...some code...)

which is transformed into the top code.

Now I have eliminated a source of typos and made the code much more
readable. Note that a function will not work for this because I am
establishing lexical bindings for "...some code..."


Sure, that's a reason why you might want to use this. And I think, if
you are making the point that this should not be called 'self-modifying
code' in the proper sense, you do have a point - you are manipulating
strings in a way that might be handled elsewise in another language. If
you look at the above, it's really data you are manipulating, not code.


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.

Another example:

(ITER (WITH specials = (get-sorted-specials unsorted-list))
(WITH result = '())
(FOR (sym . str) IN specials)
(FOR char0 = (char str 0))
(FOR char1 = (and (= 2 (length str)) (char str 1)))
(FOR lchar0 PREVIOUS char0 INITIALLY nil)
(FOR pair = (assoc char0 result :test #'char=))
(if (null pair)
(push (setf pair (cons char0 nil)) result)
(case lchar0
(#\a (COLLECT char0 into a-list))
(#\b (COLLECT char0 into b-list))))
(FOR new = (cons char1 sym))
(push new (cdr pair))
(FINALLY (return result)))

ITER is a macro, and it does not get a big string to process. It gets
a forms (fyi a form is either an atom or a list of atoms and/or
forms), which it examines and transforms to build the resulting code.
Here, some of those forms contain symbols defined by ITER, some are
'ordinary' lisp. The ITER symbols can be anywhere in the code block,
ITER will find them and handle them properly in the result. I
capitalized them above. Notice the COLLECT words down in the IF's
else form. Lisp macros are so powerful because the macro operates on
the parse tree of the code. It is trivial for ITER to locate the
COLLECT words and insert the code for them.

Again I also want to stress that I can't use a function to do this type
of abstraction; I want all of the resulting code (including transformed
bits and other bits just used as is) to be in the same lexical scope.

Below is what the ITER macro expands into for the above code. I show
you all this to give you an idea of the amazing amount of crap that
can be cut out of your programs if you use macros to abstract away the
scaffolding.
(LET* ((SPECIALS (GET-SORTED-SPECIALS UNSORTED-LIST))
(RESULT 'NIL)
(#:LIST36 NIL)
(SYM NIL)
(STR NIL)
(CHAR0 NIL)
(CHAR1 NIL)
(LCHAR0 NIL)
(PAIR NIL)
(A-LIST NIL)
(#:END-POINTER37 NIL)
(#:TEMP38 NIL)
(B-LIST NIL)
(#:END-POINTER39 NIL)
(NEW NIL)
(#:POST-SAVE-CHAR0-40 NIL))
(BLOCK NIL
(TAGBODY
(SETQ #:LIST36 SPECIALS)
(SETQ LCHAR0 NIL)
(SETQ #:POST-SAVE-CHAR0-40 NIL)
LOOP-TOP-NIL
(IF (ATOM #:LIST36) (GO LOOP-END-NIL))
(LET ((#:G3840 (CAR #:LIST36)))
(SETQ SYM (CAR #:G3840))
(SETQ STR (CDR #:G3840))
#:G3840)
(SETQ #:LIST36 (CDR #:LIST36))
(PROGN (SETQ LCHAR0 #:POST-SAVE-CHAR0-40))
(SETQ CHAR0 (CHAR STR 0))
(PROGN (SETQ #:POST-SAVE-CHAR0-40 CHAR0))
(SETQ CHAR1 (IF (= 2 (LENGTH STR)) (CHAR STR 1)))
(SETQ PAIR (ASSOC CHAR0 RESULT :TEST #'CHAR=))
(IF (NULL PAIR)
(SETQ RESULT (CONS (SETQ PAIR (CONS CHAR0 NIL)) RESULT))
(LET ((#:G3841 LCHAR0))
#:G3841
(IF (EQL #:G3841 '#\a)
(PROGN
NIL
(PROGN
(SETQ #:TEMP38 (LIST CHAR0))
(SETQ #:END-POINTER37
(IF A-LIST
(SETF (CDR #:END-POINTER37) #:TEMP38)
(SETQ A-LIST #:TEMP38)))
A-LIST))
(IF (EQL #:G3841 '#\b)
(PROGN
NIL
(PROGN
(SETQ #:TEMP38 (LIST CHAR0))
(SETQ #:END-POINTER39
(IF B-LIST
(SETF (CDR #:END-POINTER39) #:TEMP38)
(SETQ B-LIST #:TEMP38)))
B-LIST))))))
(SETQ NEW (CONS CHAR1 SYM))
(LET* ((#:G3844 NEW)
(#:G3843 PAIR)
(#:G3842 (CONS #:G3844 (CDR #:G3843))))
(COMMON-LISP::%RPLACD #:G3843 #:G3842))
(GO LOOP-TOP-NIL)
LOOP-END-NIL
(RETURN RESULT))
NIL))

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.

--
Jock Cooper
www.fractal-recursions.com


Downloaded your 'UltraFractal'. I was curious to see if it was written
in Lisp, but it doesn't appear so. [Not that that invalidates anything
you say.]


Actually Ultra Fractal was written by Frederik Slijkerman and is available
(as you must have found) at www.ultrafractal.com. I just used it to create
the various images and animations on my site. I believe UF is written in
Delphi.
Jul 22 '05 #353
Maahes wrote:
So programs = algorithms + bookkeeping. Outsource as much of the
bookkeeping as you can, I say!

Oh god, its almost reads like your saying Lisp requires less commenting :)

I can't possibly mean this, so I'm sure I've misinferred here..
If anything, Lisp looks more like assembly, where you would expect a lot of
commenting on every single line...


I just ran a quick comment count on the same code that I used elsewhere
in this thread (CMUCL's source tree in the Lisp corner, VNC in the other
corner). Lisp weighs in at:

Characters: total 16061565, comment 3020763 (18.8%)

versus

Characters: total 9947254, comment 2331753 (23.4%)

25% more flab on the challenger.
--
Cameron MacKinnon
Toronto, Canada

Jul 22 '05 #354
Cameron MacKinnon <cm********@clearspot.net> wrote in message news:<qI********************@golden.net>...

[ ... ]
Why bother arguing about shift/reduce and reduce/reduce conflicts and
the de facto and de jure meanings of e.g. a[x+++y] = x+++y; - every
language has a wart or two in the corner cases, and C defenders are just
going to reply that such things are bad style and not done anyway.
Those weren't the cases I was talking about -- in fact, none of what
you've cited above is really an ambiguity either.

There are, however, ambiguities to be found, such as:

a b(c);

In C++, this could be either a definition of b as an object of type a,
with c as an initializer, OR it could be a declaration of b as a
function that returns an a and takes a c as a parameter. There are a
number of other examples along this line, but (at least from a
viewpoint of pure syntax) these are real ambiguities. C++ has a fairly
simple rule about how to deal with all of them, but even though the
rule itself is simple, implementing it is anything but, and is
semantic, not syntactical -- the syntax itself really IS ambiguous.

[ ... ]
Say, speaking of citing, don't you still owe us one from your claim that
"[t]ests have repeatedly shown that C is far more readable than Lisp."


Where do you find a mention (by anybody) of citing anything?

In any case, I never said or implied that I'd provide citations. I
said those were results from tests that I conducted. I conducted the
tests for a (temporary) employer, so I'm pretty sure I couldn't
(legally) publish the results without their permission. Since that
company went under in the .com bust I'm not even sure whose permission
I'd need at this point.

In the end, I'm reasonably certain other tests have been done, but if
you want them, you'll have to find them yourself -- until or unless
there's some change in Lisp syntax that invalidates what I've already
done, I'm not much more interested in searching for such results than
I am in searching for new proofs that the world is round.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 22 '05 #355
mikel <mi***@evins.net> writes:
Is that really an advantage?


I think so; generic functions and ordinary functions are both appliable
objects that take arguments; I don't see any special reason why they should
have different syntax. Macro calls and uses of other special operators also
use the same general syntax:

(operator arg1 arg2 ... argn)


The reason to have a difference syntax is to better model how humans think in
certain situations.

I have used Lisp's syntax. It is nicely general. Ada has a similar syntax for
OO method calls.

The problem is that very often I want to think about asking individual objects
to do certain behaviour. Saying:

obj.doSomething(withData)

clarifies that better than:

doSomething(obj, withData)

It is a mental organization thing.

Essentially, class scopes can indeed be useful.

Consider a record or struct syntax in the standard langages: data.field

Mind you, Lisp is consistent here too, calling a field accessor function/macro
on the data.

There is no question that Lisp's approach is more general, especially given
generic methods. Sometimes, the class scope/focus of things is useful.

E.g. in Lisp or scheme, something like:

(obj doSomething withData)

Don't know how to do that with macros, however. The approaches I have seen
usually force things like

(obj 'doSomething withData)

with the implied inefficient dynamic lookup of methods.

--
Cheers, The Rhythm is around me,
The Rhythm has control.
Ray Blaak The Rhythm is inside me,
rA******@STRIPCAPStelus.net The Rhythm has my soul.
Jul 22 '05 #356
Ray Blaak wrote:
mikel <mi***@evins.net> writes:
Is that really an advantage?
I think so; generic functions and ordinary functions are both appliable
objects that take arguments; I don't see any special reason why they should
have different syntax. Macro calls and uses of other special operators also
use the same general syntax:

(operator arg1 arg2 ... argn)

The reason to have a difference syntax is to better model how humans think in
certain situations.

I have used Lisp's syntax. It is nicely general. Ada has a similar syntax for
OO method calls.

The problem is that very often I want to think about asking individual objects
to do certain behaviour. Saying:

obj.doSomething(withData)

clarifies that better than:

doSomething(obj, withData)

It is a mental organization thing.


Fair enough. This is, however, just syntactic sugar, and if you really
want it you can build it with a macro. The Lispy result might look like,
for example,

(send obj do-something with-data)

Because the macro gets expanded to

(do-something obj with-data)

there is no difference, apart from the differenet surface syntax, which
is provided because the user happens to like it for this case.

As an aside, Dylan began as a Lisp dialect and later evolved an infix
syntax; for a while it had both syntaxes, and the syntax

obj.doSomething(withData)

was exactly equivalent to

doSomething(obj,withData)

or

(doSomething obj withData)

Indeed, it was fully general and worked the other way; anything that
could be called like this:

foo(bar)

could also be called like this:
bar.foo()

Essentially, class scopes can indeed be useful.


That might be true, but doesn't mean the same thing. Assuming that by
'class scopes' you mean that you want objects that contain methods as
data elements, you can do that in Lisp as well, in a couple of different
ways, but if you want a comprehensive system of function-calling,
inheritance, and the like that resembles a Smalltalk-like object system
or a C++-like object system, then you have to do a little more work
defining metaclasses and method combinations and so on.

Jul 22 '05 #357
Ray Blaak <rA******@STRIPCAPStelus.net> writes:
Sometimes, the class scope/focus of things is useful.

E.g. in Lisp or scheme, something like:

(obj doSomething withData)


[untested]

(defmacro with-svo (var &body body)
`(macrolet ((,var (gf-name &rest args)
`(,gf-name ,',var ,@args)))
,@body))

(with-svo (obj)
(obj doSomething withData))

this will only "work" when you work in your own world because the
entire clos culture thinks differently and you'll have issues (none of
them technical) when working with others.

p.s. - the above is only a short read macro away from:

(enable-svo-syntax)

[obj.doSomething withData]

--
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
Jul 22 '05 #358
JKop <NU**@NULL.NULL> writes:
The big lie with C++ is that the access specifiers actually enforce
access- its trivial to typecast an instance's pointer and arbitrarily
manipulate the object's members. Its more correct to say the access
specifiers provide some naive compile-time limits on how instances of
a class can be manipulated. If you need to protect your object
internals from other programmers, I think you'll need a more robust
technique.


Next you'll be complaining that TV isn't water-proof.

Putting stuff in the "private" or "protected" section is purely for ease of
use - it's *not* intended to "protect" the internals of the class.


Oh I'm not complaining- its just how C++ is. My point is that access
specifiers are essentially no more than a suggestion to the programmer
about how an interface should be used.

But I don't think ease has anything to do with it. There is a
suggestion of access enforcement via the specifiers that is not backed
up by other parts of the language, and this is not usually discussed
alongside the merits of specifiers.

Gregm

Jul 22 '05 #359
In article <41********@duster.adelaide.on.net>,
"Maahes" <ma****@internode.on.net> wrote:
What is it that you use access specifiers for?
For protecting your implementation from the other programmers.
If you don't protect your variables and strictly define your interfaces, and
limit their power, you'll find the other programmers will completely
misusing your code. Then when you go to rewrite it to provide new features,
you'll find you can't because all the variables you want to trash are being
used in critical parts of multiple projects.


Okay, so access specifiers are for protection.

In article <up*******************@news.indigo.ie>,
JKop <NU**@NULL.NULL> wrote:
Putting stuff in the "private" or "protected" section is purely for ease of
use - it's *not* intended to "protect" the internals of the class.


Okay, so access specifiers are *not* for protection.

What are access specifiers for again?
Jul 22 '05 #360
rmagere wrote:
"Pascal Bourguignon" <sp**@mouse-potato.com> wrote in message
news:87************@naiad.informatimago.com...
"Maahes" <ma****@internode.on.net> writes:
A + (B * C / D) - (E * F)

so that there is no misunderstanding of your code. Certainly not needed,
but
makes it easier to read at a glance, which is what I would say is the
highest priority when designing a language to be used in a team
environment..
Not sufficient:

1 + (2 * 2 / 4) - (1 * 1)

Do you expect: 1 or 0 ?
<source language=c>
1 + (2 * (2 / 4)) - (1 * 1), /* ==> 0 */
1 + ((2 * 2) / 4) - (1 * 1) /* ==> 1 */
</source>


I am sorry I am thick but how do you get 0?
1 + (2 * (2/4)) - (1 * 1) ==>


2/4 is integer division (so you would expect 0 as result) 1 + (2 * 0.5) - 1 ==>
1+(2*0)-1 ==> 1 + 1 - 1 ==>
1 + 0 - 1 ==>
1


0

hs
Jul 22 '05 #361
In article <uf***********@STRIPCAPStelus.net>,
Ray Blaak <rA******@STRIPCAPStelus.net> wrote:
mikel <mi***@evins.net> writes:
Is that really an advantage?
I think so; generic functions and ordinary functions are both appliable
objects that take arguments; I don't see any special reason why they should
have different syntax. Macro calls and uses of other special operators also
use the same general syntax:

(operator arg1 arg2 ... argn)

The reason to have a difference syntax is to better model how humans think in
certain situations.
[Let me return to this below.]
It is a mental organization thing.

Essentially, class scopes can indeed be useful.
Perhaps. I guess I believe you. Okay, class scope can sometimes
be useful.
Mind you, Lisp is consistent here too, calling a field accessor function/macro
on the data.

There is no question that Lisp's approach is more general, especially given
generic methods.


But what you (seem to) give up when you accept class scope is this
beautiful generality.

You claimed above that class scope models how humans think in certain
situations. Frankly, as a cognitive psychologist, I'm finding it hard
to think of data that support (or refute) your claim.

My intuition (and it is a just an intuition, not an established fact
about human cognition) is that taking a consistent, parsimonious
approach to function/method calls brings an increased economy to the
comprehension of Lisp code. Programming languages are formalisms, and
those who uses formalisms (e.g., mathematicians) have historically
worked awfully hard to eliminate special cases and unnecessary
redundancies.
Jul 22 '05 #362
In article <MP***********************@news.indigo.ie>,
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote:
Let me point out something. If you do twenty projects in this fashion
you will have twenty new languages. Surely that vitiates any benefit of
a particular language, even if it is marginally better suited to the
problem domain of a given project?


On one hand, I agree with you. But all significant programs
develop their own "vocabulary," one that matches the domain
at hand. The hard part about understanding a large program
is rarely mastering the details of the language in which it
is written. Rather, it is understanding the underlying
model of the domain scattered throughout its functions,
methods, classes, etc.

On the other hand, though, I disagree. Someone once claimed
that Lisp is a "programmable programming language". It is
the best available tool for building new domain-specific
languages. Why settle for a tool that is less-featured in
this regard. (This is the heart of the admittedly trollish
tenth rule of programming due to Greenspun.)

Of course, we can respectfully disagree about whether this
is the right approach to building large programs. Perhaps
it is a defining characteristic of the Lisp community that
they think this way: When faced with a complex domain, one
"grows Lisp up" to meet it.
Jul 22 '05 #363
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote in message news:<MP************************@news.indigo.ie>.. .
In article <cf**************************@posting.google.com >,
ka*@ashi.footprints.net says...
The C++ style of protection is completely at odds with the very design
of the object system, because there is no notion of class scope. 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. The ordinary scoping rule applies.


You've lost me, I'm afraid...


In C++, a class is not just a blueprint for creating objects, but it's
also a lexical namespace. An identifier X declared within class C
(that is not nested in a namespace or another class) is actually C::X.
This is not class membership but scoping.

Within the body of a member function, C::X can be referred to using
the short name X, even though X is not declared anywhere in the
lexical scope: the body of the member function is not enclosed in the
class definition but is outside of it.

By manipulating the class definition, we can introduce names into the
scopes of function bodies that are located away from that definition,
and we can seriously alter their meaning.

This is a critical language design mistake; it's in no way necessary
for ``class scope'' to exist in an object system.

In Python, which has single dispatch like C++, members are referenced
using a self symbol, so that self.x means the x member of this object,
analogous to this->x, and x just has the normal meaning, denoting a
lexical variable or whatnot.

Lisp has multiple dispatch so that there isn't even a self object. A
method with three specializable parameters has three ``self'' objects.
They are explicitly named as parameters, nothing is hidden. Class
scope imposed into the Lisp paradigm would wreak even greater havoc,
because there would be clashes between identically named members from
the different classes.

Some dialects of the Pascal language have a much criticized WITH
statement that is similar to class scope. It introduces a block of
code in which the members of a record can be accessed using just their
short, unqualified names. Like C++ class scope, the WITH statement
has the problem that when fields are added to the record, they
suddenly become visible in all these scopes, potentially shadowing
existing references to those same names in those blocks of code.
Moreover, WITH statements themselves can be nested.

Modula-3 has a much more sane, completely different WITH statement, in
which the programmer explicitly declares unqualified names and the
expressions for which they stand, such as WITH X = A[i] ... meaning
that X is like a local macro denoting A[i] over this block.

Common Lisp has something similar, called SYMBOL-MACROLET. And it also
has something called WITH-SLOTS that is implemented on
SYMBOL-MACROLET. This WITH-SLOTS feature lets the programmer create
unqualified symbols that behave like variables over a scope, but which
are bound to the slots of a class object. For instance:

(with-slots (first-name last-name number) employee-object
;; just use first-name, etc.
)

The construct explicitly names the symbols for which bindings are to
exist. There is no way to manipulate this from a remote location.
Adding more slots to the class of employee-object has no effect,
because this is all lexically scoped.

The WITH-SLOTS macro can also give alternate names, which is handy if
you have nested WITH-SLOTS forms for objects of the same class, for
instance:

(with-slots ((x0 x) (y0 y)) point0
(with-slots ((x1 x) (y1 y)) point1
(my-graphics-library::draw-line x0 y0 x1 y1)))

If you are really aching for some of the conveniences of class scope,
you can emulate it by developing some short hand over WITH-SLOTS or
SYMBOL-MACROLET.

Lexical scope means that if we see some reference to (apparently) a
variable X, we just search the enclosing forms for the innermost
definition. If we don't find one, then it's an unbound reference, or a
reference to a global/dynamic variable.
Jul 22 '05 #364
Sashank Varma <no**@vanderbilt.edu> writes:
There is no question that Lisp's approach is more general, especially given
generic methods.
But what you (seem to) give up when you accept class scope is this
beautiful generality.


Yes, but in the situations where I want the class scope I do not in fact
need/want the generality.

Note carefully that I do not want to give up the beautiful generality if
required: it is always there if I need it.
You claimed above that class scope models how humans think in certain
situations. Frankly, as a cognitive psychologist, I'm finding it hard
to think of data that support (or refute) your claim.
Let me be precise: it is how *I* think when solving certain kinds of problems.

For other kinds of problems I think differently, and then the full generality
of multimethods can come into play.
My intuition (and it is a just an intuition, not an established fact
about human cognition) is that taking a consistent, parsimonious
approach to function/method calls brings an increased economy to the
comprehension of Lisp code. Programming languages are formalisms, and
those who uses formalisms (e.g., mathematicians) have historically
worked awfully hard to eliminate special cases and unnecessary
redundancies.


The class scope view is a more restricted and simplied one. That simplicity
aids in understanding when it is in effect.

Anytime one builds absraction layers on top of general components and
features, there is a similar "restriction" coming into play. Any specific
solution is by definition a restriction of the set of possible solutions.

Or not. My essential point is that I have used both approaches in the past and
have found that there are times when I want the class scope view since it
guides the solution a certain way. Other times I need the general way.

I want both.

--
Cheers, The Rhythm is around me,
The Rhythm has control.
Ray Blaak The Rhythm is inside me,
rA******@STRIPCAPStelus.net The Rhythm has my soul.
Jul 22 '05 #365
"Maahes" wrote:
So programs = algorithms + bookkeeping. Outsource as much of the
bookkeeping as you can, I say!


Oh god, its almost reads like your saying Lisp requires less commenting :)

I can't possibly mean this, so I'm sure I've misinferred here..
If anything, Lisp looks more like assembly, where you would expect a lot of
commenting on every single line...


Appearances can deceive. The way a programming language looks
to someone not used to it provides very little information
about subtle matters like how much commenting programs in it
require.

A very quick survey of a bit of my own code suggests that
I write slightly fewer comments in Lisp code than in C or C++.
Generally, the things I do in Lisp are harder than the things
I do in C or C++, which you'd expect to imply more commenting.
So I have some weak evidence that Lisp code doesn't need
such heavy commenting as C++ code does.

--
Gareth McCaughan
..sig under construc
Jul 22 '05 #366
ka*@ashi.footprints.net (Kaz Kylheku) wrote in message news:<cf**************************@posting.google. com>...

[ ... ]
Ambiguous means I have to look up a bunch of hidden rules that were
added to an ambiguous language and arbitrarily resolve the parsing
conflicts.
Okay, so we no longer have to wonder: you clearly don't know what
ambiguous means!
By the way, look at the ridiculous grammar factoring that's needed in
order to avoid the use of explicit precedence and associativity rules.
The expression 42 ends up being a multiplicative-expression *and*
an additive-expression at the same time. Yet it neither adds nor
multiplies.
I find this a bit interesting, but I'm afraid I'll have to wait until
after work to look it up, since my copy of the standard is at home.

[ ... ]
I'm almost certain that Japanese is full of ambiguities, being a
natural language.
Probably true -- but the ambiguities are due to the definition (or
lack thereof) of the language, not my ignorance.
The difference is that there aren't any hidden rules about it.
Hmm...your definition of "hidden" seems to be a strange one. The rules
(grammatical and otherwise) for C++ are all contained in a single
standard. For English there's no single standard specifying all the
grammatical rules, and probably not even one book directory to point
to all the other books that contain all the rules. To me, this seems
far more a matter of "hidden rules". I suppose Japanese may be better
than English in this regard (most languages are, after all) but I
still doubt that they're all in one place or anything like it.
An
ambiguity in natural language doesn't pretend to be something else.
That simply makes it sound remarkably as if you have little or no
experience with real life or natural languages at all. Just for
example, I'd guess that at least 60% of all the law suits filed on
earth are based on contrat language that pretended to be something
else, but was (in retrospect) clearly ambiguous.
If you utter something ambiguous that leads to a misunderstanding, you
can't claim superiority by referring the poor victim of your
misunderstanding to an associative precedence chart.
I see. I guess there are no contract attorneys (or probably any kind
of attorneys) in your world?

[ ... ]
Suppose that an alien encounters a message from Earth which looks like

A + B * C / D - E * F

The alien might be able to deduce what the operators are, and then it
is stuck.
I probably shouldn't try to argue this one, since (based on your
comments above) you seem to be from a planet substantially different
from the one where I live, so you probably have considerably more
knowledge of being that are comletely alien, at least to me.

I guess in the end, if your position is that Lisp might be more useful
for aliens, so be, I won't try to argue the point. The fact remains
that by the time most people start to program, something like "a+b*c"
already has meaning for them, and completely ignoring that background
(and in fact basically requiring that they UNlearn the useful
knowledge they already posess) does NOT improve understanding.
Now the same alien receives:

(- (+ A (/ (* B C) D)) (* E F))

Aha, it's obvious that the two symbols ( ) are special and that they
serve to enclose, as suggested by their shape. Moreover, they balance,
which reinforces that suspicion.
You start by postulating a being of which we know absolutely nothing,
but then postulate that you can provide an accurate prediction about
what it'll find obvious.

I'm not sure whether to believe that you're unbelievably coneited, or
merely insane.
I find it particularly interesting that C and C++ both contain some
things that (based on pure syntax) really ARE ambiguous, but those


What, like evaluation orders?


No, of course not. Which part of "syntax" didn't you understand?
That's not pure syntax, but semantics.
Oh, so it wasn't lack of understanding, just a lousy attempt at a
straw man.
That's a whole different pile of unbelieveable idiocy that should have
been fixed long ago.
You do nobody (especially yourself) any favors by claiming any
decision with you happen to disagree as "unbelievable idiocy".
Or, I'm guessing that perhaps by ``pure syntax'' you mean ``just the
raw grammar, with no symbol table information''. As in, what is this:

(a)(b)(c)+(d);
I'm not sure this is the simplest or best-chosen example, but at least
it IS an example of what I mentioned, yes.

[ ... ]
With my package, I could write the getc() macro call such that when
the first time it is evaluated, the enclosed expression is parsed and
classified. If it is found to have side effects, like getc(stream++)
then the program stops with an assertion. If it's suspected to have
side effects, a warning is produced and the program continues, and of
course if there are no side effects, it is silent. In both these
cases, the expression is stored into a hash table so it doesn't have
to be parsed again; the next time that same call is evaluated, the
hash will tell that all is good.
I guess I can see where this would be a stimulating intellectual
project, but I'm hard put to conceive of a lot of useful purposes for
it.
So as you can see, I have done some incredibly devilish things in
order to make a dumb language safer.


....or at least think you have. It sounds to me like an awful lot of
work with little real benefit, but if you're happy with what you did,
more power to you.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 22 '05 #367
"Maahes" <ma****@internode.on.net> wrote
Method call:
C++: rabbit.jump(3)
Lisp: (jump rabbit 3)


C: rabbit_jump(rabbit, 3)


C doesn't have classes and methods AFAIK. The Lisp call above is
really to a method of the rabbit class, but it looks exactly the same
as an ordinary function call.
Class method call:
C++: Rabbit::jump(rabbit, 3)
Lisp: (jump rabbit 3)


C++: Rabbit::jump(3)
C: rabbit_jump(3)

I don't know lisp, but it doesn't look right. A class call would have no
concept of a rabbit object as there is no data related to the class call. So
what does the "rabbit" do in your line.


I assumed that even if the design decision was made to make jump a
class method, one would like to know which rabbit object the caller
wanted to have jump. Hence it is passed as an argument.
Well, *one* language has syntax that remains consistent throughout.

*two* languages.


Lisp and C? Well, in C's case that's because there is really one one
kind of call, so it's not all that surprising that the syntax for that
kind of call is consistent.
Jul 22 '05 #368


Gareth McCaughan wrote:
Kenneth Tilton wrote:
Jeez, your eyes did not shriek aloud at that semi-colon at the end of a
line beginning "if ..."?!

Yes, they did. And at the "(1 ..." in the Lisp code.
I'm sorry if you think taking a couple of seconds to
spot a typo at 1.30am local time is proof of incompetence.


Naw, I was just being a d*ckhead. That is what /I/ do at 1:30am when I
get back from the pub.

:)

kenny
--
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Jul 22 '05 #369

Let me start by thanking you for your honest and thoughtful
response. I appreciate the opportunity to learn more about how
others program.

Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
I like to have as much 'protected' as practicable, while 'private'
is essentially unused. Of course that is suited to a one-man
operation, for team-work I would not so blithely share stuff with
derived classes. When you've written both base and derived class,
'protected' is enough IMO.
So, unless I misunderstand the symantics of the 'protected'
specifier, thinks marked this way are accessible to the class and
any sub-classes, but no one else. Is that correct?

I believe items declared 'public' are accessible to anyone, as
they would be in C. If one does not declare an specifier, do they
not default to 'public'?
Actually my latest project uses a lot of polymorphism and even
(shock) makes use of multiple inheritance, which I used to declare
essentially useless! So maybe with more extensive class
hierarchies, I will find myself starting to declare members as
'private'.
Again, IIRC, 'private' items are inaccessible to everyone except
the class itself. Have I misunderstood the semantics?
Contrary to popular belief, I do evolve my methodologies, albeit
reluctantly ;-)


I have no doubt. It happens to all of us, sooner or later. :-)

--jon
Jul 22 '05 #370
jc*****@taeus.com (Jerry Coffin) writes:
There are, however, ambiguities to be found, such as:

a b(c);

In C++, this could be either a definition of b as an object of type a,
with c as an initializer, OR it could be a declaration of b as a
function that returns an a and takes a c as a parameter. There are a
number of other examples along this line, but (at least from a
viewpoint of pure syntax) these are real ambiguities. C++ has a fairly
simple rule about how to deal with all of them, but even though the
rule itself is simple, implementing it is anything but, and is
semantic, not syntactical -- the syntax itself really IS ambiguous.


Didn't I already say that? Maybe I wasn't being clear, but this is why a
real description of the structure of a C/C++ program can not be very
similar to the source. It needs all kinds of annotations indicating what
each token really is in this semantic context.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #371
Hartmann Schaffer <hs@hartmann.schaffernet> writes:
afaik, AMD used a lisp written system to verify the design of their 64
bit processors. search for ACL2 (sorry, don't have the url handy)


It's a debian package, if anyone cares.

The code is at:
ftp://ftp.cs.utexas.edu:/pub/moore/acl2/v2-8/

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #372
Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
I would say "self-modifying code" includes any program in which code is
generated and executed as part of the expected output of the program.
It's no longer running itself as originally written.

I know there are inevitable ambiguities and special cases, simply
because there is no real dividing line between code (to be executed) and
data (to be manipulated). I would augment my definition above to
exclude cases in which there is a 'hierarchy of execution levels'. I
would not consider code that runs a cellular automaton that performs a
computation to be self-modifying, for example. The generated code has
to have approximate 'parity of esteem' with the original code.


Then lisp code is usually not self modifying. Macros simply translate
from a simple declaration of semantics to a possibly complex
implementation of those semantics. You can modify a function's
definition from within the function, but that's rarely a useful
technique. I have used it to good effect in a timed genetic algorithm
search where I had the top level be a loop that kept doing the
select-breed cycle and I could redefine the functions that selected and
bred the population without having to stop execution. The new
definitions were simply picked up on the next iteration of the loop.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #373
Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
That seems clear. May it be assumed it [Lisp] does not claim to
possess the advantages of the C++/Simula model of OO?


What "advantages" are you imagining here?

Lisp has 3 different constructs to represent 3 different concepts. C++
has one that tries to be all 3 at once. If you want to use one part and
not the other, you're screwed.

Types are defined using defclass.
Scopes are created using let/lambda.
Namespaces are created using defpackage.

Yes, C++ has namespaces separately, too, but you can't choose to not
inherit the namespace of your superclass. Since you are inheriting scope
as well as type, instance variables are shadowed instead of merged. The
language can't tell whether the name clash was intentional (attempting
to add declarations to the variable - such as making the type
declaration more specific) or unintentional.

In Lisp, you never get stuck in a situation where you want to extend a
type but maintain an independent scope so that variable names don't
clash.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #374
Rahul Jain wrote:
a b(c); In C++, this could be either a definition of b as an object of type a,
with c as an initializer, OR it could be a declaration of b as a
function that returns an a and takes a c as a parameter. There are a
number of other examples along this line, but (at least from a
viewpoint of pure syntax) these are real ambiguities. C++ has a fairly
simple rule about how to deal with all of them, but even though the
rule itself is simple, implementing it is anything but, and is
semantic, not syntactical -- the syntax itself really IS ambiguous.


Didn't I already say that? Maybe I wasn't being clear, but this is why a
real description of the structure of a C/C++ program can not be very
similar to the source. It needs all kinds of annotations indicating what
each token really is in this semantic context.


"Doc, it hurts when I go like that."

"I'm writing you a prescription. 'Don't go like that.'"

A description of a program at the source level should be its source. If you
have a problem with that, spend more time cleaning up your code, so a
statement like a_t b(c_t) is more clearly a declaration, with _t on its
types, and not a function call.

A higher level description of a design shouldn't waste its time on low-level
details like those.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #375
"Steven E. Harris" <se*@panix.com> writes:
Jon Boone <ip******@delamancha.org> writes:
What is it that you use access specifiers for?
Refining interfaces and enforcing invariants.

In CL, using package system deliberately can aid in /communicating/
these intents or desires, but there's a stronger non-enforceable trust
factor involved.

--
Steven E. Harris


I assume Gerry is talking about this issue.

Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
I like to have as much 'protected' as practicable, while 'private' is
essentially unused. Of course that is suited to a one-man operation,
for team-work I would not so blithely share stuff with derived classes.
When you've written both base and derived class, 'protected' is enough
IMO.

Actually my latest project uses a lot of polymorphism and even (shock)
makes use of multiple inheritance, which I used to declare essentially
useless! So maybe with more extensive class hierarchies, I will find
myself starting to declare members as 'private'. Contrary to popular
belief, I do evolve my methodologies, albeit reluctantly ;-)


Didn't we just discuss why CL is bad and C++ is good because C++
_trusts_ the programmer to do his memory management and pointer
arithmetic perfectly?

Do you use a garbage collector and disable pointers when you are working
in a project team? If so, what's the magic compiler flag? ;)

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #376
"Maahes" <ma****@internode.on.net> writes:
For protecting your implementation from the other programmers.
If you don't protect your variables and strictly define your interfaces, and
limit their power, you'll find the other programmers will completely
misusing your code. Then when you go to rewrite it to provide new features,
you'll find you can't because all the variables you want to trash are being
used in critical parts of multiple projects.


Don't you document your code?

Even without documentation, Lisp does this fine. Stuff that's marked as
internal-only (prefixed with % or %% if it's really internal to the
implementation) and/or unexported from the library's package (needs to
be accessed with a double colon instead of a single one from the
outside) is stuff that isn't guaranteed to be stable, or at least won't
be announced as a change.

If you are using symbols like these from someone else's code, you
obviously know what you're doing and need to mess with the internals of
the library. You'll know to pay close attention to that code breaking
when you upgrade.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #377
Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
You just don't get it, do you? Object-orientation is about program
architecture as well as language features. It's not about mixing and
matching a multiplicity of 'paradigms'.
Oh really? So you shouldn't use imperative code in an OO application?
Interesting.
Somebody else proposed that everybody design their own object system.
No. Actually, most features can be added to the object system directly,
since it can be extended using itself. If you want something radically
different, sure, you can design your own object system, just like you
can design your own control structure when that makes your program's
intended behavior easier to discern from the code.
OO as 'language feature' is cargo-cult OO.
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.
The bamboo airport looks just like a real one, but the planes aren't
going to land.


Except that Lisp's object system is a complete object system, even more
so that C++'s (or Java's for that matter). Even before CLOS, objects had
types and functions/objects could be polymorphic. That's why CLOS can be
implemented as simply a set of macros on top of the older Lisp
features... except for one spot: being able to define new types needs to
be done specifically for each implementation, because this functionality
already existed in older Lisps and CLOS has to integrate completely with
the rest of the type system to be complete.

As I've gone over before, other aspects of the C++ object system that
don't have to do with object orientation are implemented directly and
independently in Lisp.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #378
Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
In article <87************@nyct.net>, rj***@nyct.net says...
"Maahes" <ma****@internode.on.net> writes:
> Ok, thanx for the heads up.
> So Jak and Daxter isn't even a proof that Lisp is useful for games, since
> even those programmers decided they needed a variant for it to be useful...


This is how lisp always works. You customize the language to the
application domain, so that you can describe _what_ you want acheieved,
not _how_ you might want it done in some specific situation that may not
even be relevant to the final production application.


Of course, this is true of any high level language. In C++,
customisation comes mostly from defining classes and methods - the
language syntax remains consistent throughout.

Which seems like a win to me...


The syntax of Lisp is consistent throughout and is consistent even
_before_ you extend the behaviors.

But classes and methods don't encompass all of the ways you want to
express your application's various behaviors. If they did, why do you
need any syntax other than classes and methods?

Why do mathematical operators need to be infix? Just call an add()
method on a number object, passing it another number object and you'll
get the sum back as the result.

Why do you need looping constructs? Just define a class that has methods
for the four parts of the for construct in C -- constructor for the
initialization clause, a step() method for the step clause, a done()
method for the termination test, and a body() method for the loop's
body. Isn't that cleaner?

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #379
Kenny Tilton <kt*****@nyc.rr.com> writes:
Naw, I was just being a d*ckhead. That is what /I/ do at 1:30am when I
get back from the pub.


Yeah, that's what happens when you leave the pub early and have time to
kill before you get your unemployed ass to bed somewhere around 5:00.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #380
"Computer Whizz" <ol*********@hotmail.com> writes:
"Rahul Jain" <rj***@nyct.net> wrote in message
news:87************@nyct.net...
"Computer Whizz" <ol*********@hotmail.com> writes:
Now here it is much better for C/C++ IMO.
parameters are passed using the ()'s to group them together, and the
function outside. While in Lisp, the function and parameters are in
exactly
the same place.
No, the operator is in the beginning of the evaluated form and the
parameters are the rest of it. I can't see how that's "the same place"
any more than the reception is in the same place as the janitor's
closet. They're in the same building, sure, but the reception is right
at the entrance.


Yes - but "our" buildings have walls between the rooms.


So do ours. I hope you see that the elements of the form are separated
by somehow...
(OK - I sound like an ass a little there... Still, Lisp programmers seem all
happy and ine saying "I can read Lisp code OK" when it's not you - but the
editor reading it out for you.
I might use a simple syntax highlisghter to show variables/functions/static
text but I can just as easily judge and evaluate raw C/C++/most other
languages - even if they've been typed by a monkey with no actual use of the
tab key... )


That's not a problem. I have an editor that can indent properly. But how
easily do you spot the
if (foo());
do_whatever();
something_else();
problem?
English has a different syntax, and an amazingly complex one. The flow
of lisp code is determined by the parens, which humans infer using the
indentation applied by the editor.


That's where they differ more prominently! C/C++/whatever IS (at least in my
mind) very similar to English. It has words following each other in a
"flow".


You mean that there's no nesting? No well-defined structure? Lisp code
flows. You just look at the banks of the river and ignore the actual
river that's flowing. The banks merely shape the flow of the river.
Don't stare at them.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #381
"Maahes" <ma****@internode.on.net> writes:
You misunderstand. Lispniks still edit text as so many characters. We
just have /at our disposal/ when we choose to call on them sundry mad
useful tools for editing blocks of code in one go.


QUOTE:
Yes, I am constantly irritated that I don't get a single conceptual
block (such as an entire for loop or a single addend in a summation)
with a single keystroke when I'm at work coding Java.


That sounds like the editor is inserting stuff to me.


It probably wasn't clear: I was talking about selection. But I do have
automated code generation scripts in my editor because there's so much
noise in the syntax. Effectively, those scripts are a decompression
algorithm to decompress my ideas into the masses of Java code needed to
express a simple pattern.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #382
"Maahes" <ma****@internode.on.net> writes:
A + (B * C / D) - (E * F)

so that there is no misunderstanding of your code. Certainly not needed, but
makes it easier to read at a glance, which is what I would say is the
highest priority when designing a language to be used in a team
environment..
Ah, so Lisp is designed to make sure there is no misunderstanding of
your code, and is therefore excellent for use in a team environment.
Gee, I just love this thread... Will it ever end. I can see this stuff going
round in circles for weeks :)


:)

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #383
jc*****@taeus.com (Jerry Coffin) writes:
ka*@ashi.footprints.net (Kaz Kylheku) wrote in message news:<cf**************************@posting.google. com>...
The difference is that there aren't any hidden rules about it.


Hmm...your definition of "hidden" seems to be a strange one.


Are you familiar with the principle of least surprise? That's what we're
trying to convey here.

--
Rahul Jain
rj***@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Jul 22 '05 #384
chris <ca*@cs.york.ac.uk> wrote
Class method call:
C++: Rabbit::jump(rabbit, 3)
Lisp: (jump rabbit 3)

What is this? are you saying that the class rabbit has a static member
function that takes a rabbit and a 3? I'm not sure why you would want
such a thing..


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.
Also are you saying in lisp when I write (jump rabbit 3) it's impossible
to tell if I'm calling a member function of Rabbit that takes a single
parameter, or a general function that takes two parameters?


No, that's not how it works.

To begin with, the method call actually takes two parameters; the
types of each parameter is matched against the set of available
methods with the same name and the best match is called. There is no
such thing as a member function of a class, but there may be a method
that's ready and willing to handle calls involving an instance of
Rabbit in the first parameter place.

This way, methods taking any type of object and methods specifically
taking only certain types of objects can co-exist peacefully.
Jul 22 '05 #385
Jon Boone posted:

Let me start by thanking you for your honest and thoughtful
response. I appreciate the opportunity to learn more about how
others program.

Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
I like to have as much 'protected' as practicable, while 'private'
is essentially unused. Of course that is suited to a one-man
operation, for team-work I would not so blithely share stuff with
derived classes. When you've written both base and derived class,
'protected' is enough IMO.
So, unless I misunderstand the symantics of the 'protected'
specifier, thinks marked this way are accessible to the class and
any sub-classes, but no one else. Is that correct?


Correct:

class Base
{
protected:

int k;
};

class Derived : public Base
{
Derived()
{
k = 4;
//This is perfectly legal
}
};
int main()
{
Base monkey;

monkey.k = 4;
//This is illegal
}
I believe items declared 'public' are accessible to anyone, as
they would be in C. If one does not declare an specifier, do they
not default to 'public'?


They default to private.

Writing:

class Blah
{
int k;
};
is the same as writing:

class Blah
{
private:
int k;
};
Conversly, if you opt for the "struct" keyword, things default to public,
ie:

struct Blah
{
int k;
};
is the same as:
struct Blah
{
public:
int k;
};
Actually my latest project uses a lot of polymorphism and even
(shock) makes use of multiple inheritance, which I used to declare
essentially useless! So maybe with more extensive class
hierarchies, I will find myself starting to declare members as
'private'.


Again, IIRC, 'private' items are inaccessible to everyone except
the class itself. Have I misunderstood the semantics?

Correct. Private items are even inaccesible to dervied classes.
-JKop
Jul 22 '05 #386
What are access specifiers for again?

Here's how I go about things:
1) I'm writing a class.

2) I want an object in the class to store some data.

3) I decide whether the user needs to know anything about this data.

4) If so, I make it "public", if not I make it "private".
Why make it private? I consider it to be a synonym for "Hey user, you don't
need to read up on this bit, it's just the internal guts of my class, you
don't have to worry about it, it doesn't affect how you use the class, ie.
the interface".
Ofcourse my user can just open the header file, replace private with public
and alter my private objects willy-nilly. To this I say:

"I warned you. You're messing with the internals of the class. I haven't
documented how the internals works so either A) You've figured it out by
reading my code, or B) You're messing. Either way I assume no liablility. I
gave you a user-friendly easy-to-use class, end of story."
Similarly, when I've been given a class written by some-one else, I don't
read through the private section, why... because I don't need to! All I'm
worried about is reading the "public" section, because that's the stuff I'll
work with to get what I want out of the class.
-JKop
Jul 22 '05 #387
JKop wrote:

What are access specifiers for again?


Here's how I go about things:


Same here:

1) I'm writing a package.

2) I want a variable in the package to store some data.

3) I decide whether the user needs to know anything about this data.

4) If so, I export it from the package, if not I don't.
Why no export? I consider it to be a synonym for "Hey user, you don't
need to read up on this bit, it's just the internal guts of my package,
you don't have to worry about it, it doesn't affect how you use the
package, ie. the interface".

Of course my user can just use the variable with a special qualified
access and alter my non-exported variables willy-nilly. To this I say:

"I warned you. You're messing with the internals of the package. I
haven't documented how the internals works so either A) You've figured
it out by reading my code, or B) You're messing. Either way I assume no
liablility. I gave you a user-friendly easy-to-use package, end of story."

Similarly, when I've been given a package written by someone else, I
don't read through the non-exported symbols. Why? Because I don't need
to! All I'm worried about is reading the exported symbols, because
that's the stuff I'll work with to get what I want out of the package.

+++++++++++++++++++

In Common Lisp, access control and the object system are orthogonal
concepts.
Pascal

--
Pascal Costanza University of Bonn
mailto:co******@web.de Institute of Computer Science III
http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)
Jul 22 '05 #388
In article <no************************@news.vanderbilt.edu> ,
no**@vanderbilt.edu says...
In article <MP***********************@news.indigo.ie>,
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote:
Let me point out something. If you do twenty projects in this fashion
you will have twenty new languages. Surely that vitiates any benefit of
a particular language, even if it is marginally better suited to the
problem domain of a given project?


On one hand, I agree with you. But all significant programs
develop their own "vocabulary," one that matches the domain
at hand. The hard part about understanding a large program
is rarely mastering the details of the language in which it
is written. Rather, it is understanding the underlying
model of the domain scattered throughout its functions,
methods, classes, etc.

On the other hand, though, I disagree. Someone once claimed
that Lisp is a "programmable programming language". It is
the best available tool for building new domain-specific
languages. Why settle for a tool that is less-featured in
this regard. (This is the heart of the admittedly trollish
tenth rule of programming due to Greenspun.)

Of course, we can respectfully disagree about whether this
is the right approach to building large programs. Perhaps
it is a defining characteristic of the Lisp community that
they think this way: When faced with a complex domain, one
"grows Lisp up" to meet it.


Fair comment. But put this way, whichever side you prefer, you can
hardly see it as an especially important or 'life-changing' advantage of
Lisp, can you?

- Gerry Quinn

Jul 22 '05 #389
In article <m3************@spiritus.delamancha.org>,
ip******@delamancha.org says...

Let me start by thanking you for your honest and thoughtful
response. I appreciate the opportunity to learn more about how
others program.

Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
I like to have as much 'protected' as practicable, while 'private'
is essentially unused. Of course that is suited to a one-man
operation, for team-work I would not so blithely share stuff with
derived classes. When you've written both base and derived class,
'protected' is enough IMO.
So, unless I misunderstand the symantics of the 'protected'
specifier, thinks marked this way are accessible to the class and
any sub-classes, but no one else. Is that correct?


Yes.
I believe items declared 'public' are accessible to anyone, as
they would be in C. If one does not declare an specifier, do they
not default to 'public'?


No, private. [Although C++ retains the 'struct' keyword from C, and
members of a struct default to public.]

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.

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.
Actually my latest project uses a lot of polymorphism and even
(shock) makes use of multiple inheritance, which I used to declare
essentially useless! So maybe with more extensive class
hierarchies, I will find myself starting to declare members as
'private'.


Again, IIRC, 'private' items are inaccessible to everyone except
the class itself. Have I misunderstood the semantics?


No, that is correct. (You can use the 'friend' keyword to make
exceptions in special cases.)

- Gerry Quinn

Jul 22 '05 #390
In article <87************@nyct.net>, rj***@nyct.net says...
Gerry Quinn <ge****@DELETETHISindigo.ie> writes:
I like to have as much 'protected' as practicable, while 'private' is
essentially unused. Of course that is suited to a one-man operation,
for team-work I would not so blithely share stuff with derived classes.
When you've written both base and derived class, 'protected' is enough
IMO.
Didn't we just discuss why CL is bad and C++ is good because C++
_trusts_ the programmer to do his memory management and pointer
arithmetic perfectly?

Do you use a garbage collector and disable pointers when you are working
in a project team? If so, what's the magic compiler flag? ;)


No, *we* didn't discuss that. But there's a difference, in any case.
Garbage is a very global issue. And pointer arithmetic is a very non-
global issue. A class doesn't use either to mess with the internals of
a different class.

- Gerry Quinn

Jul 22 '05 #391
In article <cf**************************@posting.google.com >,
ka*@ashi.footprints.net says...
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote in message news:<MP************************@news.indigo.ie>.. . By manipulating the class definition, we can introduce names into the
scopes of function bodies that are located away from that definition,
and we can seriously alter their meaning.
Not a problem, because functions are bound to classes. 'Away' is a
matter of definition. Lispers have been going on about how closing
parentheses half a mile away from their opening parentheses don't
matter. Likewise, there's a trail from function to class definition.
This is a critical language design mistake; it's in no way necessary
for ``class scope'' to exist in an object system.
Nonsense. There is every reason.
Lisp has multiple dispatch so that there isn't even a self object. A
method with three specializable parameters has three ``self'' objects.
They are explicitly named as parameters, nothing is hidden. Class
scope imposed into the Lisp paradigm would wreak even greater havoc,
because there would be clashes between identically named members from
the different classes.


That's because whatever 'class' functions you bolt on to Lisp, the
language is not object-oriented and never will be, except maybe at
package level. Deal with it.

- Gerry Quin


Jul 22 '05 #392
On Thu, 4 Nov 2004, Gerry Quinn wrote:
Fair comment. But put this way, whichever side you prefer, you can
hardly see it as an especially important or 'life-changing' advantage of
Lisp, can you?


Not as a lisp-only feature, but I'm certainly finding that level of thing
highly useful in Haskell - and it's having a serious effect on my
day-to-day programming.

--
fl****@flippac.org
Jul 22 '05 #393
In article <MP************************@news.indigo.ie>,
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote:
That's because whatever 'class' functions you bolt on to Lisp, the
language is not object-oriented and never will be, except maybe at
package level. Deal with it.


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

We (Common Lispers) don't think encapsulation is an integral part of OO.
Instead we have a separate language feature (packages) that handle
encapsulation. ``CLOS'' is left to deal with inheritance and
polymorphism (which, incidentally, are far more powerful than their C++
counterparts).

This is a difference of opinion.

-bcd
--
*** Brian Downing <bdowning at lavos dot net>
Jul 22 '05 #394
Gerry Quinn wrote:
In article <cf**************************@posting.google.com >,
ka*@ashi.footprints.net says...
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote in message
news:<MP************************@news.indigo.ie>.. .

By manipulating the class definition, we can introduce names into the
scopes of function bodies that are located away from that definition,
and we can seriously alter their meaning.


Not a problem, because functions are bound to classes. 'Away' is a
matter of definition. Lispers have been going on about how closing
parentheses half a mile away from their opening parentheses don't
matter. Likewise, there's a trail from function to class definition.

I agree with this, and Lisp methods tend to be located even further from the
class definition, for that matter.
Besides, most C++ IDEs have something similar to M-., which lets you move
directly from the invocation or declaration of a function to its
definition.

On the subject of Lisp, though, I'd hope that most Lispers *don't* think
having closing parantheses a long way from their opener is a good thing.
Personally I always try to keep functions below a screenful, so I can see
all of it at once.

I keep telling friends not to do that in C, though, and they keep not
listening to me - even adding vertical whitespace where none is needed - so
I wouldn't be surprised at all if I someday see a 200-line Lisp function.
They probably have better memory than I do.

This is a critical language design mistake; it's in no way necessary
for ``class scope'' to exist in an object system.


Nonsense. There is every reason.

If you're basing it on a message-passing paradigm, then there is. If you
have multiple dispatch then it doesn't make sense. Design choice, there.

Which one of those is best is a different discussion, but *for C++*, class
scope is reasonable. *For Lisp*, it isn't.

Class scope tends to play havoc with multiple inheritance, though, if that
includes automatically binding variables to the instance/class slots.
Lisp has multiple dispatch so that there isn't even a self object. A
method with three specializable parameters has three ``self'' objects.
They are explicitly named as parameters, nothing is hidden. Class
scope imposed into the Lisp paradigm would wreak even greater havoc,
because there would be clashes between identically named members from
the different classes.


That's because whatever 'class' functions you bolt on to Lisp, the
language is not object-oriented and never will be, except maybe at
package level. Deal with it.

Packages are namespaces, classes are... well, classes. They're entirely
different concepts: although class/instance slots can in some ways be said
to be in a separate namespace, in reality they are just in a separate
lexical scope.

That's true for C++ too, it's just slightly harder to see because function
definitions don't have to be inside the class-definiton braces.[1] In Java
they do, IIRC.
Now, then. How can you possibly say that Lisp isn't object-oriented, when
you can even specialize methods on built-in primitive types such as lists
(okay, conses) and numbers? (And fixnums, bignums, integers, floats, and so
on.)

It was *designed* to be an object-oriented language; the Common Lisp ANSI
standard was the first object-oriented language to be standardized.

Other people have already said this, though. Why, then, do you keep claiming
this? What does Lisp lack, that stops it from being object-oriented?
1: Hmm, can you still call it a lexical scope, then? I was pretty sure the
idea of a lexical scope involved the look of the source code;
myclass::function is inside myclass's lexical scope, but it isn't actually
*written* there.
Jul 22 '05 #395
Brian Downing wrote:
In article <MP************************@news.indigo.ie>,
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote:
That's because whatever 'class' functions you bolt on to Lisp, the
language is not object-oriented and never will be, except maybe at
package level. Deal with it.


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

We (Common Lispers) don't think encapsulation is an integral part of OO.
Instead we have a separate language feature (packages) that handle
encapsulation. ``CLOS'' is left to deal with inheritance and
polymorphism (which, incidentally, are far more powerful than their C++
counterparts).

This is a difference of opinion.

I might add that you do have encapsulation, if you decide to use slot-value
for "private" slots and accessors for public slots. That probably isn't a
good idea, though, since slots might go away at some point while accessors
can be redefined to emulate the slot some other way. The canonical example
may be storing a vector as magnitude+direction vs. x-pos, y-pos and so on.

One way that works, then, is by naming private functions as "%function%",
and public functions as "function".

It works for me, and although it's just a difference in syntax, we've
already established that that's true for C++ as well. People won't be
calling %internal-method% without noticing the %'s.

Jul 22 '05 #396
Gerry Quinn wrote:
In article <m3************@spiritus.delamancha.org>,
ip******@delamancha.org says...


[snip]
I believe items declared 'public' are accessible to anyone, as
they would be in C. If one does not declare an specifier, do they
not default to 'public'?


No, private. [Although C++ retains the 'struct' keyword from C, and
members of a struct default to public.]

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.

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.

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.
Jul 22 '05 #397
In article <MP************************@news.indigo.ie>,
Gerry Quinn <ge****@DELETETHISindigo.ie> wrote:
Fair comment. But put this way, whichever side you prefer, you can
hardly see it as an especially important or 'life-changing' advantage of
Lisp, can you?


Well it's life-changing for those whose life it changed.

I know, that's a bit circular. Most programmers come
to Lisp after having mastered more mainstream languages.
In my days, the natural progression was Basic->Pascal->C.
I don't know what it is these days - perhaps Visual Basic
->Java->C++? Those that "convert" to Lisp wonder why
others do not. There are of course pragmatic reasons
(i.e., number of jobs) and matters of taste (i.e., do
you resonate with the material in Graham's "On Lisp"?).
But to a convert -- at least to this convert -- some of
the reasons seems merely conservative or reactionary.

An additional problem is that relatively few programmers
make the reverse progression, from Lisp-like languages
to more mainstream languages. I'm not speaking here of
those who were exposed to Scheme in an introductory class
and found it weird. I'm speaking of people who spent a
few years immersed in Lisp, mastered its idioms, and
moved on to more mainstream languages because they
thought them techically superior. (Ray Blaack, who was
participating in this thread, indicated that he is one of
the few exceptions in this regard.)

These are some of the reasons why advocacy debates between
Lispers and users of more mainstream languages rarely
yield new converts for either side.
Jul 22 '05 #398
Sashank Varma <no**@vanderbilt.edu> writes:
I'm speaking of people who spent a few years immersed in Lisp, mastered its
idioms, and moved on to more mainstream languages because they thought them
techically superior. (Ray Blaack, who was participating in this thread,
indicated that he is one of the few exceptions in this regard.)


Actually, I in fact think Lisp *is* techically superior. I just don't use it
in my job. I wish I could.

I use Java and C# instead. I avoid C++ like the plague and only use it if
forced to maintain a legacy project. I avoid VB as well.

It would be great to be able to use Common Lisp, Scheme, Dylan, etc on real
projects. For that matter, it would also be great to be a games developer.

PS: its "Blaak". "Blaack" sounds like spitting up a hairball :-).

--
Cheers, The Rhythm is around me,
The Rhythm has control.
Ray Blaak The Rhythm is inside me,
rA******@STRIPCAPStelus.net The Rhythm has my soul.
Jul 22 '05 #399
Rahul Jain <rj***@nyct.net> writes:
[.....] Types are defined using defclass. Scopes are created using let/lambda.
What about PROGV? Does it qualify here? I think it does.

I'm just curious...

Btw, why do you omit FLET?
Namespaces are created using defpackage. [.....]


Regards, Szymon.
Jul 22 '05 #400

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

39
799
by: Peter Lewerin | last post by:
peter.lewerin@swipnet.se (Peter Lewerin) wrote > There is a paradigm > difference between CLOS and non-OOP Lisp code, but the language is the > same, and it's quite possible to mix the two. D'oh. I first meant to write approximately "There is a complexity difference but no paradigm difference.", but then I thought people would
0
7353
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7277
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7516
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
1
7263
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7626
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
3339
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1732
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
902
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
568
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.