Optimizing delegates

Daniel Gibson metalcaedes at gmail.com
Sun Dec 19 16:40:11 PST 2010


On Mon, Dec 20, 2010 at 1:06 AM, loser <noneedtotalkanymore at to.me> wrote:
> Daniel Gibson Wrote:
>
>> On Sun, Dec 19, 2010 at 5:44 PM, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> 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
>> >
>>
>> I think using an alias makes the code less readable.
>> "int foobar(int delegate(int) f)" tells you that the argument should be (a
>> delegate of) a function that accepts an int and returns an int.
>> "foobar3(alias fun)()" tells you almost nothing. You know that some kind of
>> template parameter is expected, but not if it's a function or whatever, and
>> even less what signature that function should have.
>>
>> IMHO some other syntax than just "alias fun" should be used for this purpose
>> (inlined delegates known at compile time) - some syntax that documents the
>>  signature of the expected function, like with real delegates.
>
> Hear, hear. Another problem with this approach I couldn't even think of. With luck, illegal code may compile. You have no clean way to enforce/document the domain of the comparator/predicate.
>

I don't think illegal code would compile, when fun is called in foobar() the
compiler will check if the function aliased by fun has a suitable signature.

My point concerns only readability of function-signatures, I think.
IMHO when you look at a function signature you should know what kind of
parameters are expected, at least in a strongly typed language.


More information about the Digitalmars-d mailing list