Skip to content

add __traits(getCurrentFunction)#11538

Closed
ghost wants to merge 1 commit intomasterfrom
unknown repository
Closed

add __traits(getCurrentFunction)#11538
ghost wants to merge 1 commit intomasterfrom
unknown repository

Conversation

@ghost
Copy link

@ghost ghost commented Aug 9, 2020

  • fix issue 8109
  • fix issue 9306

This new traits is a shortcut allowing to call the function we are in and this without using mixin and __FUNCTION__ tricks.

@dlang-bot
Copy link
Contributor

dlang-bot commented Aug 9, 2020

Thanks for your pull request, @NilsLankila!

Bugzilla references

Auto-close Bugzilla Severity Description
8109 enhancement typeof(function) within functions
9306 enhancement __function alias

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#11538"

@ghost ghost added the Severity:Enhancement label Aug 9, 2020
@UplinkCoder
Copy link
Member

Nice, you can argue about the long name, but the trait is a good addition

@Geod24
Copy link
Member

Geod24 commented Aug 9, 2020

What's the use case ?

EDIT: I see issue 8109 has some more informations. Honestly I'm not very convinced by this, the only examples I've seen so far are artificial and don't enable any useful pattern. It would be good to have a more idiomatic use case.

@ghost
Copy link
Author

ghost commented Aug 9, 2020

I have this that has bugs, due to overloads, when using __FUNCTION__ but that would work with the traits:

/**
 * Can be mixed-in as first expression statement of a function body to
 * automatically return if one of the parameter is null. This works for classes,
 * interfaces and pointers.
 *
 * See_Also: voidFunctionProtector.
 *
 * Bugs: Does not work with overloads.
 *
 * Params:
 *      _RETURN_EXP = A string representing the expression to return when the
 *          function gives a return.
 */
enum string functionProtector(string _RETURN_EXP = "") = "
    import std.traits : ParameterIdentifierTuple, Parameters, PointerTarget;

    alias _FUNC_PARAMS_IDENT = ParameterIdentifierTuple!(mixin(__FUNCTION__));
    alias _FUNC_PARAMS_TYPES = Parameters!(mixin(__FUNCTION__));
    alias _RET_TYPE          = typeof(return);

    static foreach (n; 0 .. _FUNC_PARAMS_IDENT.length)
    {
        static if ( is(_FUNC_PARAMS_TYPES[n] == class) ||
                    is(_FUNC_PARAMS_TYPES[n] == interface) ||
                    is(PointerTarget!(_FUNC_PARAMS_TYPES[n])))
        {
            if (mixin(_FUNC_PARAMS_IDENT[n] ~ ` is null`))
            {
                static if (!is(_RET_TYPE == void))
                    return mixin(" ~ _RETURN_EXP ~ ");
                else
                    return;
            }
        }
    }
";

@ghost
Copy link
Author

ghost commented Aug 9, 2020

I'd say that the idiomatic case is when mixin something in a func. Obvioulsy the factorial example is not interesting because in this case you know what to call when you write your func body but when you mix something, that something has to be generic enough to work, like my functionProtector in any function.

@ghost
Copy link
Author

ghost commented Aug 9, 2020

ping @TurkeyMan, as you requested that feature you may have other use cases to expose to @Geod24.

@MoonlightSentinel
Copy link
Contributor

MoonlightSentinel commented Aug 9, 2020

There's another approach to consider: Fixing the parent trait to work properly within functions (it currently fails with a forward reference error).

Then one could use __traits(parent, <local declaration>) or __traits(parent, {}) to get the current function.

@UplinkCoder
Copy link
Member

UplinkCoder commented Aug 9, 2020 via email

This new traits is a shortcut allowing to call the function we
are in without using `mixin` and `__FUNCTION__` tricks.
@TurkeyMan
Copy link
Contributor

TurkeyMan commented Aug 16, 2020

@Geod24 Use case is any mixin template where you want to refer to the function it's introduced to.
Typically, some tools that scrape details from the functions parameter list, or various forms of pass-through shim's.,

This is extremely cool!

@TurkeyMan
Copy link
Contributor

TurkeyMan commented Aug 16, 2020

Then one could use __traits(parent, ) or __traits(parent, {}) to get the current function.

That's also cool. It's not at all obvious though; it would need to be wrapped in some core.meta helper or something to give it a proper name.

It's possible that using parent might be complicated by nesting within the function you're trying to sample though?
What would parent give within a mixin template? A reference to the mixin template itself, or a reference to the parent of the location the mixin template is mixed in to?

@MoonlightSentinel
Copy link
Contributor

That technique does not signal intent though.

Fair enough. We could also consider allowing __traits(parent) to get the enclosing symbol.

What would parent give within a mixin template? A reference to the mixin template itself, or a reference to the parent of the location the mixin template is mixed in to?

The latter:

module mod;

mixin template Foo()
{
    void bar() {}
    pragma(msg, __traits(parent, bar).stringof);
}

mixin Foo!(); // mod

void f()
{
    mixin Foo!(); // f()
}

@TurkeyMan
Copy link
Contributor

It's lame to declare a dummy symbol, but that would theoretically be fine. You would wrap it in a core.traits.

@MetaLang
Copy link
Member

MetaLang commented Apr 7, 2021

It's lame to declare a dummy symbol, but that would theoretically be fine. You would wrap it in a core.traits.

No need for a dummy symbol:

module test;

mixin template Foo()
{
    //The parent of an anonymous function is the enclosing module/template/aggregate/function
    pragma(msg, __traits(parent, {}).stringof);
}

mixin Foo!(); //module test

template Bar()
{
    mixin Foo!();
}

alias _ = Bar!(); //Bar!()

struct Test
{
    mixin Foo!(); //Test
}

void f()
{
    mixin Foo!(); //f()
}

void main()
{
	mixin Foo!(); //main()
}

@RazvanN7
Copy link
Contributor

The user has abandoned this PR, however, a link to it is present in the issues that it was trying to fix. Anyone that wants to pick it up feel free to reopen or start a new PR from scratch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants