Discussion:
Beginner question (was: C, Obj-C, C++, Java)
(too old to reply)
Bruce Toback
1998-12-10 18:01:53 UTC
Permalink
A beginner question follows.
I like Obj-C, and it has some incredible
useful features that Java just plain lacks, but Java may be better suited
for someone new to OO and YB.
I'm trying to figure out now which language to use; I'd be new to both.
The business case for using Java is very strong, but the engineer in me
is tired of working around C++ language limitations (all of which are
related to C++'s static binding) and would like to concentrate on solving
real problems for a change. (Devising solutions to problems imposed by
the development environment is NOT solving real problems.)

An awful lot of YB appears to be dependent on dynamic binding. A very
basic and powerful OO technique, sending a dynamically-selected message
to a collection of objects, seems impossible to do in Java (and is
utterly impossible in C++, unless you count pointer-to-member subterfuges
as good engineering practice) .Can someone explain what it is I'm missing?
Is this actually not necessary to coding with YB?

-- Bruce

--------------------------------------------------------------------------
Bruce Toback Tel: (602) 996-8601| My candle burns at both ends;
OPT, Inc. (800) 858-4507| It will not last the night;
11801 N. Tatum Blvd. Ste. 142 | But ah, my foes, and oh, my friends -
Phoenix AZ 85028 | It gives a lovely light.
***@optc.com | -- Edna St. Vincent Millay
Ben Moseley
1998-12-11 10:58:59 UTC
Permalink
Post by Bruce Toback
An awful lot of YB appears to be dependent on dynamic binding. A very
basic and powerful OO technique, sending a dynamically-selected message
to a collection of objects, seems impossible to do in Java (...).
In Java, providing you're happy to accept the restriction that the method be
declared in an 'interface', you can simply iterate over objects and invoke the
method (as represented by a 'Method' object). The actual method which is
executed will be dynamically selected based on the run time type of the
receiver (as passed to the 'invoke' method of the 'Method' object).

The restriction about the method being in an interface isn't normally too
binding (it is conceivable that you might be unable to ensure all objects are
of the same Class/Interface - in which case your invocation will fail even if
the receiver implements the method).

Is this the problem you are describing, or have I misunderstood what you were saying?

--Ben
dIsCoRd
1998-12-11 14:19:01 UTC
Permalink
Post by Ben Moseley
Post by Bruce Toback
An awful lot of YB appears to be dependent on dynamic binding. A very
basic and powerful OO technique, sending a dynamically-selected message
to a collection of objects, seems impossible to do in Java (...).
In Java, providing you're happy to accept the restriction that the method be
declared in an 'interface', you can simply iterate over objects and invoke the
method (as represented by a 'Method' object). The actual method which is
executed will be dynamically selected based on the run time type of the
receiver (as passed to the 'invoke' method of the 'Method' object).
I think he meant that in ObjC, there is a dynamic _typing_. The binding is
dynamic in both ObjC and Java (ie at runtime, the er.r.. runtime will
choose the correct method implementation). However, in ObjC, the method
implementation does not have to exist at the time of the compile. If i
have a generic obejct (of type id) then I can send it any message I want,
and if it has a method implementation, it will be used, if not, it will
try to forward it. In Java, if you have a deneric object (of type Object),
then you are restricted heavily in the messages that you can send it
(basically nothing except what is defined in the Object class itself).

Alternatively, he could have been talking about the fact that you can
dynamically select the actual messages sent at runtime (using code logic)
- its a lot like function pointers, really, but it has a really _nice_
target/action paradigm / event loop thingie (<- technical term :)

--

/\ karl hsu
/ \ ***@charm.net
/ \ www.charm.net/~discord/
/ () \
/ \
/ \____/ \
/____________\
Chuck Pisula
1998-12-11 14:37:54 UTC
Permalink
Post by dIsCoRd
I think he meant that in ObjC, there is a dynamic _typing_. The binding is
dynamic in both ObjC and Java (ie at runtime, the er.r.. runtime will
choose the correct method implementation).
Sorry If I'm restating, but I've joined this conversation late. I believe
one issue that is central to YB's dynamic binding is the Java reflection
mechanism. As we all know, the objective-C runtime system performs
dynamic message lookup. Java can do this, but its "reflection" mechanism
for looking up methods is _extremely_ slow right now. Objective-C has an
excellent runtime for this with caching, etc... How can the NEXTSTEP,
err.. YB kit work efficiently in this light? (assuming you want to do alot
of dynamic message lookup).

Chuck
dIsCoRd
1998-12-11 14:49:01 UTC
Permalink
Post by Chuck Pisula
Sorry If I'm restating, but I've joined this conversation late. I believe
one issue that is central to YB's dynamic binding is the Java reflection
mechanism. As we all know, the objective-C runtime system performs
dynamic message lookup. Java can do this, but its "reflection" mechanism
for looking up methods is _extremely_ slow right now. Objective-C has an
excellent runtime for this with caching, etc... How can the NEXTSTEP,
err.. YB kit work efficiently in this light? (assuming you want to do alot
of dynamic message lookup).
I'm not entirely sure what reflection has to do with dynamic binding?

Anyway, the YB kit works efficiently by being written in ObjectiveC :)
The Java bridge just translates calls and lets the ObjC runtime deal with
everything on the YB side.

If you're asking how ObjC does dynamic dispatch well (relatively, anyway),
it statically binds what it can, and all dynamic lookups are stored in a
hashtable. So the first couple of times you use functionality in a n app,
its a bit slow. Once the has talbe gets filled, its pretty good - notmuch
slower than a virtual function call in C++, if i remember correctly. Don't
know if apples runtime cache is global, oor per class (global would be my
guess, but ?)

One of the big slowdowns that I remember is reference counting in the
Apple frameworks - someone mentioned that retain/release calls were
regular method calls, and thus much slower than you want something like
that to be.


--

/\ karl hsu
/ \ ***@charm.net
/ \ www.charm.net/~discord/
/ () \
/ \
/ \____/ \
/____________\
Helge Hess
1998-12-11 15:04:46 UTC
Permalink
Post by dIsCoRd
If you're asking how ObjC does dynamic dispatch well (relatively, anyway),
it statically binds what it can, and all dynamic lookups are stored in a
hashtable. So the first couple of times you use functionality in a n app,
its a bit slow. Once the has talbe gets filled, its pretty good - notmuch
slower than a virtual function call in C++, if i remember correctly. Don't
know if apples runtime cache is global, oor per class (global would be my
guess, but ?)
The way the ObjC runtime works is implementation dependend.
Post by dIsCoRd
One of the big slowdowns that I remember is reference counting in the
Apple frameworks - someone mentioned that retain/release calls were
regular method calls, and thus much slower than you want something like
that to be.
Whether this results in big-slowdowns depends very much on the
application. It is an issue in applications that use many objects, an
example are EOF applications. EOF does a lot of RC partly because of
snapshotting and the layering (rows become dictionaries, dictionaries
become objects and the reverse).
Anyway, as someone from Apple explained some time ago the
method-capabilities are actually used in Apple's frameworks. That is,
the way the RC is managed depends on the class, which is quite unusual
IMHO. The way it should have been done IMHO is using a RC field in the
object and inline functions for retain and release.

Also note that the slowdown may be justified, I prefer having memory
management with slowdown over not-having memory management at all ..
Best would be automatic memory management (GC) though.

Helge
--
MDlink online service center
http://www.mdlink.de/
dIsCoRd
1998-12-11 15:51:45 UTC
Permalink
Someone tell me if this is wrong or imcomplete somewhere...

Differences between Objective-C and Java


Syntax
Java is based on C++. It has no header files.
Objective-C is based on C/Smalltalk. Classes consist of a
header file and 1 or more implementation files.

