 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Phlip Guest
|
Posted: Sun Nov 27, 2005 8:42 pm Post subject: Re: Why no local functions ? |
|
|
Timothy Madden wrote:
| Quote: | I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of C++
?
|
Because a language should reserve (most) syntax until it can achieve some
new effect with that syntax.
The best feature for a private method would be a block closure, like this:
void foo() {
int bar = 42;
void thread() {
doSomethingTo(&bar);
}
beginThread(thread);
}
In that example, the inner function thread() can refer to the outer
function's local variable. Without that effect, the nested function syntax
is only syntactic sugar.
However, the C languages use a definition that assists implementors to store
each function invocation's local variables on a hardware stack. This helps
compete with Assembler. Without languages as fast as C++, we would have the
odious choice between rapid development in slow languages like Smalltalk or
Python, or slow development in rapid Assembly code.
In my example, thread()'s access to bar persists after the function foo()
returns. This breaks the deal that 'bar' can live on a hardware stack.
Compiler implementors must find alternative representations for variables,
and must taint every variable used in a closure. The compiler may or may not
know that beginThread() might allow thread() to call after foo() returns, so
the compiler must chose pessimism, and the variable bar would have a lot of
overhead.
Incidentally, in terms of design without regard to performance, block
closures allow a variable like bar to have the longest lifespan with the
narrowest scope, so block closures are good things. We can acheive them with
reference-counted smart pointers. Very-high level languages that provide
block closures give their variables this representation too.
--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
|
|
| Back to top |
|
 |
Timothy Madden Guest
|
Posted: Sun Nov 27, 2005 11:29 pm Post subject: Why no local functions ? |
|
|
Hello all.
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of
C++ ?
There surely are many people who will find them very helpfull. gcc has
them as a non-standard option, but only when compiling C language code,
so I'm afraid there might be some obscure reason why local functions are
not so easy to be dealt with in C++, which I do not yet know.
Anyone knows what is the problem with supporting local functions in C++ ?
Thank you
Timothy Madden
Romania
|
|
| Back to top |
|
 |
davidrubin@warpmail.net Guest
|
Posted: Sun Nov 27, 2005 11:35 pm Post subject: Re: Why no local functions ? |
|
|
What do you mean by 'local' functions? Functions at file scope?
|
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Sun Nov 27, 2005 11:40 pm Post subject: Re: Why no local functions ? |
|
|
* Timothy Madden:
| Quote: |
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of
C++ ?
|
C++ supports local functions in the form of member functions of local
classes.
Such functions do not have access to the enclosing scope's variables,
and in particular they do not have access to the enclosing function's
arguments.
The main reason for that restriction is probably that local functions à
la Pascal are inefficient (they require a linked stack structure, look
up "Dijkstra displays"), not really of any help in solving problems, and
can be easily emulated if you _really_ need them.
Another restriction is that, as I recall, they do not have linkage, e.g.
you cannot use a locally defined function as a template parameter.
I'm not sure of the reason for that latter restriction.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
|
|
| Back to top |
|
 |
Timothy Madden Guest
|
Posted: Mon Nov 28, 2005 12:05 am Post subject: Re: Why no local functions ? |
|
|
Gianni Mariani wrote:
| Quote: | davidrubin (AT) warpmail (DOT) net wrote:
What do you mean by 'local' functions? Functions at file scope?
No, I think he means Pascal like local functions.
e.g.
int f()
{
int i;
void f() // A
{
i = 2; // links to int f()::i
}
f(); // links to int f()::void f()
return i; // returns 2
}
|
Yes, I mean Pascal like local functions. Local functions would indeed
have direct access to all already declared variables and symbols in the
enclosing function, and could be nested on many levels.
They were so cool when I was programming in Pascal and I was sorry to
give them up to switch to C++.
Timothy Madden
Romania
|
|
| Back to top |
|
 |
