Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 18, 2005 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
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). |
January 19, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | 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
|
January 19, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | 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.
|
January 21, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to parabolis | 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
|
January 21, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | 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. |
January 21, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to parabolis | 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.
|
January 21, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to Unknown W. Brackets | 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. |
January 21, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to parabolis | 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
|
January 21, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | 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. |
January 21, 2005 Re: 2.0: Defining and calling a nested func all at once | ||||
---|---|---|---|---|
| ||||
Posted in reply to parabolis | 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.
> It is the bodies that cause clutter and it was "body clutter" that I 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
|
Copyright © 1999-2021 by the D Language Foundation