"Ary Borenszweig" <a...@esperanto.org.ar> wrote in message news:ieldl1$1of...@digitalmars.com... > On 12/19/2010 01:44 PM, Andrei Alexandrescu wrote: >> On 12/19/10 10:35 AM, Ary Borenszweig wrote: >>> On 12/19/2010 01:21 PM, Andrei Alexandrescu wrote: >>>> On 12/19/10 9:32 AM, Ary Borenszweig wrote: >>>>> I have this code: >>>>> >>>>> --- >>>>> import std.stdio; >>>>> >>>>> int foobar(int delegate(int) f) { >>>>> return f(1); >>>>> } >>>>> >>>>> int foobar2(string s)() { >>>>> int x = 1; >>>>> mixin("return " ~ s ~ ";"); >>>>> } >>>>> >>>>> void main() { >>>>> writefln("%d", foobar((int x) { return 2*x; })); >>>>> writefln("%d", foobar2!("9876*x")); >>>>> } >>>>> --- >>>>> >>>>> When I compile it with -O -inline I can see with obj2asm that for the >>>>> first writefln the delegate is being called. However, for the second >>>>> it just passes >>>>> 9876 to writefln. >>>>> >>>>> From this I can say many things: >>>>> - It seems that if I want hyper-high performance in my code I must use >>>>> string mixins because delegate calls, even if they are very simple and >>>>> the >>>>> functions that uses them are also very simple, are not inlined. This >>>>> has the drawback that each call to foobar2 with a different string >>>>> will generate a >>>>> different method in the object file. >>>> >>>> You forgot: >>>> >>>> writefln("%d", foobar2!((x) { return 2*x; })()); >>>> >>>> That's a real delegate, not a string, but it will be inlined. >>>> >>>> >>>> Andrei >>> >>> Sorry, I don't understand. I tried these: >>> >>> 1. >>> int foobar3(int delegate(int) f)() { >>> return f(1); >>> } >>> >>> writefln("%d", foobar3!((int x) { return 2*x; })()); >>> >>> => foo.d(12): Error: arithmetic/string type expected for >>> value-parameter, not int delegate(int) >>> >>> 2. >>> int foobar3()(int delegate(int) f) { >>> return f(1); >>> } >>> >>> writefln("%d", foobar3!()((int x) { return 2*x; })); >>> >>> => Works, but it doesn't get inlined. >>> >>> And I tried that "(x) { ... }" syntax and it doesn't work. >>> >>> Sorry, it must be my fault I'm doing something wrong. What's the correct >>> way of writing optimized code in D, code that I'm sure the compiler will >>> know how to optimize? >> >> void foobar3(alias fun)() { >> return fun(1); >> } >> >> >> Andrei > > foo.d > --- > import std.stdio; > > int foobar3(alias f)() { > return f(1); > } > > void main() { > writefln("%d", foobar3!((x) { return 9876*x; })()); > } > > aster...@deep-water:~/dmd2/linux/bin$ ./dmd foo.d -O -inline > aster...@deep-water:~/dmd2/linux/bin$ ./obj2asm foo.o | vi - > (line 530) > _Dmain: > push EBP > mov EBP,ESP > mov EAX,offset FLAT:_d3std5stdio6stdouts3std5stdio4f...@sym32 > push dword ptr _t...@sym32[0eh] > push dword ptr _t...@sym32[010h] > push 02694h > call _d3std5stdio4file19__t8writeflntayatiz8writeflnmfaya...@pc32 > xor EAX,EAX > pop EBP > ret > nop > nop > > No, it doesn't seem to get inlined. Luckily. Because if it did get inlined > then I would improve DMD by giving an error on this line: > > int foobar(int delegate(int) f) { > ... > } > > foo.d(3): Error: Hey man, what are you doing? Don't you know that if you > pass delegates that way they don't get inlined? You should write it this > way: "int foobar(alias f)()". That is, of course, if you want your code to > be more performant.
It's not completely useless: "int foobar(int delegate(int) f) { }" allows you to choose what delegate to send at run-time. "int foobar3(alias f)() { }" doesn't. (Although, I suppose you might be able to work around that moving the run-time selection from the caller of foobar3 to the delegate passed into "int foobar3(alias f)() { }". Not sure if there are cases where that would be awkward to do.) I will say though, it's a hell of a lot easier to remember the syntax of "int foobar(alias f)()". :)