Timothy Madden Guest
|
Posted: Mon Nov 28, 2005 12:26 am Post subject: Re: Why no local functions ? |
|
|
Alf P. Steinbach wrote:
| Quote: | * Timothy Madden:
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of
C++ ?
C++ supports local functions in the form of member functions of local
classes.
Such functions do not have access to the enclosing scope's variables,
and in particular they do not have access to the enclosing function's
arguments.
The main reason for that restriction is probably that local functions à
la Pascal are inefficient (they require a linked stack structure, look
up "Dijkstra displays"), not really of any help in solving problems, and
can be easily emulated if you _really_ need them.
Another restriction is that, as I recall, they do not have linkage, e.g.
you cannot use a locally defined function as a template parameter.
I'm not sure of the reason for that latter restriction.
|
Yes, exactly. C++ already has static functions in local classes. Why
should it not directly have local functions ?
Would you please explain me why a 'linked stack structure' is
inefficient ? I think this are compiler internals and after all anybody
is free not to use such local functions. Having me to emulate them would
also be inefficient.
How do you find emulating local functions easy ? The only way I know of
is with many arguments passed by reference to a normal C++ function.
I do not like the restriction of having only global or namespace symbols
as possible template arguments, but I can see a reason for it: It allows
a programmer to separate template declarations (in headers) from
template definitions (in special source files) and then only use
explicit template instantiaton, all over an entire project or program.
Explicit instantiations would be all placed in dedicated source files,
that so have guaranteed visibility to all template arguments ever used
(template arguments are allways global or extern symbols). A programmer
might want to take this presumably difficult aproach (to using
templates) as a first step in preparation for switching to a compiler
that supports export, or because the full template definitions are based
on too much code that normaly has to be all included in headers.
By the way: what popular compilers do you know of that support export ?
Thank you
Timothy Madden
Romania
|
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Mon Nov 28, 2005 12:43 am Post subject: Re: Why no local functions ? |
|
|
* Timothy Madden:
| Quote: | Alf P. Steinbach wrote:
* Timothy Madden:
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of
C++ ?
C++ supports local functions in the form of member functions of local
classes.
Such functions do not have access to the enclosing scope's variables,
and in particular they do not have access to the enclosing function's
arguments.
The main reason for that restriction is probably that local functions à
la Pascal are inefficient (they require a linked stack structure, look
up "Dijkstra displays"), not really of any help in solving problems, and
can be easily emulated if you _really_ need them.
Another restriction is that, as I recall, they do not have linkage, e.g.
you cannot use a locally defined function as a template parameter.
I'm not sure of the reason for that latter restriction.
Yes, exactly. C++ already has static functions in local classes. Why
should it not directly have local functions ?
|
That's a good question, if you mean local functions with the same (lack
of) access. But it's no big deal to wrap it in a class.
| Quote: | Would you please explain me why a 'linked stack structure' is
inefficient ?
|
It has to be linked... ;-)
I'm not sure exactly how inefficient this is.
| Quote: | How do you find emulating local functions easy ? The only way I know of
is with many arguments passed by reference to a normal C++ function.
|
You can collect those many arguments in one argument.
| Quote: | By the way: what popular compilers do you know of that support export ?
|
Comeau. Also it's said there's an undocumented compiler switch for the
Intel compiler where you can turn on the 'export' feature. And
apparently Borland tried it out as a beta feature but didn't go for it.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
|
|
| Back to top |
|
 |
Gianni Mariani Guest
|
Posted: Mon Nov 28, 2005 12:56 am Post subject: Re: Why no local functions ? |
|
|
[email]davidrubin (AT) warpmail (DOT) net[/email] wrote:
| Quote: | What do you mean by 'local' functions? Functions at file scope?
|
No, I think he means Pascal like local functions.
e.g.
int f()
{
int i;
void f() // A
{
i = 2; // links to int f()::i
}
f(); // links to int f()::void f()
return i; // returns 2
}
|
|
| Back to top |
|
 |
Timothy Madden Guest
|
Posted: Mon Nov 28, 2005 1:15 am Post subject: Re: Why no local functions ? |
|
|
Phlip wrote:
| Quote: | Timothy Madden wrote:
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of C++
?
Because a language should reserve (most) syntax until it can achieve some
new effect with that syntax.
The best feature for a private method would be a block closure, like this:
void foo() {
int bar = 42;
void thread() {
doSomethingTo(&bar);
}
beginThread(thread);
}
|
Hey !!!!
That is a logic or semantic error!
My question is more about syntax allowed in C++.
The above code could also trigger a syntax error if compilers implement
the type for expression _&thread_ to be something like void (foo::*)(),
that is even if you take the function's address, the pointer type is
still 'pointer to nested function in foo'. Of course beginThread() has a
prototype stating it takes pointers to real functions, since it is
likely to be declared by the library, and foo is likely to be declared
latter in user code.
Timothy Madden
Romania
|
|
| Back to top |
|
 |
