Topic: Nested functions (was: Zero-length structures and pointer comparisons)
Author: pabloh@hpwala.wal.hp.com (Pablo Halpern )
Date: Mon, 11 Jan 1993 23:15:23 GMT Raw View
In article <1993Jan06.193256.6590@microsoft.com>, jimad@microsoft.com (Jim Adcock) writes:
|> In article <4048@hpwala.wal.hp.com> pabloh@hpwala.wal.hp.com (Pablo Halpern ) writes:
|> |Absolute orderings are a slightly different matter. In the case of < and
|> |>, one might expect a significant performance improvement if the pointers
|> |are assumed to point into the same array, since the segment part can be
|> |ignored even for far pointers. A ptrcmp() function might be worthwhile and
|> |should present no special implementation problems for segmented
|> |architectures. However, systems (like the lisp machine) where pointers
|> |change behind the program's back DO present a problem since the
|> |bit-pattern-based ordering could change even if the equality/inequality
|> |property does not change. This would argue against *requiring* a ptrcmp()
|> |function.
|>
|> Except some OS's using segmented architectures implement movable segments,
|> in which case the problem becomes the same as lisp machines --
|> "pointers change behind the programmers back"
Perhaps, but not usually. Part of the power of segments is to be able to
change the physical location of a segment without changing pointers to that
segment. Never the less, the problem DOES exist on some architectures,
both segmented and not.
|>
|> My claim is that in either of these cases the pointers *aren't* changing --
|> they still point at the same objects. What is changing is the underlying
|> implementation of the pointer, which is an implementation issue not
|> a language issue. Casting pointers to and from int remains as always
|> implementation dependent. The only issue in question is whether we
|> should introduce a new requirement on OS's that the OS must maintain
|> a total ordering on their objects. Clearly IMHO this would represent
|> a stumbling block to many OS's, such a the lisp machines, movable segment
|> OS's and OO databases. Making such a new requirement on C++ would make
|> C++ not reasonably portable to these systems. The question then is
|> whether or not the standard C++ language should exist on such machines.
Exactly. Maintaining a total ordering of objects based on pointers to
those objects is not resonable in some OS's. IMHO, the need for a total
ordering of pointers is not as compelling as the ability to implement the
C++ standard on the widest variety of architectures. A function like
ptrcmp() should fall into the "common extentions" catagory. Most
systems could implement this function using a varient bit-by-bit
comparison. Systems that patch pointers in running code could not
implement this function.
--
- Pablo
------------------------------------------------------------------------
Pablo Halpern (617) 290-3542
HP Waltham pabloh@hpwarq.wal.hp.com
I am self-employed, so my opinions *do* reflect those of my employer.
However, they may not reflect the opinions of my client.
------------------------------------------------------------------------
Author: pabloh@hpwala.wal.hp.com (Pablo Halpern )
Date: Mon, 4 Jan 1993 23:13:10 GMT Raw View
In article <BzDJHu.t2@frumious.uucp>, pat@frumious.uucp (Patrick Smith) writes:
|> Surely one would want to insist on
|>
|> p == q => ptrcmp(p,q) == 0
|>
|> If this weren't true, one wouldn't be able to use ptrcmp as a basis
|> for organizing an ordered binary tree for searching. Are there any
|> likely-to-be-common uses of ptrcmp which don't need this assumption?
|>
|> Unfortunately, meeting this condition might be expensive on
|> segmented architectures (according to the many other postings
|> on this subject).
I've had it! Enough blathering about what might be possible or expensive
on segmented architectures! A segmented architecture does not present as
many difficulties as some people think. In a segmented machine, like the
80x86, pointers can be divided into two catagories:
a) Segment with offset ("far" pointers)
b) Offset-only ("near" pointers)
In what is commonly called the "large memory model," only far pointers
are found. In the "small memory model," only near pointers are found.
It is valid to use both near and far pointers in the same program.
Far pointers present no special difficulties for equality tests unless
operating-system operations map multiple segments to the same memory
location, in which case the program is no longer strictly conforming.
(Normalizing pointers, a practice used in some 8086 C compilers, is not
usually necessary. A compiler that normalizes must also pay the price with
a more complicated equality check.)
Near pointers present a problem at first glance, because the segment
information seems to be missing. But that ignores a fundamental fact about
near pointers:
A pointer can be represented as an offset without a segment IF AND
ONLY IF THE SEGMENT IS KNOWN OR IMPLIED BY CONTEXT.
This means that the compiler can always know the segment part of a near
pointer. Consider the following code:
void* memcpy(void* s1, const void* s2, size_t n);
...
int *px, *py;
int s;
...
memcpy(x, y, s);
Assume px and py are near (offset-only) pointers.
At the point that memcpy is called, px and py might have the same offset.
In order for memcpy to work (and it MUST work if this is a conforming
implementation), either px and py must point into the same segment, OR the
compiler must be able to determine the correct segment for each. In the
latter case, the segment information must be supplied to memcpy, e.g. in
the conversion from int* to void*. The important thing to note is that
memcpy CAN distiguish px from py even if they have the same offset.
SOOO... It is already a requirement that two pointers to different objects
must be distinguishable. It is therefore easy to meet a requirement that
pointers to *different* objects must compare *unequal*. More difficult, in
light of normalization and OS hanky-panky, is the current ARM requirement
that pointers to the *same* object must compare *equal*. However as I
stated earlier, OS hanky-panky is non-conforming and normalization is an
implementation decision that carries the price of slower pointer
comparisons.
Absolute orderings are a slightly different matter. In the case of < and
>, one might expect a significant performance improvement if the pointers
are assumed to point into the same array, since the segment part can be
ignored even for far pointers. A ptrcmp() function might be worthwhile and
should present no special implementation problems for segmented
architectures. However, systems (like the lisp machine) where pointers
change behind the program's back DO present a problem since the
bit-pattern-based ordering could change even if the equality/inequality
property does not change. This would argue against *requiring* a ptrcmp()
function.
--
- Pablo
------------------------------------------------------------------------
Pablo Halpern (617) 290-3542
HP Waltham pabloh@hpwarq.wal.hp.com
I am self-employed, so my opinions *do* reflect those of my employer.
However, they may not reflect the opinions of my client.
------------------------------------------------------------------------
Author: jimad@microsoft.com (Jim Adcock)
Date: 06 Jan 93 19:32:56 GMT Raw View
In article <4048@hpwala.wal.hp.com> pabloh@hpwala.wal.hp.com (Pablo Halpern ) writes:
|Absolute orderings are a slightly different matter. In the case of < and
|>, one might expect a significant performance improvement if the pointers
|are assumed to point into the same array, since the segment part can be
|ignored even for far pointers. A ptrcmp() function might be worthwhile and
|should present no special implementation problems for segmented
|architectures. However, systems (like the lisp machine) where pointers
|change behind the program's back DO present a problem since the
|bit-pattern-based ordering could change even if the equality/inequality
|property does not change. This would argue against *requiring* a ptrcmp()
|function.
Except some OS's using segmented architectures implement movable segments,
in which case the problem becomes the same as lisp machines --
"pointers change behind the programmers back"
My claim is that in either of these cases the pointers *aren't* changing --
they still point at the same objects. What is changing is the underlying
implementation of the pointer, which is an implementation issue not
a language issue. Casting pointers to and from int remains as always
implementation dependent. The only issue in question is whether we
should introduce a new requirement on OS's that the OS must maintain
a total ordering on their objects. Clearly IMHO this would represent
a stumbling block to many OS's, such a the lisp machines, movable segment
OS's and OO databases. Making such a new requirement on C++ would make
C++ not reasonably portable to these systems. The question then is
whether or not the standard C++ language should exist on such machines.
Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: 20 Dec 92 14:33:22 GMT Raw View
>
>What can nested functions do that OO features of C++ can't? Use
>of nested functions sounds like you may be trying to delegate
>implementation, which is a great use for objects.
>
What nested functions allow you to do that you cant with objects
is take a function that is getting to big and decompose it rapidly
and reliably into several smaller functions.
The second thing you can do is rapidly and reliably factor
out common pieces of code, again to reduce the size of a function,
improve readability and reliability.
One can then later reorganise so the functions are put
into a class instead of a function, however this is a much bigger
job, and it tends to enforce design decisions when one would
prefer to defer them. And when one does finally 'objectify'
the code, it would be nice to have the nested functions
already there waiting to be turned into members,
instead of having to do functional and data decomposition
simultaneously.
There are times when procedural code is much cleaner
than using objects. For example, when one has some objects
with complex links between them (including mutual self reference),
it is often easier to just make the objects raw and then stick
all the pointers in. Doing it with constructors is quite tricky,
especially considering that some of the pointers dont exist yet,
and the initialisation code is spread all over the place
like spagetti. This is particularly true while rapid prototyping.
There's also a couple of technical advantages to
having nested functions even when coding
member functions, over adding a private helper member, one being
that the class interface doesnt have to be changed.
I've mentioned all these things, because I've just
gone through the process of taking a parser function
and turning it into an object. It took longer to
do this than write the original procedural code.
I had to do it, but I would have prefered to be able to
do some functional decomposition first, I think the whole
process would have been quicker.
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: chased@rbbb.Eng.Sun.COM (David Chase)
Date: 16 Dec 1992 23:47:32 GMT Raw View
In article <24413@alice.att.com> ark@alice.UUCP () writes:
>The first time I tried to use gcc's nested functions,
>my program dumped core -- apparently due to a bug in gcc.
>The next version of gcc I tried worked. This suggests
>that the implementation isn't exactly trivial.
See other post. In our (Olivetti Research Center, now defunct)
experience, nested functions were not hard, though not trivial (is the
compiler that you use made up only of trivial pieces? Somehow, I
doubt it. Keep things in proportion.) We implemented C-interoperable
nested functions in one (68k-only) release of Modula-3, and it was
a relative no-brainer compared to most other parts of a modern
compiler. Keep in mind that gcc 2.* says "beta-test" all over it, so
I am not surprised if a shiny new non-standard feature doesn't work
perfectly.
David Chase
Sun
Author: harvey@opl.com (Harvey Reed)
Date: 17 Dec 92 16:31:56 GMT Raw View
nau@ssesco.com (William Nau) writes:
>>> Why are nested functions so hard? I think that
>>> Gnu C's implementation of nested functions shows that it does not
>>> cause any particularly difficult implementation problems.
>>
[Koenig replied]
>>The first time I tried to use gcc's nested functions,
>>my program dumped core -- apparently due to a bug in gcc.
>>The next version of gcc I tried worked. This suggests
>>that the implementation isn't exactly trivial.
>It suggests that they didn't properly test that release. Given
>a decent design, it's not asking that much out of a high level
>language. It does amaze me that this wonderful object oriented
>language does not allow for nested functions.
What can nested functions do that OO features of C++ can't? Use
of nested functions sounds like you may be trying to delegate
implementation, which is a great use for objects.
--
++harvey
========================================================================
internet: harvey@opl.com / hreed@cs.ulowell.edu / h.reed@ieee.org
voice: 617-965-0220
Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Thu, 17 Dec 1992 20:45:22 GMT Raw View
In article <BzBHn4.26J@ssesco.com> nau@ssesco.com (William Nau) writes:
>
>It suggests that they didn't properly test that release. Given
>a decent design, it's not asking that much out of a high level
>language. It does amaze me that this wonderful object oriented
>language does not allow for nested functions.
>
Some OO people claim nested functions are anathema to
good OO design. I have read the arguments, they relate to
cleanly dividing the problem up, and removing coupling.
Nested function have an implicit interface
(bad design concept) to their enclosing scope.
Not being a religious OO convert, and finding
in practice I could use nested functions here and there,
I would support their introduction, however.
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: michi@ptcburp.ptcbu.oz.au (Michael Henning)
Date: Thu, 17 Dec 1992 23:25:59 GMT Raw View
ark@alice.att.com (Andrew Koenig) writes:
>The first time I tried to use gcc's nested functions,
>my program dumped core -- apparently due to a bug in gcc.
>The next version of gcc I tried worked. This suggests
>that the implementation isn't exactly trivial.
I could also suggest that the implementor was trivial :-)
Michi.
--
-m------- Michael Henning +61 75 950255
---mmm----- Pyramid Technology +61 75 722475 FAX
-----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au
-------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Tue, 15 Dec 1992 08:05:24 GMT Raw View
ark@alice.att.com (Andrew Koenig) writes:
>maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>
>> Do you personally favour nested functions?
>
>In general, yes. For C++, I'm not sure.
>
>> If not, why not?
>
>The main argument against it is that C doesn't have them, which means
>that having them in C++ would make C interoperability more difficult.
>It would also be more difficult to interface C++ programs with
>low-level assembly-language things like on-board controllers. I don't
>care about that personally, but I know that other people do.
I don't see why this is a good counter-argument. After all, C doesn't
have classes, constructors, exceptions, templates, etc., etc., but
we still manage. Why are nested functions so hard? I think that
Gnu C's implementation of nested functions shows that it does not
cause any particularly difficult implementation problems.
--
Fergus Henderson fjh@munta.cs.mu.OZ.AU
This .signature virus is a self-referential statement that is true - but
you will only be able to consistently believe it if you copy it to your own
.signature file!
Author: ark@alice.att.com (Andrew Koenig)
Date: 15 Dec 92 19:37:58 GMT Raw View
In article <9235019.15484@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
> Why are nested functions so hard? I think that
> Gnu C's implementation of nested functions shows that it does not
> cause any particularly difficult implementation problems.
The first time I tried to use gcc's nested functions,
my program dumped core -- apparently due to a bug in gcc.
The next version of gcc I tried worked. This suggests
that the implementation isn't exactly trivial.
--
--Andrew Koenig
ark@europa.att.com
Author: nau@ssesco.com (William Nau)
Date: 15 Dec 92 20:16:15 GMT Raw View
>> Why are nested functions so hard? I think that
>> Gnu C's implementation of nested functions shows that it does not
>> cause any particularly difficult implementation problems.
>
>The first time I tried to use gcc's nested functions,
>my program dumped core -- apparently due to a bug in gcc.
>The next version of gcc I tried worked. This suggests
>that the implementation isn't exactly trivial.
It suggests that they didn't properly test that release. Given
a decent design, it's not asking that much out of a high level
language. It does amaze me that this wonderful object oriented
language does not allow for nested functions.
--
William R. Nau
Supercomputer Systems Engineering and Services Company (SSESCO)
511 11th Avenue South, Suite 216
Minneapolis, Minnesota 55415-1536
(612) 342-0003
nau@SSESCO.com