Typing
Java has weak static typing. Method calls are synonymous
with Messages and are checked at compile time.
However, the programmer can cast objects to other
objects.
Objective-C has dynamic and weak static typing. Messages
and Method calls are distinct. A generic object can
accept any type of message. Static typing can be
enforced by the programmer, but casting is still
allowed. If an object is cast to a specific type,
compile-time checking takes place.

Binding
Java has dynamic binding.
Objective-C has static and dynamic binding. Static message
dispatch is equivalent to a function call.

Exceptions
Java has language level support.
Objective-C does not - it is supported through libraries or
frameworks.

MultiThreading
Java has language level support.
Objective-C does not - it is supported through libraries or
frameworks.

Security
Java has a security manager.
Objective-C does not. In addition, all methods are public
in Objective-C.

Namespaces
Java has a universal and distributed name space for
classes. You can have classes installed on one
computer and Java can load them on another using http.
Objective-C has dynamic class loading capabilities, but
only from the same file system. I believe that all
Messages live in a single namespace (class methods are
separate).

Event Model
Java has Nested Classes.
Objective-C has Selector types, allowing Messages to be
programmatically added to a class.

Categories
Java does not have categories. All code for a class must be
in a single file. This may be a function of the
security manager.
Objective-C allows programmers to extend a class without
subclassing, by adding new methods through categories.
It also allows programmers to break up the code for a
class into multiple files.

Memory
Java has a fixed heap used for object allocation. The
initial heap size and maximum size is set at start.
Java has language support for Automatic Garbage
Collection.
Objective-C uses the heap as managed by the OS and the
runtime system. Objective-C has no language support
for garbage collection - different methods are used by
different implementations (Apple uses reference
counting, GNU uses either reference counting or
automatic garbage collection).

Message Forwarding
Objective-C objects can forward any message it does not
understand to another object, allowing the creation of
"proxy" objects.
Java throws an exception if the message is unknown.
Function calls are checked at compile time. This may
be a function of the security manager.

poseAs
Objective-C allows a class to pose as another class -
whenever an object of type "A" would be created and
used, create and use class "B" instead.
In Java, this would violate the security manager, and so is
strictly forbidden.

Fragile-Base-Class
(subclasses break when superclasses are changed)
Java has it.
Objective-C has it, but only for instance variables
referenced by the subclass.

RTTI
Java does this through reflection.
Objective-C is supported in the runtime.




--

/\ karl hsu
/ \ ***@charm.net
/ \ www.charm.net/~discord/
/ () \
/ \
/ \____/ \
/____________\
Fabien Roy
1998-12-15 23:44:35 UTC
Permalink
You forgot:

Nil objects:
Java raise an exception if the receiver of a message
(or method) is nil.
Thus: if selectedObjectArray return nil
the following code:
this.selectedObjectArray().count()
will generate an exception at run time.

In Obj-C:
[[self selectedObjectArray] count]
will give a count of 0.

Later.

Fabien
---
Fabien L Roy NationsBanc Montgomery Securities, LLC
voice: (704)386-75-76 100 North Tryon Street
fax: (704)388-95-64 NC1-007-09-08
Charlotte NC 28255
Beeper: 143-9722 (1-800-946-46-46) or
http://www.MobileComm.com/message/
email: ***@ncmi.com (NeXT/Mime)
Pager-email ***@mobilecomm.net
tetuya takeo
1998-12-16 09:22:24 UTC
Permalink
Maybe, this deserves to note;

Serialization(Archiving)
To serialize Java object, simply declare Serializable
interface for the class, and declare transient keyword for
member variables which should not be serialized.
To archive Obj-C object, programmer should write methods like
encodeWithCoder: explicitly for the class.

---
Tetuya TAKEO
***@amtec.co.jp (NeXTmail/MIME accepted)
dIsCoRd
1998-12-11 15:59:35 UTC
Permalink
I'd like for Apple to have Automatic Garbage Collection, I think. I don't
see the a need for reference counting anymore - some AGC implementations
are quite good (EIFFEL and SmallTalk, for instance).

Someone mentioned the need for RC for distributed computing - how does
Java do it? (I really don't know). Why the advantage of RC over AGC for
distributed?

I'd like for there to be a way to do both - have an AGC, but also a way
for the programmer to say "I'm done with this - kill it!". Maybe thats not
possible in a truly dynamic environment.

Eiffel had an interesting concept, if I remember - they allowed you to
"hint" to the garbage collector thread that you had time, and now would be
a good time to run a quick GC cycle. I don't know if that would be
appropriate...

Maybe just a better implementation of RC (especially Autorelease pools)
would do it for me.

Thats one of the things i relally liked about Java - AGC (the other was
the complete lack of the somewhat arcane C syntax that you sometimes see
in ObjC programs).

Maybe we just need an Objective-(Better)C :)

--

/\ karl hsu
/ \ ***@charm.net
/ \ www.charm.net/~discord/
/ () \
/ \
/ \____/ \
/____________\
Fabien Roy
1998-12-16 14:43:13 UTC
Permalink
Fabien,
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
Big difference there.
Just my 2 cents,
Eric
See for yourself:
Source:
/* Generated by the NeXT Project Builder
NOTE: Do NOT change this file -- Project Builder maintains it.
*/

#import <appkit/appkit.h>
#import <foundation/NSArray.h>
#import <foundation/NSUtilities.h>

void main(int argc, char *argv[]) {

NSArray *myArray= nil;

NSLog(@"myArray: %@ , [myArray count] = %d", myArray, [myArray count]);
exit(0);
}

Compile NS3.3:
cc -g -Wall -DDEBUG -I./sym -arch i386 -I. -c NilObject_main.m -o
cc -g -Wall -DDEBUG -I./sym -arch i386 -ObjC -sectcreate __ICON __header NilObject.iconheader -segprot __ICON r r -sectcreate __ICON app /usr/lib/NextStep/Workspace.app/application.tiff -o NilObject.debug/NilObject i386_debug_obj/NilObject_main.o -lFoundation_s -lMedia_s -lNeXT_s

Results:

***@fargo> gdb NilObject.debug/NilObject -x PB.gdbinit
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.7 (NeXT 3.3 patch), Copyright 1992 Free Software Foundation, Inc...
Reading symbols from /tmo/NilObject/NilObject.debug/NilObject...done.
Reading symbols from /usr/shlib/libFoundation_s.E.shlib...done.
Reading symbols from /usr/shlib/libMedia_s.A.shlib...done.
Reading symbols from /usr/shlib/libNeXT_s.C.shlib...done.
Reading symbols from /usr/shlib/libsys_s.B.shlib...done.

(gdb) r
Starting program: /tmo/NilObject/NilObject.debug/NilObject
Dec 16 09:36:29 [11822] myArray: *nil* , [myArray count] = 0

Program exited normally.
(gdb)

---
Fabien L Roy NationsBanc Montgomery Securities, LLC
voice: (704)386-75-76 100 North Tryon Street
fax: (704)388-95-64 NC1-007-09-08
Charlotte NC 28255
Beeper: 143-9722 (1-800-946-46-46) or
http://www.MobileComm.com/message/
email: ***@ncmi.com (NeXT/Mime)
Pager-email ***@mobilecomm.net
Ben Moseley
1998-12-16 15:08:45 UTC
Permalink
Fabien,
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
Big difference there.
Just my 2 cents,
Eric
The call will indeed return 'nil'.

