www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - 2.0: Defining and calling a nested func all at once

reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
On the same project I mentioned in my previous message, I declared a 
function which I was only going to call in one spot.  I had to name it 
(see prev msg), but I would have preferred to not name it.

So this syntax would have been correct (though unreadable):
	DoStuff(function char[](ulong) {...} (<argument>)));

Does anybody have a good idea for some sort of syntax that would allow 
you to define an unnamed function and then immediately call it?  I 
couldn't write a simple expression because it required recursion (or 
looping, if you prefer).
Jan 18 2005
next sibling parent Andy Friesen <andy ikagames.com> writes:
Russ Lewis wrote:
 On the same project I mentioned in my previous message, I declared a 
 function which I was only going to call in one spot.  I had to name it 
 (see prev msg), but I would have preferred to not name it.
 
 So this syntax would have been correct (though unreadable):
     DoStuff(function char[](ulong) {...} (<argument>)));
 
 Does anybody have a good idea for some sort of syntax that would allow 
 you to define an unnamed function and then immediately call it?  I 
 couldn't write a simple expression because it required recursion (or 
 looping, if you prefer).

I would think it would be clearer to write it as a named function, followed by an invocation. char[] doRecursiveThing(ulong l) { .... } char[] result = doRecursiveThing(<argument>); DoStuff(result); "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." -- Brian Kernighan -- andy
Jan 18 2005
prev sibling next sibling parent reply parabolis <parabolis softhome.net> writes:
Russ Lewis wrote:

 Does anybody have a good idea for some sort of syntax that would allow 
 you to define an unnamed function and then immediately call it?  I 
 couldn't write a simple expression because it required recursion (or 
 looping, if you prefer).

Unless I am completely missing something I think I can show you why no such syntax exists. For a function to be unnamed you would have to either (a) provide the function body in the same scope in which it is used or (b) create a (named!) scope to contain the function body and bring it into the scope. (a) seems like the most straightforward approach however you desire to avoid cluttering the "mindspace" of the reader is IMHO defeated by having a function body is much more "mindspace" clutter than simply using the convention of appending "_aux" to the calling function name and being able to pull the "_aux" function body out of the calling function's body. (b) of course is no help either because now you are naming a namespace instead of a function and did not really save anything... The most straitforward way to declare a new namespace and scope would be to define a function with the namespace name you would be using which should probably be the calling function's name appended with "_aux". Finally there is an argument that using any special syntax for unnamed functions would be arcane enough that enough readers would be confused because they either are not aware of it or understand it to work in a way it does not. So to avoid such confusion I would not use the syntax and would append "_aux" to a helper function name.
Jan 19 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
parabolis wrote: 

 Russ Lewis wrote:
 
 Does anybody have a good idea for some sort of syntax that would
 allow you to define an unnamed function and then immediately call it?
  I couldn't write a simple expression because it required recursion
 (or looping, if you prefer).

Unless I am completely missing something I think I can show you why no such syntax exists. For a function to be unnamed you would have to either (a) provide the function body in the same scope in which it is used or (b) create a (named!) scope to contain the function body and bring it into the scope.

Yes I see a miss. There is: (c) provide a place holder for the function body in the scope of the definition. And there is a gap in the language that needs to be filled according to Russ' needs. Currently it is totally legal to define and call an anonymous function provided that it is not recursive: <code> void main(){ printf( "%d\n", function int(int i){ return i/2;} (12) ); } </code> But there is no evindence, that this has to be restricted to non recursive functions. The place holder mentioned in alterbnative (c) can be called "self" as Russ himself mentioned, or "function" giving for example: <code> void main(){ printf( "%d\n", function int(int i){ return i/2 + ( i> 10 ? function( i/2) : 0);} (12) ); } </code> To me it is quite evident that the keyword function followed by a left parenthesis is a call and not the start of another function literal. Therefore the allowance to drop the result type "void" in function literals should be abandoned before 1.0 -manfred
Jan 20 2005
parent reply parabolis <parabolis softhome.net> writes:
Manfred Nowak wrote:

 parabolis wrote: 
 
Russ Lewis wrote:

Does anybody have a good idea for some sort of syntax that would
allow you to define an unnamed function and then immediately call it?
 I couldn't write a simple expression because it required recursion
(or looping, if you prefer).

Unless I am completely missing something I think I can show you why no such syntax exists. For a function to be unnamed you would have to either (a) provide the function body in the same scope in which it is used or (b) create a (named!) scope to contain the function body and bring it into the scope.

