Re: How to get the UDAs for a function parameter correctly?

2020-05-10 Thread Heromyth via Digitalmars-d-learn

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?

2020-05-10 Thread Adam D. Ruppe via Digitalmars-d-learn

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?

2020-05-10 Thread Heromyth via Digitalmars-d-learn
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

2020-05-10 Thread Seven Seas via Digitalmars-d-learn

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?

2020-05-10 Thread bauss via Digitalmars-d-learn

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?

2020-05-10 Thread ag0aep6g via Digitalmars-d-learn

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?

2020-05-10 Thread Adnan via Digitalmars-d-learn




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?

2020-05-10 Thread NaN via Digitalmars-d-learn

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 :)