Phlip Guest
|
Posted: Mon Nov 28, 2005 1:59 am Post subject: Re: Why no local functions ? |
|
|
Timothy Madden wrote:
| Quote: | Hey !!!!
That is a logic or semantic error!
|
I can't tell if you read my post. I don't give a darn about the binding of
thread(). I discussed the binding of bar.
--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
|
|
| Back to top |
|
 |
Kaz Kylheku Guest
|
Posted: Mon Nov 28, 2005 4:37 am Post subject: Re: Why no local functions ? |
|
|
Timothy Madden wrote:
| Quote: | Hello all.
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of
C++ ?
|
Local functions are useless if you cannot do indrection on them such
that the resulting function pointers carry with them the dynamic
environment instantiated from their lexical scope.
Even if you support downward funargs only, it complicates the
representation of a function pointer. The pointer must carry not only
the address, but additional information about how to locate the
environment for that function call.
If the C language had local functions, programmers would expect to be
able to just use them wherever functions are expected. That is to say,
to write code that accepts function pointer arguments which would work
either with regular functions or local functions.
The obvious way to do that is to represent regular old function
pointers the same way as the local function pointers, except that they
have a null environment.
This goes against the "don't pay for what you don't use" principle.
C doesn't have local functions, and C++ is based on C. Not enough
people were shouting loud enough for C++ to get local functions. And
C++ is also deliberately backward-compatible with C. If C++ had local
functions and pointers to local functions, there would still be a need
to have ordinary pointers to functions that are C compatible (i.e.
represented as straight machine addresses and nothing but, if that's
what the C compilers do on a given platform).
So if there are ever going to be local functions in C++, there will
have to be some special syntax for indirecting upon them, the same way
that there is special syntax (pointer ot member) for indirecting on
member functions.
There are similarities between closures and member functions. Member
functions need a ``this'' pointer to locate their environment: their
environment is an explicitly-defined class object. The environment of a
first class function is an instance of the lexical environment spun
into an object, which is also accessed by a kind of ``this'' pointer.
You can emulate closures in C++ using objects, in particular objects
that overload the () operator, which can be regarded as function
objects or functors.
C++ does have local classes: classes defined in a block scope. You can
write a local class which inherits from some functor base class.
Instantiate an object of that class in the same scope and pass it down.
You should even be able to return it. It's not exactly a closure,
because anything you want to "capture" has to be declared as a member
of that object, and initialized through the constructor or whatever
additional means. There is no visibility from the function bodies to
the lexical environment in the surrounding block.
class Function {
public:
virtual int call ()() = 0;
virtual ~Function { }
};
FunctionnBase *MakeCounter(int initialValue)
{
class Counter : public Function {
private:
int count;
public:
Counter(int startingValue) : count(startingValue) { }
int call() {
return ++count;
}
};
return new Counter(initialValue);
}
// ...
Function *counter = MakeCounter(10);
cout << counter->call() << endl; // outputs 10
cout << counter->call() << endl; // outputs 11 ...
I've worked on a project where this technique was used quite
successfully. Such local objects were used in a client middleware to
install handlers for a stateful comunication protocol with a server.
Depending on what commands you sent to the server and in what
situation, you had to handle different kinds of responses in different
ways.
Moreover, you didn't know from what context you were called, so you had
to save and restore your handling object. So the local object was
instantiated from a local class, pushed to the top of a stack of
handlers, and then popped later.
It's not nearly as nice as having real closures, but there it is. Real
closures in C++ would not be that much more convenient than the above,
because of the limitations of static typing and the lack of automated
memory management. What a closure would do is effectively write the
local class for you using the lexical environment as the specification,
so you could eliminate the class declaration and construction steps.
|
|
| Back to top |
|
 |