I believe the confusion comes from the fact that when used as or cast to an
integer, 'nil' is equivalent to 0. No 'count' message is ever sent anywhere.
Fabien Roy
1998-12-16 18:44:54 UTC
Permalink
Post by Ben Moseley
Fabien,
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
Big difference there.
Just my 2 cents,
Eric
The call will indeed return 'nil'.
I believe the confusion comes from the fact that when used as or
cast to an integer, 'nil' is equivalent to 0. No 'count' message is
ever sent anywhere.
#define nil (id)0 /* id of Nil instance */
Cheers,
--Ben
Anyway it will not generate an exception.

In a previous Java project we have a lot of

if (!myArray && myArray.count()) ...etc

Again a Nil Object RETURNS 0 for int, NaN for float or double and nil for a pointer!
This has nothing to do with casting, BTW how could we cast (id)0 to float or double and get NaN

Se for yourself:

/********* MyNSObject.h *********************/
#import <appkit/appkit.h>

#import <foundation/NSObject.h>
#import <foundation/NSString.h>

@interface MyNSObject:NSObject
{
}
-(float) myFloatValue;
-(NSString *) myNSStringValue;


@end
/********* End of MyNSObject.h *********************/
/********* MyNSObject.m *********************/
#import "MyNSObject.h"

@implementation MyNSObject

-(float) myFloatValue
{
return 1.11111;
}
-(NSString *) myNSStringValue
{
return @"A string";
}

@end
/********* End of MyNSObject.m *********************/
/********* NilObject_mainObject.m *********************/
/* Generated by the NeXT Project Builder
NOTE: Do NOT change this file -- Project Builder maintains it.
*/

#import <appkit/appkit.h>
#import <foundation/NSArray.h>
#import <foundation/NSUtilities.h>
#import "MyNSObject.h"

void main(int argc, char *argv[]) {

NSArray *myArray= nil;
MyNSObject *myObject=nil;

NSLog(@"myArray: %@ , [myArray count] = %d", myArray, [myArray count]);
NSLog(@"myObject: %@ , [myObject myFloatValue] = %f,[myObject myDoubleValue] = %f [myObject myNSStringValue] = %@", myObject, [myObject myFloatValue],[myObject myDoubleValue],[myObject myNSStringValue]);
exit(0);
}
/********* End of NilObject_mainObject.m *********************/

Compile on NS3.3
cc -g -Wall -DDEBUG -I./sym -arch i386 -I. -c MyNSObject.m -o ./i386_debug_obj/MyNSObject.o
cc -g -Wall -DDEBUG -I./sym -arch i386 -I. -c NilObject_main.m -o ./i386_debug_obj/NilObject_main.o
cc -g -Wall -DDEBUG -I./sym -arch i386 -ObjC -sectcreate __ICON __header NilObject.iconheader -segprot __ICON r r -sectcreate __ICON app /usr/lib/NextStep/Workspace.app/application.tiff -o NilObject.debug/NilObject i386_debug_obj/MyNSObject.o i386_debug_obj/NilObject_main.o -lFoundation_s -lMedia_s -lNeXT_s


Results:

***@fargo> gdb NilObject.debug/NilObject -x PB.gdbinit
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.7 (NeXT 3.3 patch), Copyright 1992 Free Software Foundation, Inc...
Reading symbols from /tmo/NilObject/NilObject.debug/NilObject...done.
Reading symbols from /usr/shlib/libFoundation_s.E.shlib...done.
Reading symbols from /usr/shlib/libMedia_s.A.shlib...done.
Reading symbols from /usr/shlib/libNeXT_s.C.shlib...done.
Reading symbols from /usr/shlib/libsys_s.B.shlib...done.

(gdb) r
Starting program: /tmo/NilObject/NilObject.debug/NilObject
Dec 16 13:16:37 [12433] myArray: *nil* , [myArray count] = 0
Dec 16 13:21:47 [12511] myObject: *nil* , [myObject myFloatValue] = NaN,[myObject myDoubleValue] = NaN [myObject myNSStringValue] = *nil*

Program exited normally.
(gdb)

---
Fabien L Roy NationsBanc Montgomery Securities, LLC
voice: (704)386-75-76 100 North Tryon Street
fax: (704)388-95-64 NC1-007-09-08
Charlotte NC 28255
Beeper: 143-9722 (1-800-946-46-46) or
http://www.MobileComm.com/message/
email: ***@ncmi.com (NeXT/Mime)
Pager-email ***@mobilecomm.net
Chuck Swiger
1998-12-17 17:02:40 UTC
Permalink
Post by Ben Moseley
The call will indeed return 'nil'.
I believe the confusion comes from the fact that when used as or cast to an
integer, 'nil' is equivalent to 0. No 'count' message is ever sent anywhere.
Bill Bumgarner
1998-12-17 17:14:18 UTC
Permalink
This is a different situation than the original discussion [and still on the
topic of Mac OS X Developer, thankfully]....

The original discussion was regarding return values resulting from sending a
message to a nil object pointer. The only case that it is truly defined is when
invoking a method that returns a pointer to an object. Other cases are
coincidental due to the structure of a frame on the stack-- bools, chars, and
shorts all fit into the 4 byte return value found on the stack on 32 bit machines
and, as such, methods returning shorter-than-word values will be zero when
sending a message to a nil object pointer. And, no, there is no casting
involved-- when invoking a non-nil-pointer method that returns BOOL, the return
value is still stored in the same four bytes-- but only one of the four bytes are
used for the value....

However, when returning something that doesn't fit into the default 4-byte hunk
o' return value memory on a "normal" 32-bit architecture frame, the results are
undefined-- both by specification and by practice. I.e:

float f = [(id)0x0 floatValue];

Will be undefined; it may actually be zero, but that is merely coincidence.

This is because the calling conventions change when the return value is larger
than can fit in the default frame's hunk o' memory for the return value.... I'm
sure Chuck can provide a lucid explanation of that-- I simply trust that the
compiler gets it right....

b.bum
Post by Ben Moseley
The call will indeed return 'nil'.
I believe the confusion comes from the fact that when used as or cast to an
integer, 'nil' is equivalent to 0. No 'count' message is ever sent anywhere.
Brian Willoughby
1998-12-17 17:26:43 UTC
Permalink
I am reasonably certain that return values are passed in a register. This is
based on m68k, i386, and ppc assembly output that I have read through.

The end result is the same for processors with 32-bit registers, because
there are only four bytes to store the return value. Remember, we're not
dealing with Pascal calling conventions under ObjC.

Brian Willoughby Software Design: NEXTSTEP, OpenStep, Rhapsody, MacOS X
Sound Consulting Apple Enterprise Alliance Partner

