Thread overview
Why does not UFCS work for method defined inside unittest block?
Jul 31, 2018
Ky-Anh Huynh
Jul 31, 2018
Ky-Anh Huynh
Jul 31, 2018
Simen Kjærås
Aug 01, 2018
Ky-Anh Huynh
July 31, 2018
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.

Thanks a lot.



July 31, 2018
dmd version that I'm using:

$ dmd --version
DMD64 D Compiler v2.081.1-dirty
Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved written by Walter Bright

July 31, 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
August 01, 2018
On Tuesday, 31 July 2018 at 08:42:28 UTC, Simen Kjærås wrote:
> 
>
> 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."
>
>  [...]

Thanks a lot Simen :)