John Harrison Guest
|
Posted: Mon Nov 28, 2005 8:32 am Post subject: Re: Why no local functions ? |
|
|
Timothy Madden wrote:
| Quote: | Hello all.
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of
C++ ?
There surely are many people who will find them very helpfull. gcc has
them as a non-standard option, but only when compiling C language code,
so I'm afraid there might be some obscure reason why local functions are
not so easy to be dealt with in C++, which I do not yet know.
Anyone knows what is the problem with supporting local functions in C++ ?
Thank you
Timothy Madden
Romania
|
The problem is function pointers.
typedef void (*func_ptr)();
func_ptr return_generator()
{
int n = 0;
int next_int()
{
return n++;
}
return &next_int;
}
return_generator returns a function pointer to a function that accesses
a variable local to return_generator. By the time next_int is executed
that variable will no longer exist. The only way around this would be to
place limits on functions pointers (this is what pascal does), drop the
stack model for local variables (this is what lisp does) or place limits
on local functions (what then is the point).
john
|
|
| Back to top |
|
 |
Kaz Kylheku Guest
|
Posted: Mon Nov 28, 2005 8:34 am Post subject: Re: Why no local functions ? |
|
|
Phlip wrote:
| Quote: | Timothy Madden wrote:
I program C++ since a lot of time now and I still don't know this simple
thing: what's the problem with local functions so they are not part of C++
?
Because a language should reserve (most) syntax until it can achieve some
new effect with that syntax.
The best feature for a private method would be a block closure, like this:
void foo() {
int bar = 42;
void thread() {
doSomethingTo(&bar);
}
beginThread(thread);
}
In that example, the inner function thread() can refer to the outer
function's local variable. Without that effect, the nested function syntax
is only syntactic sugar.
|
That is not true. Your example shows a first-class closure. The
environment in which bar has the value 42 persists even after the
function foo() terminates, allowing the thread to run the function.
You can have ``second class'' closures that are still useful, which can
only be passed down.
Pascal's local functions are like that. They are more than syntactic
sugar, but less than full blown closures.
| Quote: | However, the C languages use a definition that assists implementors to store
each function invocation's local variables on a hardware stack.
|
If you support downward funargs only, everything can still be on the
stack.
| Quote: | This helps
compete with Assembler. Without languages as fast as C++, we would have the
odious choice between rapid development in slow languages like Smalltalk or
Python, or slow development in rapid Assembly code.
|
Python is slow because it's immature implementation technology. There
are implementations of these types of languages that have very good
compilers that put out native machine code.
| Quote: | In my example, thread()'s access to bar persists after the function foo()
returns. This breaks the deal that 'bar' can live on a hardware stack.
|
Correct. However, a decent compiler for a language that has closures
will perform a careful analysis of each lexical scope capsule. It will
identify all of the closures and classify them based on what power they
require. Some closures will disappear entirely. Some can be proved to
be downward funargs only, and some may be found which must be assumed
to escape.
Only those closures which escape break the deal about the hardware
stack.
Rule number one is to have a good compiler.
| Quote: | Compiler implementors must find alternative representations for variables,
and must taint every variable used in a closure. The compiler may or may not
|
After a closure has escaped that captures variable X, and if its body
modifies X, then any escaping function must be assumed to modify X by
means of calling that escaped closure. X can't be cached in a register
across external calls. Is this what taint means?
| Quote: | know that beginThread() might allow thread() to call after foo() returns, so
the compiler must chose pessimism, and the variable bar would have a lot of
overhead.
|
That's right. Because beginThread() is an external call, the closure
passed into it is an escaping closure. Therefore, the environment which
it captures must be allocated in an object that will survive the
termination of the surrounding block.
Even if thread's aren't involved, the external function could stash the
closure somewhere, like in some global variable, and then it could be
called later.
What if the programmer knows that the closure is downward only, but
it's not obvious to the compiler? A declaration mechanism can exist to
express that.
In Common Lisp, for instance, you can use (declare (dynamic-extent
....)). The gist of it is that it tells the compiler about objects that
do not escape and can thus be stack allocated. If they are passed down
somewhere, they are not stashed away, and they are not returned upward
either. By means of this, you can express that a closure is downward
only, and so the bindings that it captures can be on the stack.
``Dynamic extent'' is the Lisp word for what is known as ``automatic
storage duration'' in C.
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Mon Nov 28, 2005 10:48 am Post subject: Re: Why no local functions ? |
|
|
Kaz Kylheku wrote:
| Quote: |
C doesn't have local functions, and C++ is based on C. Not enough
people were shouting loud enough for C++ to get local functions.
|
Yep.
Local functions in *original' PASCAL became necessary to solve
scoping-problems. Original PASCAL had just one translation unit,
so everything had to be squeezed into it. That made programming
'source code libraries' a hard thing, since function name clashes
came into ones way every now and then.
Local functions solved that problem to some extent.
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
| Back to top |
|
 |
