Re: How to get the UDAs for a function parameter correctly?
On Monday, 11 May 2020 at 02:34:32 UTC, Adam D. Ruppe wrote: On Monday, 11 May 2020 at 02:25:39 UTC, Heromyth wrote: I want to get the UDAs for for a function parameter. Here the test code and I got some errors: I think my blog aside is one of the few if only write-ups on how to do this: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_02_11.html#how-to-get-uda-on-a-function-param the library will not help much, you need to slice the parameters yourself. (It might work combine lib stuff with slice though, e.g. getUDA!(Parameters!F[1 .. 2]) maybe, i have never tried). but this does work: static if(is(typeof(method) P == __parameters)) foreach(idx, _; P) {{ // alias for convenience later alias param = P[idx .. idx + 1]; // this slice is the trick // can get the identifier now string ident = __traits(identifier, param); // and the attributes foreach(attr; __traits(getAttributes, param)) {} }} That's great! It should use static if(is(typeof(method) P == __parameters)) to get all the parameters instead of using: alias Params = Parameters!(member); Here is the adjusted code: = import std.stdio; import std.traits; import std.meta; struct Length { int a; int b; } class ClassA { void test(@Length(1, 9) int len, @Length(2, 4) int size) { writeln("It's OK"); } void test(string name, @Length(3, 5) int len) { writeln("Works now"); } void test() { } } string test(T)() { string str; alias currentMembers = __traits(getOverloads, T, "test"); static foreach(member; currentMembers) {{ static if(is(typeof(member) Params == __parameters)) { static foreach(i, _; Params) {{ alias ThisParameter = Params[i .. i + 1]; static foreach(uda; __traits(getAttributes, ThisParameter)) { str ~= uda.stringof ~ "\n"; } }} } }} return str; } void main() { enum aa = test!(ClassA); writeln(aa); }
Re: How to get the UDAs for a function parameter correctly?
On Monday, 11 May 2020 at 02:25:39 UTC, Heromyth wrote: I want to get the UDAs for for a function parameter. Here the test code and I got some errors: I think my blog aside is one of the few if only write-ups on how to do this: http://dpldocs.info/this-week-in-d/Blog.Posted_2019_02_11.html#how-to-get-uda-on-a-function-param the library will not help much, you need to slice the parameters yourself. (It might work combine lib stuff with slice though, e.g. getUDA!(Parameters!F[1 .. 2]) maybe, i have never tried). but this does work: static if(is(typeof(method) P == __parameters)) foreach(idx, _; P) {{ // alias for convenience later alias param = P[idx .. idx + 1]; // this slice is the trick // can get the identifier now string ident = __traits(identifier, param); // and the attributes foreach(attr; __traits(getAttributes, param)) {} }}
How to get the UDAs for a function parameter correctly?
I want to get the UDAs for for a function parameter. Here the test code and I got some errors: source/app.d(29,33): Error: first argument is not a symbol source/app.d(39,15): Error: template instance app.test!(ClassA) error instantiating How can I fix this? Would this be a bug? Thanks. = import std.stdio; import std.traits; import std.meta; struct Length { int a; int b; } class ClassA { void test(@Length(1, 9) int len, @Length(2, 4) int size) { writeln("It's OK"); } void test(string name) { writeln("Can't be compiled"); } } string test(T)() { string str; alias currentMembers = __traits(getOverloads, T, "test"); static foreach(member; currentMembers) {{ alias Params = Parameters!(member); static foreach(i; 0 .. Params.length) {{ alias ThisParameter = Params[i .. i + 1]; static foreach(uda; __traits(getAttributes, ThisParameter)) { str ~= uda.stringof ~ "\n"; } }} }} return str; } void main() { enum aa = test!(ClassA); writeln(aa); }
Function Templates with Only Template Parameters and UFCS
Given the code: ``` auto foo(alias A, string str)() { // do stuff } struct Bar { // members } Bar bar; bar.foo!"hello"; // This is an error. Would have to do foo!(bar, "hello") ``` Assuming that I haven't misunderstood or borked something, having UFCS for function templates whose parameters are only for the template would, seemingly, be nice. Are there workarounds? Is it possible to implement, and possibly the more important question, is it a good idea? One downside is there would be more ambiguity when one is parsing that last line.
Re: Why does indexing a string inside of a recursive call yield a different result?
On Sunday, 10 May 2020 at 10:02:18 UTC, Adnan wrote: In my naive implementation of edit-distance finder, I have to check whether the last characters of two strings match: ulong editDistance(const string a, const string b) { if (a.length == 0) return b.length; if (b.length == 0) return a.length; const auto delt = a[$ - 1] == b[$ - 1] ? 0 : 1; import std.algorithm : min; return min( editDistance(a[0 .. $ - 1], b[0 .. $ - 1]) + delt, editDistance(a, b[0 .. $ - 1]) + 1, editDistance(a[0 .. $ - 1], b) + 1 ); } This yields the expected results but if I replace delt with its definition it always returns 1 on non-empty strings: ulong editDistance(const string a, const string b) { if (a.length == 0) return b.length; if (b.length == 0) return a.length; //const auto delt = a[$ - 1] == b[$ - 1] ? 0 : 1; import std.algorithm : min; return min( editDistance(a[0 .. $ - 1], b[0 .. $ - 1]) + a[$ - 1] == b[$ - 1] ? 0 : 1, //delt, editDistance(a, b[0 .. $ - 1]) + 1, editDistance(a[0 .. $ - 1], b) + 1 ); } Why does this result change? Wrap the ternary condition into parenthesis. editDistance(a[0 .. $ - 1], b[0 .. $ - 1]) + (a[$ - 1] == b[$ - 1] ? 0 : 1)
Re: Why does indexing a string inside of a recursive call yield a different result?
On 10.05.20 12:02, Adnan wrote: ulong editDistance(const string a, const string b) { if (a.length == 0) return b.length; if (b.length == 0) return a.length; const auto delt = a[$ - 1] == b[$ - 1] ? 0 : 1; import std.algorithm : min; return min( editDistance(a[0 .. $ - 1], b[0 .. $ - 1]) + delt, editDistance(a, b[0 .. $ - 1]) + 1, editDistance(a[0 .. $ - 1], b) + 1 ); } This yields the expected results but if I replace delt with its definition it always returns 1 on non-empty strings: ulong editDistance(const string a, const string b) { if (a.length == 0) return b.length; if (b.length == 0) return a.length; //const auto delt = a[$ - 1] == b[$ - 1] ? 0 : 1; import std.algorithm : min; return min( editDistance(a[0 .. $ - 1], b[0 .. $ - 1]) + a[$ - 1] == b[$ - 1] ? 0 : 1, //delt, editDistance(a, b[0 .. $ - 1]) + 1, editDistance(a[0 .. $ - 1], b) + 1 ); } Why does this result change? You're going from this (simplified): delt = a == b ? 0 : 1 result = x + delt to this: result = x + a == b ? 0 : 1 But that new one isn't equivalent to the old one. The new one actually means: result = (x + a == b) ? 0 : 1 You need parentheses around the ternary expression: result = x + (a == b ? 0 : 1)
Why does indexing a string inside of a recursive call yield a different result?
In my naive implementation of edit-distance finder, I have to check whether the last characters of two strings match: ulong editDistance(const string a, const string b) { if (a.length == 0) return b.length; if (b.length == 0) return a.length; const auto delt = a[$ - 1] == b[$ - 1] ? 0 : 1; import std.algorithm : min; return min( editDistance(a[0 .. $ - 1], b[0 .. $ - 1]) + delt, editDistance(a, b[0 .. $ - 1]) + 1, editDistance(a[0 .. $ - 1], b) + 1 ); } This yields the expected results but if I replace delt with its definition it always returns 1 on non-empty strings: ulong editDistance(const string a, const string b) { if (a.length == 0) return b.length; if (b.length == 0) return a.length; //const auto delt = a[$ - 1] == b[$ - 1] ? 0 : 1; import std.algorithm : min; return min( editDistance(a[0 .. $ - 1], b[0 .. $ - 1]) + a[$ - 1] == b[$ - 1] ? 0 : 1, //delt, editDistance(a, b[0 .. $ - 1]) + 1, editDistance(a[0 .. $ - 1], b) + 1 ); } Why does this result change?
Re: Is there a way to tell if an auto ref parameter is by ref or by value?
On Sunday, 10 May 2020 at 01:15:58 UTC, Anonymouse wrote: On Sunday, 10 May 2020 at 00:33:07 UTC, NaN wrote: Ie something like.. auto Foo(T)(auto ref T x) { static if (isByRef(x)) { } else { } } __traits(isRef, x) Thanks :)