Topic: Proposal: Nested anonymous functors


Author: Nicola Musatti <objectway@divalsim.it>
Date: Wed, 27 Feb 2002 13:15:11 GMT
Raw View

Eric Hopper wrote:
[...]
> Suddenly you've created a way for code to mysteriously jump back to a
> previous stack context, then jump back to the new stack context.  If you
> remove the ability to refer to local variables, or member variables (which
> imply passing in 'this'), you make them much less useful, intuitive and
> lisp-like.

Although the previous message referred to functors, the same problem
applies to local functions if you allow them to refer to names in the
surrounding scopes. This is easily solved by adding to each function
activation frame a pointer to the previous activation frame. Resolving
names from surrounding scopes becomes a question of moving back on the
activation list for an appropriate number of links and then adding an
offset.

Of course this requires changing calling conventions, but it's not that
complicated per se.

>  I've seen some abortive attempt at doing this without allowing
> you to refer to member variables or local variables in Python and it's
> created nothing but problems, and Python is changing it to work like lisp
> does it.
>
> Sadly, in order to do it like lisp does it and still allow people to
> retain their sanity you need to introduce garbage collection.  You're
> essentially creating nearly invisible aliases for stack variables with
> that construct.

The real problem in the Lisp approach is that Lisp and similar languages
allow you to return the equivalent of local functions; for this to work
the local function has to carry along a portion of its calling
environment and this cannot really be done without some form of garbage
collection.

On the other hand Pascal always had local functions without requiring
garbage collection; local functions are considered in scope only in the
context of the function in which they are defined: attempting to return
a pointer to a local function is somewhat analogous to returning a
reference to a local object.

This line of reasoning can directly be applied to local classes.

Cheers,
Nicola Musatti

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Eric Hopper <eric.hopper@TIECommerce.com>
Date: Fri, 8 Feb 2002 01:10:28 GMT
Raw View
On Wed, 06 Feb 2002 22:40:20 -0600, Philippe A. Bouchard wrote:

> I saw proposals for nested fonctions, but I don't see the difference
> between functions and functors (besides the fact functors are more
> powerfull) so I'm proposing one for nested functors. Since types can
> already be anonymous... I'll propose one for nested anonymous functors
> instead. If it's not too complicated to implement for C++ compilator
> developers, I don't see why it shouldn't be there. It will help C++
> users:
> - Generate Lisp like code
> - Generate clean overall code (no ugly extern '__temp' structs)

Strangely enough, it is has a number of pretty thorny problems.

Supposed, for example, you have code that looks like:

#include <algorithm>
#include <iostream>
#include <string>

using namespace std;

#define lambda operator()

int main()
{
 string a[] =
 {
  "Marc",
  "Shawn",
  "George",
  "Robert"
 };
 string match = "George";

 find_if
 (
  a,
  a + 4,
  struct
  {
   bool lambda(string a)
   {
    return a == match;
   }
  } ()
 );
}

Suddenly you've created a way for code to mysteriously jump back to a
previous stack context, then jump back to the new stack context.  If you
remove the ability to refer to local variables, or member variables (which
imply passing in 'this'), you make them much less useful, intuitive and
lisp-like.  I've seen some abortive attempt at doing this without allowing
you to refer to member variables or local variables in Python and it's
created nothing but problems, and Python is changing it to work like lisp
does it.

Sadly, in order to do it like lisp does it and still allow people to
retain their sanity you need to introduce garbage collection.  You're
essentially creating nearly invisible aliases for stack variables with
that construct.

Using pointers to create aliases for variables in C causes enough problems
when you have to explicitly do it with the '&' operator.  In C++, of
course, the type signature of the function you call can do it nearly
invisibly by declaring a parameter to be a reference, which causes even
more problems.  Now, you're going to make people have to carefully
scruitinize the declarations for local functions to see if they make
aliases for member variables or 'this' by using the same name?! If C and
C++ already cause people to tear their hair out, this will cause stark
graving lunacy.

In short, there's a good reason C and C++ have no nested function
construct.  I think you'll find that almost all widely used languages that
do are garbage collected.

Have fun (if at all possible),

--
Eric Hopper

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Philippe A. Bouchard" <philippeb@videotron.ca>
Date: Fri, 8 Feb 2002 04:25:09 GMT
Raw View
I don't know, but it is already possible to define nested classes, template
or not. What if main() was considered to be a class with its local variables
to be like member variables? I don't know if I'm missing something...

.... and member references (aliases) are already in the standard...


Regards,
Philippe

"Eric Hopper" <eric.hopper@TIECommerce.com> wrote in message
news:xfy88.25239$Wf1.5565967@ruti.visi.com...
> On Wed, 06 Feb 2002 22:40:20 -0600, Philippe A. Bouchard wrote:
> Suddenly you've created a way for code to mysteriously jump back to a
> previous stack context, then jump back to the new stack context.  If you
> remove the ability to refer to local variables, or member variables (which
> imply passing in 'this'), you make them much less useful, intuitive and
> lisp-like.  I've seen some abortive attempt at doing this without allowing
> you to refer to member variables or local variables in Python and it's
> created nothing but problems, and Python is changing it to work like lisp
> does it.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 8 Feb 2002 16:06:22 GMT
Raw View
In article <xfy88.25239$Wf1.5565967@ruti.visi.com>, Eric Hopper
<eric.hopper@TIECommerce.com> writes
>In short, there's a good reason C and C++ have no nested function
>construct.  I think you'll find that almost all widely used languages that
>do are garbage collected.