Yes I see a miss. There is: (c) provide a place holder for the function body in the scope of the definition.

 The place holder mentioned in alterbnative (c) can be called "self" as Russ 
 himself mentioned, or "function" giving for example:
 
 <code>
 void main(){

We are in the scope of main:
   printf( "%d\n",
     function int(int i){ return i/2 + ( i> 10 ? function( i/2) : 0);}

Here is the body of the anonymous function - still in the scope of main().
     (12)

Here is the application of the anonymous function - again still in the scope of main().
   );
 }
 </code>

I think perhaps I did not explain clearly what I meant in case (a) but this is exactly the sort of thing I had in mind. Consider the "_aux" alternative and the "mindspace" consumed in main() in this example: ---------------------------------------------------------------- void main(){ printf( "%d\n", main_aux(12) ); } int main_aux(int i) { return i/2; } ---------------------------------------------------------------- The name "main_aux" screams "I am a function used in main and so unimportant my author did not even give me a real name." The aux is short for auxiliary and indicates the aux function's whole purpose in life is to do something on main's behalf. So the first part of my argument applied to your example is that in case (a) everything that goes into using and defining an anonymous function in the same scope clutters the code horribly and the author's mind to such an extent I do not believe it would really be desirable. The second part of my argument applied to your example is that defining and calling anonymous functions is such an arcane piece of syntax to start with many readers would have to go read the D spec to figure out what exactly is happening. Ergo the whole example looks a bit like this in enough cases not to warrant the use: ---------------------------------------------------------------- void main(){ printf( "%d\n", /* Anonymouns functions from the D spec: http://digitalmars.com/d/expression.html#FunctionLiteral FunctionLiteral ... function Type ( ParameterList ) FunctionBody ... In the following case this is: function int(int i){ return i/2;} Type = "int" ParameterList = "int i" FunctionBody = "{ return i/2; }" */ function int(int i){ return i/2;} (12) ); } ---------------------------------------------------------------- This example is not exactly the paradigm of readability. So to sum it up the (1) "_aux" convention allows you to keep the body of the anonymous function out of the way and (2) also does not add a everthing encountered in a doc+google+NG search to understand what is happening.
Jan 20 2005
parent reply "Unknown W. Brackets" <unknown simplemachines.org> writes:
Forgive me this, but is "aux" really that much more readable?  We have 
keywords such as "for", "if", "function", and other complete words... 
and then "_aux"?

For one thing, that limits you to just one "auxilliary" function.  What 
if I want two?  Do I use "main_aux_sec" (which will stand for "main's 
auxilliary secondary function?)

Sorry, but I personally can't stand the practical obfusication of names, 
and when you speak of doing this to *INCREASE* readability... it just 
makes me unclear on what you really mean.  Are we talking about the same 
readability here?

JavaScript, for example, uses the following:
function (parameters) { body; }

JavaScript is typeless (well, it isn't, but it's not strongly typed) so 
this makes sense.  But in D, if the function needs to return something 
it needs to be bool, int, or char[], etc... so what's wrong with 
function int?  To me, that follows normally.

As for separating the function, it would be nice to have named functions 
which can share the scope of their caller, but imho there's not all that 
much call for it.  In your case, you seem to want to name it "aux" 
anyway, so why don't you?  And it only looks ugly and disorganized 
because you're not used to it; to some, having variable declarations 
anywhere but at the top of the function may seem just as sickening.

Only my opinion, of course.

-[Unknown]

 Manfred Nowak wrote:
 This example is not exactly the paradigm of readability. So to sum it up 
 the (1) "_aux" convention allows you to keep the body of the anonymous 
 function out of the way and (2) also does not add a everthing 
 encountered in a doc+google+NG search to understand what is happening.

Jan 20 2005
parent reply parabolis <parabolis softhome.net> writes:
Unknown W. Brackets wrote:
 Forgive me this, but is "aux" really that much more readable?  We have 
 keywords such as "for", "if", "function", and other complete words... 
 and then "_aux"?

What does appending "_aux" to your function's name have to do with keywords?
 
 For one thing, that limits you to just one "auxilliary" function.  What 
 if I want two?  Do I use "main_aux_sec" (which will stand for "main's 
 auxilliary secondary function?)