[ The original discussion was regarding return values resulting from
[ sending a message to a nil object pointer. The only case that
[ it is truly defined is when invoking a method that returns a
[ pointer to an object. Other cases are coincidental due to the
[ structure of a frame on the stack-- bools, chars, and shorts all
[ fit into the 4 byte return value found on the stack on 32 bit
[ machines and, as such, methods returning shorter-than-word values
[ will be zero when sending a message to a nil object pointer.
[ And, no, there is no casting involved-- when invoking a
[ non-nil-pointer method that returns BOOL, the return value is
[ still stored in the same four bytes-- but only one of the four
[ bytes are used for the value....
[
[ However, when returning something that doesn't fit into the
[ default 4-byte hunk o' return value memory on a "normal" 32-bit
[ architecture frame, the results are undefined-- both by
[ specification and by practice. I.e:
[
[ float f = [(id)0x0 floatValue];
[
[ Will be undefined; it may actually be zero, but that is merely
[ coincidence.
Kenneth C. Dyke
1998-12-17 17:50:56 UTC
Permalink
I think the deal is that the same register is not always used for returning
values from a function call, depending on what architecture and compiler
convenctions you're dealing with.

If the compiler is expecting a float or double as a return, it may be looking
in a floating point register rather than an integer register, which more
likely than not is what is going to get a 0 placed into it by the method
dispatcher when you send a message to nil. It really has nothing (directly)
to do with the *size* of the parameter being returned, as much as it is the
expected *type* of the parameter. In the example below, a float would
(generally) have fit fine into a standard data register, but that's not where
the compiler will try to get the value from.

-Ken
I am reasonably certain that return values are passed in a register. This is
based on m68k, i386, and ppc assembly output that I have read through.
The end result is the same for processors with 32-bit registers, because
there are only four bytes to store the return value. Remember, we're not
dealing with Pascal calling conventions under ObjC.
Brian Willoughby Software Design: NEXTSTEP, OpenStep, Rhapsody, MacOS X
Sound Consulting Apple Enterprise Alliance Partner
[ The original discussion was regarding return values resulting from
[ sending a message to a nil object pointer. The only case that
[ it is truly defined is when invoking a method that returns a
[ pointer to an object. Other cases are coincidental due to the
[ structure of a frame on the stack-- bools, chars, and shorts all
[ fit into the 4 byte return value found on the stack on 32 bit
[ machines and, as such, methods returning shorter-than-word values
[ will be zero when sending a message to a nil object pointer.
[ And, no, there is no casting involved-- when invoking a
[ non-nil-pointer method that returns BOOL, the return value is
[ still stored in the same four bytes-- but only one of the four
[ bytes are used for the value....
[
[ However, when returning something that doesn't fit into the
[ default 4-byte hunk o' return value memory on a "normal" 32-bit
[ architecture frame, the results are undefined-- both by
[
[ float f = [(id)0x0 floatValue];
[
[ Will be undefined; it may actually be zero, but that is merely
[ coincidence.
Fabien Roy
1998-12-17 17:48:48 UTC
Permalink
Post by Bill Bumgarner
float f = [(id)0x0 floatValue];
This will not compile (could not find method)!
But [(anObjectThatHaveAFloatValueMethod *)0x0 floatValue];
Will compile and will give NaN as a result.
Post by Bill Bumgarner
Will be undefined; it may actually be zero, but that is merely coincidence.
b.bum
Nil Object and not a nil pointer (the compiler need a cast).
NSArray *myArray= nil;
MyNSObject *myObject=nil;

The compiler will call a default handler for each methods of the Object which id is nil.

[myObject myDoubleValue] will give you NaN
same for
[(MyNSObject *) 0x0 myDoubleValue]

See my previous post (try to compile it):


/********* MyNSObject.h *********************/
#import <appkit/appkit.h>

#import <foundation/NSObject.h>
#import <foundation/NSString.h>

@interface MyNSObject:NSObject
{
}
-(float) myFloatValue;
-(NSString *) myNSStringValue;


@end
/********* End of MyNSObject.h *********************/
/********* MyNSObject.m *********************/
#import "MyNSObject.h"

@implementation MyNSObject

-(float) myFloatValue
{
return 1.11111;
}
-(NSString *) myNSStringValue
{
return @"A string";
}

@end
/********* End of MyNSObject.m *********************/
/********* NilObject_mainObject.m *********************/
/* Generated by the NeXT Project Builder
NOTE: Do NOT change this file -- Project Builder maintains it.
*/

#import <appkit/appkit.h>
#import <foundation/NSArray.h>
#import <foundation/NSUtilities.h>
#import "MyNSObject.h"

void main(int argc, char *argv[]) {

NSArray *myArray= nil;
MyNSObject *myObject=nil;

NSLog(@"myArray: %@ , [myArray count] = %d", myArray, [myArray count]);
NSLog(@"myObject: %@ , [myObject myFloatValue] = %f,[myObject myDoubleValue] = %f [myObject myNSStringValue] = %@", myObject, [myObject myFloatValue],[myObject myDoubleValue],[myObject myNSStringValue]);
exit(0);
}
/********* End of NilObject_mainObject.m *********************/

Compile on NS3.3
cc -g -Wall -DDEBUG -I./sym -arch i386 -I. -c MyNSObject.m -o ./i386_debug_obj/MyNSObject.o
cc -g -Wall -DDEBUG -I./sym -arch i386 -I. -c NilObject_main.m -o ./i386_debug_obj/NilObject_main.o
cc -g -Wall -DDEBUG -I./sym -arch i386 -ObjC -sectcreate __ICON __header NilObject.iconheader -segprot __ICON r r -sectcreate __ICON app /usr/lib/NextStep/Workspace.app/application.tiff -o NilObject.debug/NilObject i386_debug_obj/MyNSObject.o i386_debug_obj/NilObject_main.o -lFoundation_s -lMedia_s -lNeXT_s


Results:

***@fargo> gdb NilObject.debug/NilObject -x PB.gdbinit
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.7 (NeXT 3.3 patch), Copyright 1992 Free Software Foundation, Inc...
Reading symbols from /tmo/NilObject/NilObject.debug/NilObject...done.
Reading symbols from /usr/shlib/libFoundation_s.E.shlib...done.
Reading symbols from /usr/shlib/libMedia_s.A.shlib...done.
Reading symbols from /usr/shlib/libNeXT_s.C.shlib...done.
Reading symbols from /usr/shlib/libsys_s.B.shlib...done.

(gdb) r
Starting program: /tmo/NilObject/NilObject.debug/NilObject
Dec 16 13:16:37 [12433] myArray: *nil* , [myArray count] = 0
Dec 16 13:21:47 [12511] myObject: *nil* , [myObject myFloatValue] = NaN,[myObject myDoubleValue] = NaN [myObject myNSStringValue] = *nil*

Program exited normally.
(gdb)

---
Fabien L Roy NationsBanc Montgomery Securities, LLC
voice: (704)386-75-76 100 North Tryon Street
fax: (704)388-95-64 NC1-007-09-08
Charlotte NC 28255
Beeper: 143-9722 (1-800-946-46-46) or
http://www.MobileComm.com/message/
email: ***@ncmi.com (NeXT/Mime)
Pager-email ***@mobilecomm.net
Chuck Swiger
1998-12-17 18:40:26 UTC
Permalink
Post by Bill Bumgarner
The original discussion was regarding return values resulting from sending
a message to a nil object pointer. The only case that it is truly defined
is when invoking a method that returns a pointer to an object.
More precisely, the runtime guarantees that messages sent to nil objects
return nil, and if the calling code was expecting an (id) as the return
value, the results are well-defined.

That's the easy case. :-)
Post by Bill Bumgarner
Other cases are coincidental due to the structure of a frame on the stack--
bools, chars, and shorts all fit into the 4 byte return value found on the
stack on 32 bit machines and, as such, methods returning shorter-than-word
values will be zero when sending a message to a nil object pointer. And,
no, there is no casting involved-- when invoking a non-nil-pointer method
that returns BOOL, the return value is still stored in the same four
bytes-- but only one of the four bytes are used for the value....
You're absolutely right-- no casting is involved. If the calling code was
expecting some other type of return value, then the result will not be
well-defined.

It just so happens that the specific hardware in use and the compiler's
choice of representation for the systems we care about (MOXS or OPENSTEP on
PPC or Intel) results in 0 == nil == NULL without casting.

However, whether the return value is placed on the stack or passed back to
the caller in a register is not important so long as the return value fits.
Post by Bill Bumgarner
However, when returning something that doesn't fit into the default 4-byte
hunk o' return value memory on a "normal" 32-bit architecture frame, the
float f = [(id)0x0 floatValue];
Will be undefined; it may actually be zero, but that is merely coincidence.
Having all-bits-zero equal a FP 0.0 for floats and doubles is about as
common as having int 0 equal NULL, and is done for the same reasons. It
makes life easier for initialization and the most commonly used case for
numeric conversion. (For instance, a lot of RISC architectures now have
register 0 set to all-bits-zero.)
Post by Bill Bumgarner
This is because the calling conventions change when the return value is
larger than can fit in the default frame's hunk o' memory for the return
value.... I'm sure Chuck can provide a lucid explanation of that-- I simply
trust that the compiler gets it right....
And now, you've gotten to the most complicated case.

If the caller was expecting a return value that does not fit into a register
(eg, passing a structure directly on the stack rather than explicitly by
reference), you're in a world of hurt.

Some implementations may still treat this as a call-by-reference and return
a pointer to the region of memory which the caller may then dereference. If
instead the caller gets nil instead of a valid pointer, trying to use the
return value doesn't work.

Or some implementations may use a 64/80-bit FP register for returning
floating point values, and placing 0 into the normal (integral) register used
for return values doesn't work that well, either.

-Chuck

PS: And yeah, Greg's quite right about 0 -> NULL under ANSI; it's going the
Post by Bill Bumgarner
It is the other way around (casting NULL back to zero) which is not _quite_
within the standard. I can't think of any reason why any C implementation
would _not_ do this, but it isn't exactly required.
It's because some implementations may have pointer representations that are
larger than the largest integral type. Trying to do a numeric cast would
result in loss of representation and/or an overflow.
Post by Bill Bumgarner
The standard requires pointers to be castable to an integral type of some
size (the size is implementation-dependent), and that that integer can be
cast back to a pointer and it is guaranteed that the pointer will be the
same as the original. (The mapping must be reversible.)
Are you sure about that?
Post by Bill Bumgarner
I hope this descent into language lawyer pedantry has been useful.
Better than the alternative discussion about LISP, no?

-Chuck

Charles Swiger | ***@codefab.com | Yeah, yeah-- disclaim away.
----------------+-------------------+----------------------------
You have come to the end of your journey. Survival is everything.
David Young
1998-12-16 15:21:39 UTC
Permalink
Ronald C.F. Antony
1998-12-16 15:31:31 UTC
Permalink
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
nil == 0
courtesy of C's casting.
Nil, nil, null, 0, NO, FALSE are all transparently casted to the same thing,
and I may add, intentionally so, because it allows for using return values
and counts as boolean functions.
This is actually very similar to the LISP way of dealing with nil.

Ronald
==============================================================================
"The reasonable man adapts himself to the world; the unreasonable one persists
in trying to adapt the world to himself. Therefore all progress depends on the
unreasonable man." G.B. Shaw | ***@cubiculum.com | NeXT-mail welcome
Bill Bumgarner
1998-12-16 17:53:50 UTC
Permalink
Is it still the case that an expression like:

float f = [*nil object reference* floatValue];

returns an undefined value?

--- background follows for those new to ObjC ---

The fact that any invocation of a method on nil returns nil/Nil/null/0/NO/FALSE is
by design, but coincidental across those types. Basically, the way a stack frame
is constructed, there is typically [on a 32 bit system] 4 bytes for return value,
4 bytes for stack pointer, and the arguments (4 bytes for self, 4 bytes for
selector, rest-o-args).

As such, the various forms of zero Ronald mentioned are not transparently cast to
the same thing-- the invoked method's declaration must much the type of the left
hand sign of the assignment (or the subexpression).

An invocation attempt on a nil object merely means that the return value on the
stack is set to zero-- the compiler takes care of reading only the appropriate
number of bits from the return value. It isn't really a true cast in that there
is no conversion on either end!

The undefined value problem arises when the return value does not fit into a
single 4 byte value on the stack-- at that point, gcc uses indirection (i believe)
to pass the return value back to the caller.... and, when nil is invoked,
objc_msgSend() doesn't necessarily zero out *all* of the return value, just the
part on the stack!

Somebody please correct that last paragraph... i am not really confortable with
that explanation.

b.bum
Post by Ronald C.F. Antony
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
nil == 0
courtesy of C's casting.
Nil, nil, null, 0, NO, FALSE are all transparently casted to the same thing,
and I may add, intentionally so, because it allows for using return values
and counts as boolean functions.
This is actually very similar to the LISP way of dealing with nil.
Ronald
==============================================================================
"The reasonable man adapts himself to the world; the unreasonable one persists
in trying to adapt the world to himself. Therefore all progress depends on the
Eric Hermanson
1998-12-16 17:42:22 UTC
Permalink
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
As far as I know, sending a message, which is typed to return a scalar,
to nil will return an unpredictable result. This has been discussed
several times in many of the "OpenStep" archives - please search the
archives. But the general rule is:

1. [<nil> methodReturningObject] == nil

2. [<nil> messageReturningScalarType] == undefined (i.e. don't rely on
this being nil). Instead, check for the object's existence before
sending the message, e.g.

if(object && [object methodReturningScalarType]) .......


- Eric
John Jay Feiler
1998-12-16 18:01:58 UTC
Permalink
If you do the following:


NSLog( "%@ %d", 0, 0 )


You will get "*nil* 0", because the %@ formatting "operator" implies
sending the method -description to the argument in question, unless the
argument is nil, in which case it prints "*nil*"


J
Sean Luke
1998-12-16 18:30:35 UTC
Permalink
Post by Ronald C.F. Antony
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
nil == 0
courtesy of C's casting.
Nil, nil, null, 0, NO, FALSE are all transparently casted to the same thing,
and I may add, intentionally so, because it allows for using return values
and counts as boolean functions.
This is actually very similar to the LISP way of dealing with nil.
As the Official Disagree With Ronald Guy on the list, let me delurk really
quickly to say that it *is* true that many older Lisp functions do use nil
as "false" (and t as "true"). However nil != 0 (or as Lispers say it,
nil /= 0), and Lisp (CLOS) messages cannot be sent to nil with default
expectations as in Objective-C. nil is the empty list, '(), a data type
all its own.

Sean
Ronald C.F. Antony
1998-12-16 18:58:29 UTC
Permalink
Post by Sean Luke
Post by Ronald C.F. Antony
Won't [[self selectedObjectArray] count] where [self
selectedObjectArray] is nil return nil, not 0!
nil == 0
courtesy of C's casting.
Nil, nil, null, 0, NO, FALSE are all transparently casted to the same
thing, and I may add, intentionally so, because it allows for using return
values and counts as boolean functions.
This is actually very similar to the LISP way of dealing with nil.
As the Official Disagree With Ronald Guy on the list, let me delurk really
quickly to say that it *is* true that many older Lisp functions do use nil
as "false" (and t as "true"). However nil != 0 (or as Lispers say it,
nil /= 0), and Lisp (CLOS) messages cannot be sent to nil with default
expectations as in Objective-C. nil is the empty list, '(), a data type
all its own.
You said it all with this: "As the Official Disagree With Ronald Guy".
I have neither stated nor implied it's the same. I said it's very
similar. It is very similar, since nil can be used to abort recursive
function calls, etc. in a very elegant way. LISP is a functional
language, and the idea of "sending messages" is not even something that's
native to LISP. In LISP the natural data type is the list, and
the fact that an empty list can pose as false boolean value is
thus very similar to ObjC, where the natural data type is an object,
and where a null object can assume the function of a false boolean
value.

If you can't see the similarity between, then I'm sorry for you.

Ronald
==============================================================================
"The reasonable man adapts himself to the world; the unreasonable one persists
in trying to adapt the world to himself. Therefore all progress depends on the
unreasonable man." G.B. Shaw | ***@cubiculum.com | NeXT-mail welcome
Sean Luke
1998-12-16 19:19:17 UTC
Permalink
Oops...
(or as Lispers say it, nil /= 0)
Before I get zinged on it, that oughta be: (not (eql nil 0))

:-)

Sean
Sean Luke
1998-12-16 19:50:10 UTC
Permalink
Post by Ronald C.F. Antony
You said it all with this: "As the Official Disagree With Ronald Guy".
I have neither stated nor implied it's the same. I said it's very
similar... LISP is a functional language, and the idea of "sending
messages" is not even something that's native to LISP... In LISP the
natural data type is the list, ... If you can't see the similarity
between, then I'm sorry for you.
Wow, you have a, um, very '70s view of Lisp. Kinda quaint actually. Any
modern implementation of Lisp is CLTL2-compliant (including, at the very
least, Franz Allegro, and Macintosh Common Lisp), which is structured
around CLTL2 CLOS generic functions, which is the only reasonable
comparison to Objective-C anyway. If you're still stuck in the '70s, then
I'm sorry for you :-)

"Sending messages" is most certainly something that's elegantly done with
OOP general functions in a functional language like CLTL2 Lisp. As I read
it, you had kinda implied that it Lisp nil was similar to Objective-C's
nil in a way that Java null was not. I said that like Java (and unlike
Objective-C) Lisp nil can't be sent messages by default. So let's put
that to the test:

(defclass myclass () ()) ; declare the class myclass

(defmethod mymethod ((obj myclass)) 't) ; declare the myclass method mymethod
; which just returns t when called

(let ((inst (make-instance 'myclass))) ; instantiate a myclass
(print (mymethod inst)) ; call mymethod on it
(print (mymethod nil))) ; call mymethod on nil

=======
RESULTS
=======

T ; the myclass instance returns t

Error: No methods applicable for generic function
#<STANDARD-GENERIC-FUNCTION MYMETHOD> with args (NIL) of classes
(NULL)
[condition type: PROGRAM-ERROR] ; nil gives an error when its
; mymethod is called


...just like Java, and unlike Objective-C.

...Sean, who's still thinking of writing a CLOS front-end to Yellow Box,
wow that'd be really cool...
***@cs.umd.edu
Ronald C.F. Antony
1998-12-16 21:42:33 UTC
Permalink
Post by Sean Luke
Post by Ronald C.F. Antony
LISP is a functional language, and the idea of "sending
messages" is not even something that's native to LISP... In LISP the
natural data type is the list
Wow, you have a, um, very '70s view of Lisp. Kinda quaint actually.
Hardly. Scheme is e.g. rather modern, and is not CLOS based or compliant.
Besides, CLOS is an extension to LISP, the same way ObjC is an extension
of C. If I talk about C, I don't mean ObjC, and if I talk about Lisp, then
I'm not talking about CLOS, and much more likely are not even talking
about any particular LISP dialect, but the concepts all of the different
Lisp versions (Emacs-Lisp, Scheme, Guile, scmsh, CommonLisp, etc.) share.
CLOS is certainly not part of that set of features.
Post by Sean Luke
Any modern implementation of Lisp is CLTL2-compliant (including, at the very
least, Franz Allegro, and Macintosh Common Lisp), which is structured
around CLTL2 CLOS generic functions,
This is a rather narrow view of both the terms "Lisp" and "modern".
Post by Sean Luke
which is the only reasonable comparison to Objective-C anyway.
Pure conjecture. Besides, I have not compared one language with another,
but a particular behavior with an analog, but not identical (i.e. similar)
one in each of the two languages.
Post by Sean Luke
As I read
it, you had kinda implied that it Lisp nil was similar to Objective-C's
nil in a way that Java null was not.
I didn't say that ANYWHERE. As a matter of fact, I wasn't talking about
Java anywhere. My post was simply explaining why [nil count] happens
Post by Sean Luke
Post by Ronald C.F. Antony
nil == 0
courtesy of C's casting.
Nil, nil, null, 0, NO, FALSE are all transparently casted to the same
thing, and I may add, intentionally so, because it allows for using return
values and counts as boolean functions.
This is actually very similar to the LISP way of dealing with nil.
And as I was taught English, "this" always refers to the previous noun,
subphrase, etc. i.e. in this case to "because it allows for using return
values and counts as boolean functions." Which is exactly how nil in
Lisp is used: a return value "empty list" can be used to indicate a
negative truth value in a conditional.
Post by Sean Luke
I said that like Java (and unlike Objective-C) Lisp nil can't be sent
messages by default.
That was never even at issue, and it's something that is of course true.
I still remember when I was programming in LISP. (As a matter of fact,
it was the first programming language other than HP-41 "assembly" that
I cared to learn. Basic was next out of pure necessity, and I thought it was
disgusting.
I'd rather put this issue to rest.
Post by Sean Luke
...Sean, who's still thinking of writing a CLOS front-end to Yellow Box,
wow that'd be really cool...
There was something like that, ACL for NeXTSTEP. Unfortunately, there
were either some bugs or undocumented hacks in NeXT's runtime, and NeXT
never bothered to sit together with Franz' engineers to resolve the
issue.

Ronald
==============================================================================
"The reasonable man adapts himself to the world; the unreasonable one persists
in trying to adapt the world to himself. Therefore all progress depends on the
unreasonable man." G.B. Shaw | ***@cubiculum.com | NeXT-mail welcome
Sean Luke
1998-12-16 22:32:12 UTC
Permalink
[This has gotten totally off-topic, so it'll be my last posting on the
subject...]
Post by Ronald C.F. Antony
Post by Sean Luke
Wow, you have a, um, very '70s view of Lisp. Kinda quaint actually.
Hardly. Scheme is e.g. rather modern, and is not CLOS based or compliant.
Sure, Lisp as an old and storied history, being the second oldest
high-level language still in use. But if you ask an AI or language
researcher (like me) what "Lisp" is, we'll point you to CLTL2. Not Emacs'
odd little customized Lisp, and definitely not Scheme. Even Guy Steele
will point you to CLTL2, and he's the codesigner of Scheme *and* CLTL2.
Next you'll be telling me OOP by general consent doesn't include Simula
and C++. Oh, wait a minute :-) :-)
Post by Ronald C.F. Antony
Besides, CLOS is an extension to LISP, the same way ObjC is an extension
of C....
You've not been working with Lisp lately, I take it. In fact, many modern
implementations of Lisp, such as Macintosh Common Lisp, use CLOS to handle
almost all of their low-level nonatomic objects, everything from arrays to
streams to thrown exceptions to strings. The entire standardized
exception-handling system is in CLOS. The type recognition system has
been rewritten in CLOS. This is pretty low-level stuff.
Post by Ronald C.F. Antony
Post by Sean Luke
Any modern implementation of Lisp is CLTL2-compliant (including, at the very
least, Franz Allegro, and Macintosh Common Lisp), which is structured
around CLTL2 CLOS generic functions,
This is a rather narrow view of both the terms "Lisp" and "modern".
CLTL2 is _the_ ANSI-standardized Lisp specification. I know of no current
non-freeware implementation of Lisp which hasn't moved to CLTL2 many moons
ago. No major Lisp project in my department (the largest academic CS
department in the nation, and one of the largest AI groups in the nation)
is being implemented in anything other than CLTL2. All current
non-classified government Lisp projects I know about are done in CLTL2
(don't ask). Cyc is CLTL2. KQML and KIF are CLTL2. John Koza's GP
system is now CLTL2. Even ancient GCL is being slowly moved to CLTL2 soon
enough, as its CLTL1 compliance has lost its use. Get out of the stone
ages, willya? Next you'll be using K&R function call syntax to prove
points about modern C.
Post by Ronald C.F. Antony
Post by Sean Luke
As I read it, you had kinda implied that it Lisp nil was similar to
Objective-C's nil in a way that Java null was not.
I didn't say that ANYWHERE. As a matter of fact, I wasn't talking about
Java anywhere. My post was simply explaining why [nil count] happens
to return 0.
Recent discussion in the nil-thread to date had been on the fact that [nil
foo] returns nil, as defined in Obj-C, where bar x:=nil; x.foo(); triggers
an exception in Java. In fact, your response had direct bearing on this
([nil count] returns nil, which is defined as 0x0 as it so happens). If
you were responding to something else by coincidence, my apologies.

Sean
Ronald C.F. Antony
1998-12-16 23:42:51 UTC
Permalink
Post by Sean Luke
[This has gotten totally off-topic, so it'll be my last posting on the
subject...]
But if you ask an AI or language researcher (like me)
I hope with "language researcher" you don't refer to computer languages....
Post by Sean Luke
what "Lisp" is, we'll point you to CLTL2. Not Emacs'
odd little customized Lisp, and definitely not Scheme.
As I said, narrow view. Emacs lisp is certainly not the pinacle of
Lisps, but that was also not what I said. There is more than one Lisp,
in particular more than one modern on, Scheme being one of them.
Post by Sean Luke
Even Guy Steele will point you to CLTL2, and he's the codesigner of Scheme
*and* CLTL2.
Well, let's see what he *really* has to say on the subject:
"Small is beautiful, Small is powerful, Small is easy to understand
I like the Scheme programming language, because it is small. It packs
a large number of ideas into a small number of features. [...]
(Scheme) I would call it a toolbox, a large one, filled with a careful
selection of tools that will cover most jobs well, and a few tools whose
primary purpose is to make it easy to make more tools. [...]
Scheme focuses particular attention on the concepts of abstraction
and generality to an extreme unmatched by any other language on my
list. All objects in the language may be named, by a single uniform
naming mechanism. All objects are first class.
In Common Lisp, why are there many namespaces (variables, functions, go
tags, block names, catch tags, ...)? [...]" Guy L. Steele, Jr.

To me that doesn't sound like an unqualified "pointing towards
CLTL2" and even less like an indication that Scheme is anything
but a very modern Lisp.
Post by Sean Luke
Next you'll be telling me OOP by general consent doesn't include Simula
and C++.
That discussion is over, and it was lost by the people who believe that
Simula (and by extension C++) is a OOL. The term object-oriented
was coined by the inventors of SmallTalk, and covers very specific set
of features. The fact that C++ and Simula share a more or less significant
subset of these, doesn't make them OOPLs, and if all the marketing
departments and me-too criers in the world call it otherwise.
Post by Sean Luke
Post by Ronald C.F. Antony
Besides, CLOS is an extension to LISP, the same way ObjC is an extension
of C....
You've not been working with Lisp lately, I take it.
Even in chapter 28 in CLTL2 CLOS is called "an extension". The fact that
it's used in the implementation of Lisp is an implementation detail,
which is not surprising, particularly in view of a long tradition in
Lisp programming to implement things in terms of the language itself.
If you provide an optimized object system, you'd be foolish not to
use it. If you write an ObjC compiler in ObjC, you'd also be stupid
not to use ObjC's features to create a more modular compiler.
ObjC would still remain an extension of C.
Post by Sean Luke
Post by Ronald C.F. Antony
This is a rather narrow view of both the terms "Lisp" and "modern".
CLTL2 is _the_ ANSI-standardized Lisp specification. [...]
Get out of the stone ages, willya?
The fact that CLTL2 is an ANSI standard means nothing. There is also
an ANSI standard for Cobol. That doesn't make it modern. Further,
I have not said that CLTL2 isn't modern, I just asserted that it's
not the only modern Lisp. You have a way to shift the focus of
a debate to ever new subject areas, whenever you're proven wrong
in a point of dispute.

Ronald
==============================================================================
"The reasonable man adapts himself to the world; the unreasonable one persists
in trying to adapt the world to himself. Therefore all progress depends on the
unreasonable man." G.B. Shaw | ***@cubiculum.com | NeXT-mail welcome
Greg Titus
1998-12-17 17:36:24 UTC
Permalink
Post by Ben Moseley
#define nil (id)0 /* id of Nil instance */
Of course, this is operating under the assumption that 0 can be cast to a
valid pointer type and thus, (int) 0 == NULL == nil. There's nothing in
ANSI-C that guarantees that this is the case, and it's conceivable that some
hardware variants would break.
Sorry, this is just wrong. There is exactly such an ANSI-C loophole. K&R
2nd Edition (ANSI C) page 198, section A6.6:

...
An integral constant expression with value 0, or such an expression cast to
type void *, may be converted, by a cast, by assignment, or by comparison,
to a pointer of any type. This produces a null pointer that is equal to
another null pointer of the same type, but unequal to any pointer to a
function or object.
...

It is the other way around (casting NULL back to zero) which is not _quite_
within the standard. I can't think of any reason why any C implementation
would _not_ do this, but it isn't exactly required. The standard requires
pointers to be castable to an integral type of some size (the size is
implementation-dependent), and that that integer can be cast back to a pointer
and it is guaranteed that the pointer will be the same as the original.
(The mapping must be reversible.)

My reading of the reference, though, would not prohibit a C implementation
from casting a NULL back to a non-zero integer, as long as _that_ integer,
as well as zero, results in a NULL pointer when cast back. So:
(void *)0 /* must equal NULL */
ptr1 = (void *)i = (some_possibly_big_int)ptr2; /* ptr1 must == ptr2 */
(s_p_b_i)NULL /* could be 3812398 as long as (void *)3812398 == NULL */

I hope this descent into language lawyer pedantry has been useful.

--Greg

Greg Titus
Omni Development Inc.
***@omnigroup.com
Peter Berger
1998-12-17 17:38:53 UTC
Permalink
Post by Ronald C.F. Antony
Post by Sean Luke
[This has gotten totally off-topic, so it'll be my last posting on the
subject...]
And this will be mine.
Post by Ronald C.F. Antony
Lisps, but that was also not what I said. There is more than one Lisp,
in particular more than one modern on, Scheme being one of them.
Scheme is not Lisp, by any reasonable definition. If you are saying
that Scheme is Lisp, you are wrong. This was Sean's entire point.

Your excerpted paragraph from Guy Steele's introduction (good book, BTW)
proves that Guy Steele likes Scheme. No one said he didn't. What we
-did- say is that Guy Steele, and everyone else in the world -- except
you, apparently -- would never say that Scheme is Lisp. Your excerpt
doesn't do anything, whatsoever, to disprove that truth.

So can we drop it, already?

-pete
Ronald C.F. Antony
1998-12-17 21:26:19 UTC
Permalink
Post by Peter Berger
Scheme is not Lisp, by any reasonable definition. If you are saying
that Scheme is Lisp, you are wrong. This was Sean's entire point.
That's just plain false. Lisp is a family of languages, that happens
to also contain the ANSI standard called Common Lisp. Claiming that
Scheme isn't Lisp is like saying that K&R-C isn't C, just because it's
not ANSI-C.
Post by Peter Berger
Your excerpted paragraph from Guy Steele's introduction (good book, BTW)
proves that Guy Steele likes Scheme. No one said he didn't. What we
-did- say is that Guy Steele, and everyone else in the world -- except
you, apparently -- would never say that Scheme is Lisp.
Well, I guess I have to quote Guy Steele once more, to stop the disemination
of outright disinformation:
[Steele talking about the various sizes of language specs]:
"Curious, is it not, that the spectrum should be bracketed - or perhaps
I should say paranthesize - by two dialects of Lisp?" (Meaning Scheme
with a 50 page language spec and CL with a 1000+ page language spec)

Further, the book "The Little LISPer" is using exclusively Scheme, not
CL. Guess they got the title wrong, he?

The book "Structure and Interpretation of Computer Programs" by Abelson
and Sussman is using Scheme as language and says about it: "In teaching
our material we use a dialect of the programming language Lisp." and
in general talk often about Lisp and Scheme in a fully interchangable
way.

Do you need more evidence, that your assertion that Scheme isn't Lisp
is DEAD WRONG?

You may not agree with what I say, and that's your right. But if you
want to turn that into a virtual witch-hunt whereby you try to
make me look incompetent by spreading false information, then I will
will have to reply to it, even if this thing is totally off-topic
for this list. Can we stop it now? Yeah?

Ronald
==============================================================================
"The reasonable man adapts himself to the world; the unreasonable one persists
in trying to adapt the world to himself. Therefore all progress depends on the
unreasonable man." G.B. Shaw | ***@cubiculum.com | NeXT-mail welcome
David T. McWherter
1998-12-17 19:51:18 UTC
Permalink
Chuck Swiger
1998-12-17 22:39:58 UTC
Permalink
The issue of messaging nil objects seems to be on-topic for MOXS
development, but can I suggest that the C semantics of NULL is drifting
off-topic and should be taken to email?
Of course, this is operating under the assumption that 0 can be cast to a
valid pointer type and thus, (int) 0 == NULL == nil. There's nothing in
ANSI-C that guarantees that this is the case, and it's conceivable that
some hardware variants would break.
Hmmm...don't quite get your (int) 0 ... thing
Fair enough-- I wasn't being clear, and (duh!) it's obviously wrong to say
that you can't cast 0 to NULL.

ANSI says 0 -> NULL, but it's not guaranteed that NULL -> 0. So it's not
guaranteed that 0 == NULL. That's "==" as in "is equivalent to" and not "the
C operator for assignment" or BNF or whatever.

[ ... ]
"it is guaranteed that assignment of the constant 0 to a
pointer will produce a null pointer distinguishable from
a pointer to any object.
Right, but note that using assignment implicitly performs a cast.

In the case of messaging a nil object, the compiler doesn't know that the
callee is not returning an value of the expected type. So the compiler will
not generate the appropriate code in the caller to cast the return value.

So your program may demonstrate what marketing calls "undocumented features". :-)

[ ... ]
What if the size of the double and int aren't the same - you might
only be assigning 0 to a portion of the double object...alignment
might cause other things to happen...A memset(&f, 0, sizeof(f));
Good point; switch f to be a float for a 32-bit platform.
might test your theory better...but I'm not sure if the casts
you're playing are defined at all in the ANSI standard...
They certainly aren't. That's why I did the pointer typecasting and
dereference, in order to avoid the standard C conversions. Anyway, my point
here was more to check on someone else's message where a float with all bits
zero was NaN. Shrug....

-Chuck

Charles Swiger | ***@codefab.com | Yeah, yeah-- disclaim away.
----------------+-------------------+----------------------------
You have come to the end of your journey. Survival is everything.
Giulio Cesare Solaroli
1998-12-17 19:30:40 UTC
Permalink
Hi,

I have downloaded the patch of CVS available on the CodeFab site, but I
have some troble adding *.nib files to the repository.
I am using NT4 and WebObejcts4.0 beta 2.

Everything else seems to work correctly, but I keep receiving this message
when ever I try to insert a nib file:

cvs [import aborted]: cannot lstat Bonita.nib: No such file or directory

Any idea of what could I have done wrong?

I am new to CVS; I am reading all the documentation I could find, but it is
quite easy to overlook something.

Thanks for your attention.

Giulio Cesare Solaroli
Bill Bumgarner
1998-12-17 22:08:27 UTC
Permalink
(1) are you using CVS in client/server or pserver mode? Wrappers don't work in
local mode....

(2) Try applying the -t flag; it'll give you a trace of what cvs is doing and
give a better idea as to what is going on.

(3) did you install the CVSROOT/cvswrappers file into CVSROOT properly?

(4) did you install the CVSROOT/cvswrappers onto your NT machine in the
appropriate spots?

b.bum
Post by Giulio Cesare Solaroli
Hi,
I have downloaded the patch of CVS available on the CodeFab site, but I
have some troble adding *.nib files to the repository.
I am using NT4 and WebObejcts4.0 beta 2.
Everything else seems to work correctly, but I keep receiving this message
cvs [import aborted]: cannot lstat Bonita.nib: No such file or directory
Any idea of what could I have done wrong?
I am new to CVS; I am reading all the documentation I could find, but it is
quite easy to overlook something.
Thanks for your attention.
Giulio Cesare Solaroli
Georg Wallmann
1998-12-18 10:06:15 UTC
Permalink
<fontfamily><param>Helvetica</param>> ANSI says 0 -> NULL, but it's not guaranteed that NULL -> 0. So it's not
Post by Chuck Swiger
guaranteed that 0 == NULL. That's "==" as in "is equivalent to" and not "the
C operator for assignment" or BNF or whatever.
It's my absolutely <bold>private</bold> notion, that a machine, where the NULL pointer does not get encoded as all binary zeroes, is a piece of &%@! ...and that it should die a quick and mercyful death (which I might further in writing incompatible code :)


In that spirit :) "Merry Christmas" to you all


Nat!
Chris Hanson
1998-12-17 22:01:15 UTC
Permalink
I believe the Symbolics Genera C compiler used a reference to the pair (
NIL . NIL ) at the null pointer, because the Genera operating system and
their hardware were both almost 100% Lisp-based (with the rest in assembly
for a Lisp-centric processor). I don't know how ANSI their compiler was
though.

The moral of this story: Don't rely on side effects and undocumented
behavior. Ever. Even with Yellow Box/OpenStep; after all, GNUstep might
do things differently, and you don't want to rule out porting your code to
Linux and other non-MacOS X Unix platforms, do you?
Fabien Roy
1998-12-18 23:56:29 UTC
Permalink
Not sure, exactly. It might help to step through the code
in gdb - use the 'stepi' command along with 'info reg <regname>'
commands to see what's going on. But, don't forget - the
results are seemingly unspecified, so who knows what the
compiler is doing...it may even conveivably not even be doing
an assignment...hmmm...
If you find out, let me know.
-David
It seems that this is completely handled by the compiler.
exerpt from the code

NSArray *myArray= nil;
MyNSObject *myObject=nil;
float myFloat;
double myDouble;

myFloat = [myObject myFloatValue]; <--- first break here

(gdb) Reading in symbols for NilObject_main.m...done.
Breakpoint 1 at 0x4173: NilObject_main.m:17.

Then run

(gdb) r
Starting program: /tmo/NilObject/NilObject.debug/NilObject

Breakpoint 1, main (argc=1, argv=0xbffff864) at NilObject_main.m:17
(gdb)

break in objc_msgSend (the * is needed here)
Breakpoint 2 at 0x5005f20
(gdb)

Continue

(gdb) c
Continuing.

Breakpoint 2, 0x5005f20 in objc_msgSend ()
(gdb)

Now print the Object
(gdb) p (struct Object *)*($sp + 4)
$1 = (struct Object *) 0x0

Now print the selector:

(gdb) p (char *) sel_getName((unsigned)*($sp + 8))
$3 = 0x813c "myFloatValue"

So it seems that the compiler (or runtime) has enough information
i.e. first a nil object and second a selector.
That's why we need a cast for the compiler:
[(MyNSObject *)0x0 myFloatValue]


---
Fabien L Roy NationsBanc Montgomery Securities, LLC
voice: (704)386-75-76 100 North Tryon Street
fax: (704)388-95-64 NC1-007-09-08
Charlotte NC 28255
Beeper: 143-9722 (1-800-946-46-46) or
http://www.MobileComm.com/message/
email: ***@ncmi.com (NeXT/Mime)
Pager-email ***@mobilecomm.net

Continue reading on narkive:
Loading...