Why does not UFCS work for method defined inside unittest block?

Simen Kjærås simen.kjaras at gmail.com
Tue Jul 31 08:42:28 UTC 2018


On Tuesday, 31 July 2018 at 08:28:01 UTC, Ky-Anh Huynh wrote:
> Hi,
>
> Can I define a new quick function to use inside a unittest 
> block?
>
> I have the following code:
>
> [code]
> auto foo(string[] sta) {
>   return sta;
> }
>
> auto bar(string[] sta) {
>   return sta;
> }
>
> auto h(string[] sta) {
>   return sta.foo.bar;
> }
>
> unittest {
>   import std.format;
>
>   auto f = (string[] sta) => sta.foo.bar;
>   auto g(string[] sta) {
>     return sta.foo.bar;
>   }
>
>   assert(f(["test"]) == ["test"]);
>   assert(g(["test"]) == ["test"]);
>   assert(["test"].h == ["test"]);
>   assert(["test"].g == ["test"]);
> }
> [/code]
>
> (Src: 
> https://gist.github.com/icy/64ec1838929d448d9f874d1e8261e56a)
>
> The last test will fail: Error: no property g for type string[]
>
> Please advise.

 From https://dlang.org/spec/function.html#pseudo-member:
"A free function can be called with a syntax that looks as if the 
function were a member function of its first parameter type."

A function defined in a function scope (which a unittest block 
is), is not a free function, and so does not benefit from UFCS. 
There is an explanation for why at the bottom of the above page:
"The reason why local symbols are not considered by UFCS, is to 
avoid unexpected name conflicts."

If you need a function that's available for UFCS in a unittest 
but is not there in a non-unittest context, use a version block:

     version (unittest) {
         auto fun(string[] s) { return s }
     }

And if you need something with a context:

     version (unittest) {
         string delegate (string) test;
     }
     unittest {
         string s1 = "foo";
         test = s => s ~ s1;
         "foo".test;
     }

--
   Simen


More information about the Digitalmars-d-learn mailing list