My original argument suggested using the convention of appending "_aux" as an example only. You can make up your own convention and name functions as "main_smallFunctionHelpingMainNumberOne" if you like. My only claim is that you cannot find a way to use anonymous functions to make understanding the code simpler for anybody reading it. If I am wrong and you know why it should be a simple matter for you to share an example that shows otherwise.
Jan 20 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
parabolis wrote:

 My only claim is that you cannot find a way to use anonymous functions 
 to make understanding the code simpler for anybody reading it. If I am 
 wrong and you know why it should be a simple matter for you to share 
 an example that shows otherwise.

The essentials of your argument are not restricted to functions. So your claim can be rewritten to: anonymous constructs complicate understanding. But is this really true? <code> import std.random; void main(){ int x; int* main_aux_intp; int main_aux_int; bit main_aux_bit; main_aux_intp= &x; main_aux_int= rand()/2; scanf( "%d", main_aux_intp); main_aux_bit= (*main_aux_intp) > 100; if( main_aux_bit) (*main_aux_intp) = main_aux_int; } </code> Why is if( main_aux_bit) (*main_aux_intp)= main_aux_int; more understandable than if( x > 100) x= rand()/2; ? -manfred
Jan 20 2005
parent reply parabolis <parabolis softhome.net> writes:
Manfred Nowak wrote:
 parabolis wrote:
 
My only claim is that you cannot find a way to use anonymous functions 
to make understanding the code simpler for anybody reading it. If I am 
wrong and you know why it should be a simple matter for you to share 
an example that shows otherwise.

The essentials of your argument are not restricted to functions. So your claim can be rewritten to: anonymous constructs complicate understanding.

Functions not only have a range but also a domain and a body associated with them. It is the bodies that cause clutter and it was "body clutter" that I used in my argument. So I would say there is something unique about them. The combination of your example showing anonymous variables are useful and lack of example showing the same for functions supports my initial argument.
 But is this really true?

No I would say your example of illustrates the desirability of anonymous variables very well.
Jan 21 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
parabolis wrote:

 parabolis wrote:
 
My only claim is that you cannot find a way to use anonymous
functions to make understanding the code simpler for anybody reading
it.


used in my argument.

Thanks for stating that you oversimplified your own argument. You seems to know, that it is easy to bash examples instead of recognizing the analogies. So what is in your opinion in the "mindspace"-view the difference between a function body and a huge expression on the RHS of a `=' symbol? IMO there is no difference. Then: because you already stated that anonymous variables are useful anonymous functions are useful also. I invite you to have a closer look at your own example: <code> void main(){ printf( "%d\n", main_aux(12) ); } int main_aux(int i) { return i/2; } </code> Your argument is, that the "mindspace" of main is less cluttered. This is not necessarily true because it depends on the psychological habits of the reader. But it is undoubtly true, that the "mindspace" of the module containig `main' is cluttered temporarily with an unresolved reference to `main_aux' and then constantly contaminated with the resolved reference to `main_aux'. I.e. using function/auxiliary function pairs exhaust the human short time memory chunks with doubled speed. Furthermore the contamination of the "mindspace" may lead to hardly detectable errors as you can see if you extend your example above with another pair of functions: <code> ... // as above void mainn(){ printf( "%d\n", main_aux(20) ); } int mainn_aux(int i) { return i^2; } </code> Are you recognizing, that the body of `mainn' is contaminated from the beginning with a reference to `main_aux'? Do you accept, that the "mindspace" of the bodies of all following functions is contaminated with identifiers in a number in the order of the number of the previous declared auxiliary functions? There are more arguments, but I think these are enough: fup2 poster. -manfred
Jan 21 2005
parent reply parabolis <parabolis softhome.net> writes:
Manfred Nowak wrote:
 You seems to know, that it is easy to bash examples instead of
 recognizing the analogies. So what is in your opinion in the
 "mindspace"-view the difference between a function body and a
 huge expression on the RHS of a `=' symbol?

In my opinion not much difference at all. Anonymous variables can be useful but they can also be overused.
 Your argument is, that the "mindspace" of main is less
 cluttered. This is not necessarily true because it depends on
 the psychological habits of the reader.

 But it is undoubtly true, that the "mindspace" of the module
 containig `main' is cluttered temporarily with an unresolved
 reference to `main_aux' and then constantly contaminated with
 the resolved reference to `main_aux'.

 I.e. using function/auxiliary function pairs exhaust the human
 short time memory chunks with doubled speed.