Timothy Madden Guest
|
Posted: Mon Nov 28, 2005 12:08 pm Post subject: Re: Why no local functions ? |
|
|
John Harrison wrote:
| Quote: | Timothy Madden wrote:
Hello all.
I program C++ since a lot of time now and I still don't know this
simple thing: what's the problem with local functions so they are not
part of C++ ?
There surely are many people who will find them very helpfull. gcc has
them as a non-standard option, but only when compiling C language
code, so I'm afraid there might be some obscure reason why local
functions are not so easy to be dealt with in C++, which I do not yet
know.
Anyone knows what is the problem with supporting local functions in C++ ?
Thank you
Timothy Madden
Romania
The problem is function pointers.
typedef void (*func_ptr)();
func_ptr return_generator()
{
int n = 0;
int next_int()
{
return n++;
}
return &next_int;
}
return_generator returns a function pointer to a function that accesses
a variable local to return_generator. By the time next_int is executed
that variable will no longer exist. The only way around this would be to
place limits on functions pointers (this is what pascal does), drop the
stack model for local variables (this is what lisp does) or place limits
on local functions (what then is the point).
john
|
I don't think these details really are the problem with local functions.
To clarify, lets say that they work like member functions: they are
defined to be part of the enclosig class and they can only be used in
the context of their class. Memeber functions have a limit placed on the
type of their address, but they are still a good thing.
The same goes with local functions. The type 'pointer to local function'
also holds the enclosing function name. A pointer to global function is
allways compatible with a pointer to local function. However pointers to
global functions can be assigned addresses of global functions only.
When a generic 'pointer to function' is defined in a function, it is
implicitly considered a 'pointer to local function' type. When a generic
'pointer to function' type is defined at global or namespace scope, it
is of course a nomal 'pointer to global function' type.
A function call through a pointer to local function can only be made
while enclosing function is still executing (and has not returned), and
only by other functions also local to the enclosing function or nested
in the enclosing function. The type for the pointer can be exposed and
used outside encosing function, when the function is visible, but no
function call through the pointer can be made outside.
For example:
void RawDataProcessor(int iProcessClass);
void (RawDataProcessor::*PartialProcessor)(int iCrtLevel, int
ProcessSubclass) = NULL;
void RawDataProcessor(int iProcessClass)
{
double a = (iProcessClass + 10) / 3.35;
void SimpleProcessor(int iCrtLevel, int iSubclass)
{
a = (a + 0.7*iCrtLevel) / ((iSubClass + 2)*1.02);
}
void CompoundProcessor(int iCrtLevel, int iSubclass)
{
if (iCrtLevel && iSubclass)
{
iSubclass--;
a = (a + 1.1) / 0.98;
CompoundProcessor(iCrtLevel-1, iSubclass);
}
else
SimpleProcessor(iCrtLevel, iSubclass);
}
void DeriveCodedProcessLevel(int iLevelCode, int iClass)
{
int iLevel = iLevelCode*2 - 3;
::PartialProcessor(iLevel, iClass);
}
if (iProcessClass > 7)
::PartialProcessor = CompoundProcessor;
else
::PartialProcessor = SimpleProcessor;
DeriveCodedProcessLevel(iProcessClass, iProcessClass);
count << "Processor reaches " << a << endl;
}
Here SimpleProcessor and Compound Processor form the internal workings
of public RawDataProcessor, should not be fully exposed to its outside,
and also are not that big as to make RawDataProcessor difficult to read.
Thank you
Timothy Madden
Romania
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|