Yet Ch (C with a plethora of extensions) from SoftIntegration does
provide for nested functions as well as a number of other interesting
features. Maybe they can do this because it is interpreted, but I rather
think not.


--
Francis Glassborow
Check out the ACCU Spring Conference 2002
4 Days, 4 tracks, 4+ languages, World class speakers
For details see: http://www.accu.org/events/public/accu0204.htm

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Eric Hopper <eric.hopper@tiecommerce.com>
Date: Fri, 8 Feb 2002 16:29:34 GMT
Raw View
On Thu, 07 Feb 2002 22:25:09 -0600, Philippe A. Bouchard wrote:

> I don't know, but it is already possible to define nested classes,
> template or not. What if main() was considered to be a class with its
> local variables to be like member variables? I don't know if I'm missing
> something...
>
> .... and member references (aliases) are already in the standard...

Well, nested classes have an important distinction.  You can't access the
'this' pointer of the parent class unless it's passed into some member
function of the nested class.

In Java, non-static nested classes always get an implicit 'this'
reference in their constructor, and rely on the language's garbage
collection to keep people's sanity.

You could do it this way in C++ if you wanted class declarations nested
inside of functions, but then it would be much less useful for the lambda
style functor expressions you want to use them.  Instances of the class
would have no special access to the function's local variables, or it's
implied 'this' pointer (if it's a member function).

As I said, Python was originally implemented this way, and it annoyed
people horribly, and it's being fixed now.  It couldn't be fixed in C++
because C++ isn't garbage collected.

Have fun (if at all possible),
--
Eric Hopper

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Philippe A. Bouchard" <philippeb@videotron.ca>
Date: Sat, 9 Feb 2002 02:40:46 GMT
Raw View
"Eric Hopper" <eric.hopper@tiecommerce.com> wrote in message
news:AVS88.26031$Wf1.5707040@ruti.visi.com...
> Well, nested classes have an important distinction.  You can't access the
> 'this' pointer of the parent class unless it's passed into some member
> function of the nested class.

Yes, it's true. Forget it then.

But... nested local classes must have inlined member function. It cannot be
externaly linked, since main()::S::operator() is not a valid definition. So
referencing stacked variables would result with generated code easy to
alter, depending on the depth of the instanciations. I don't see the need
for a garbage collector here. Here is the worse case I could think of:

#include <string>
#include <iostream>

using namespace std;

template <class _T>
 void depth2(int)
 { // enter in asm
  _T()("Gretzky"); // 2 'enter' level
 } // leave in asm

template <class _T>
 void depth1(long)
 { // enter in asm
  _T()("George"); // 1 'enter' level

  depth2<_T>(2);
 } // leave in asm

int main()
{ // enter in asm
 string s("Gretzky");

 struct F
 {
  bool operator()(string a)
  {
   return a == s;
  }
 };

 depth1<F>(1);
} // leave in asm


The compiler already knows were local variables are since inlined functions
already have the problem of resolving referenced parameters. The biggest
part is already resolved.


Yes I'm having fun & thanks again,
Philippe


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Philippe A. Bouchard" <philippeb@videotron.ca>
Date: Thu, 7 Feb 2002 04:40:20 GMT
Raw View
I'm continuing a discussion based on a previous email I've sent:
Subject: Local classes as template arguments

I saw proposals for nested fonctions, but I don't see the difference between
functions and functors (besides the fact functors are more powerfull) so I'm
proposing one for nested functors. Since types can already be anonymous...
I'll propose one for nested anonymous functors instead. If it's not too
complicated to implement for C++ compilator developers, I don't see why it
shouldn't be there. It will help C++ users:
- Generate Lisp like code
- Generate clean overall code (no ugly extern '__temp' structs)

Here's an example:
#include <algorithm>
#include <iostream>
#include <string>

using namespace std;

#define lambda operator()

int main()
{
 string a[] =
 {
  "Marc",
  "Shawn",
  "George",
  "Robert"
 };

 find_if
 (
  a,
  a + 4,
  struct
  {
   bool lambda(string a)
   {
    return a == "George";
   }
  } ()
 );
}

The following compiler:
Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.4/specs
gcc version 2.95.4 20011006 (Debian prerelease)

Generates:
search.cpp: In function `int main()':
search.cpp:29: semicolon missing after struct declaration
search.cpp:30: type `main()::{anonymous struct}' composed from a local class
is not a valid template-argument
search.cpp:30:   trying to instantiate `template <class _InputIter, class
_Predicate> find_if(_InputIter, _InputIter, _Predicate)'
search.cpp:30: no matching function for call to `find_if
(basic_string<char,string_char_traits<char>,__default_alloc_template<true,0>
>[4],
basic_string<char,string_char_traits<char>,__default_alloc_template<true,0>
> *, main()::{anonymous struct})'



Thanks,

Philippe
Software Engineer


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]