Here is something that illustrates this issue. Pay close attention because normally this is spoken so if you have to go back and read anything you had to cheat. ---------------------------------------------------------------- Bob is driving a bus with 15 passengers. At the first stop 3 people get off and 5 people get on. At the next stop nobody gets off and one person gets on. At the next stop half the people get off and one person gets on. For each of the next three stops the same odd number of people get off at each stop. At the next stop three people get off and nobody gets on. ---------------------------------------------------------------- You should be able to answer a question without reading it again. The question is "What was the name of the bus driver?" I know before you read this sentence you will have inadvertantly glanced back up to see what the name was even though I said it was strictly forbidden. If your argument was correct then the "mindspace" of that whole exercise should have been "constantly contaminated" by the name Bob. However it was not. The format suggest - screams even - that I will soon be asking you how many people are on the bus and you quickly realize 'Bob' has nothing to do with anything and tosses it out to make room for the important things.
 Furthermore the contamination of the "mindspace" may lead to
 hardly detectable errors as you can see if you extend your
 example above with another pair of functions:

 <code>
 ... // as above

 void mainn(){
   printf( "%d\n", main_aux(20) );
 }

 int mainn_aux(int i) { return i^2; }
 </code>

 Are you recognizing, that the body of `mainn' is contaminated
 from the beginning with a reference to `main_aux'?

If 'main_aux' causes any trouble at all then it is a trifle compared to 'main' itself. The biggest question in the readers mind would be why 'main' and 'mainn' however the answer to why 'main_aux' and 'mainn_aux' will be self evident - they are simply there because of the troublesome 'main' and 'mainn'.
Jan 21 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
This is my last post to this branch.

parabolis wrote:

[...]
 Anonymous variables can be useful but they can also be overused.

Agreed. And therefore the decision is up to the writer. [...]
 Bob is driving a bus with 15 passengers. At the first stop 3 

'Bob' has nothing to do with anything and tosses 
 it out to make room for the important things.

As I already mentioned the actions depend on the psychological habits. And you are wrong with the expectations of my habits in this area. I know this example very well, stopped reading when recognizing "bus" and rushed to the question to examine if it is really the question for the name of the driver ... bingo. However, your example shows, that programmers are used to solve difficulties, because it describes the typical body of a function returning a non-void type: to understand it, you have to look at the expression attached to the return statement first, which is usually at the end of the body and then read through the body to understand how the terms of that expression are built. Following your example, the `return' should be dropped in favour for a predefined variable `result' whose type is equal to the type of the return value of the function. There were discussions about this issue. [...]
 Are you recognizing, that the body of `mainn' is contaminated
 from the beginning with a reference to `main_aux'?


 they are simply there because of the troublesome 'main' and 'mainn'.

Please stop bashing examples: even if you replace `mainn' by a name as different from `main' as you want, the wrong call of `main_aux' cannot be detected by the compiler. So with that contamination you are living at an unnecessary risk. Furthermore your technic is applicable at the module level only: nested functions must precede the scope in which they are called. -manfred
Jan 21 2005
parent Georg Wrede <georg.wrede nospam.org> writes:
What intrigues me is the length of this thread.

A similar one could have been about naming "throwaway" variables. No one 
has a problem with i, j, etc. Then why not just use f, g, etc. for such 
throwaway functions.

There's even no problem with the scarcity of names (f,g,h), because by 
the time you need i,j and so on, you'd better rename all these to 
something meaningful anyway.
Jan 24 2005
prev sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Russ Lewis wrote:
 On the same project I mentioned in my previous message, I declared a 
 function which I was only going to call in one spot.  I had to name it 
 (see prev msg), but I would have preferred to not name it.
 
 So this syntax would have been correct (though unreadable):
     DoStuff(function char[](ulong) {...} (<argument>)));
 
 Does anybody have a good idea for some sort of syntax that would allow 
 you to define an unnamed function and then immediately call it?  I 
 couldn't write a simple expression because it required recursion (or 
 looping, if you prefer).

I'll offer two ideas, which I considered and didn't like, followed by an idea that I stumbled upon today which I like: Bad: use <arg> = <value> function char[](ulong arg = 1234) {...} bad because it looks like a default argument Bad: use <arg> : <value> function char[](ulong arg : 1234) {...} I just don't like the looks of it. What I like: function <retType>(<args>)(<values>) function char[](ulong arg)(1234) {...} The advantage here is that the arguments are right there at the front. So it's readable for people who are familiar with the construct, but I can't necessarily say that it is inherently readable for newbies. That's certainly a downside. :( Thoughts?
Jan 21 2005