Re: How do you call an eponymous template that has a secondary template arg?

2018-03-11 Thread Simen Kjærås via Digitalmars-d-learn

On Sunday, 11 March 2018 at 12:05:56 UTC, aliak wrote:

* aliasOf!int!"string" // multiple ! arguments are not allowed
* (aliasOf!int)!"string" // error c-style cast
* aliasOf!int.aliasOf!"string" // template isAliasOf(alias a) 
does not have property 'isAliasOf


Yeah, that's a little hole in the grammar, but there are ways:

// Declare an alias:
alias aliasOfInt = aliasOf!int;

// And use that:
assert(!aliasOfInt!string);


Or use std.meta.Instantiate:

assert(!Instantiate!(aliasOf!int, string));

--
  Simen


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

On Monday, 12 March 2018 at 03:13:08 UTC, Seb wrote:
Out of interest: I wonder what's your usecase for using qsort. 
Or in other words: why you can't use the high-level 
std.algorithm.sorting.sort?


This is only temporary. I will be using 
std.algorithm.sorting.sort. I was converting a C program and it 
annoyed me that I couldn't get the qsort invocation past the D 
compiler.


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 12 March 2018 at 02:44:17 UTC, Joe wrote:
I saw the extern(C) and I believe I tried it before my previous 
post, but dismissed it because I saw no difference in compiler 
behavior.


Yeah, the compiler should just tell you what specifically it is 
complaining about instead of making you hunt. These "no function 
match" errors are actually my #1 pain point as a daily D user... 
and as a regular D tech support rep, I see there are very 
frequent problems for everyone else too.


Could you explain or direct me to something that elucidates why 
the "scope" qualifiers are needed?  And is there something else 
that is necessary inside compar() or are the "scope"s just for 
decorative purposes?


So `scope` means you promise not to escape the reference outside 
your scope; that you won't store the pointers somewhere else for 
future use.


It is defined here: 
https://dlang.org/spec/function.html#parameters tho that's pretty 
light.


The compiler only checks it if you throw some random 
-dipsomething switch. The idea is something similar to Rust's 
borrow checker. It aims to make it a compile error to sneak out 
pointers to temporaries through our callback. You wouldn't do 
that anyway with a compare function, but now it is an error to 
try ( if the strict enforcement thing is thrown. and i don't 
remember the name, they are all random dip numbers on the 
switches)


I'm actually mildly against adding these directly to C functions, 
but this attribute spam is being added to all the druntime 
definitions. It requires stuff like nothrow and nogc on a bunch 
of handlers too, ugh, but the idea behind it is to make sure you 
don't break the C function's documented rules, but here checked 
by the D compiler without needing any runtime wrappers/checks.




But until recently it wasn't checked at all which is why I wasn't 
sure if that was causing your error. I guess it is required to 
match the function call even if the strict enforcement isn't 
thrown now.


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Seb via Digitalmars-d-learn

On Sunday, 11 March 2018 at 23:12:30 UTC, Joe wrote:

I'm getting a compiler error in a qsort() call as follows:

qsort(recs, num_recs, (Record *).sizeof, compar);

Record is a struct, recs is a fixed array of pointers to 
Record's and num_recs is a size_t that holds the number of 
valid records.


compar is this:

int compar(const void *p1, const void *p2)
{
import core.stdc.string : strcmp;
const Record **rp1 = cast(Record **)p1;
const Record **rp2 = cast(Record **)p2;

return strcmp((*rp1).name.ptr, (*rp2).name.ptr);
}

The error is: Error: function testd.compar (const(void*) p1, 
const(void*) p2) is not callable using argument types ()


I don't quite understand what those parentheses mean: is it 
implying "no arguments" and if so, where would one provide 
arguments?


Joe


Out of interest: I wonder what's your usecase for using qsort. Or 
in other words: why you can't use the high-level 
std.algorithm.sorting.sort?


Re: Date range iteration

2018-03-11 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, March 12, 2018 02:11:49 Jordan Wilson via Digitalmars-d-learn 
wrote:
> I wanted to iterate through a date range, so I initially tried:
> iota(Date(2016,1,1),Date(2018,1,1),dur!"days"(1));
>
> That wouldn't compile, which is fair enough I guess.

Maybe iota should be made to work, but as present, it basically wants all
three of the types it's given to be the same or implicitly convertible to
a single type. It can't handle the step being a completely different type.

> So I tried a for loop:
> for (auto i = Date(2016,1,1); i < Date(2018,1,1);
> i+=dur!"days"(1)){}
>
> That seemed to work fine, but I remember reading "for loops are
> bad" somewhere.

for loops are just fine - especially if you're just going to loop through
all the values and do something to them - but if you have a range, it's a
lot more flexible.

> So I looked for a range type mechanism, and I
> think it's this:
> foreach (i; Interval!Date
> (Date(2016,1,1),Date(2018,1,1)).fwdRange ( (a) { return
> a+dur!"days"(1); })){}
>
> My question is if the third way is the proper way of stepping
> through a period of time? It just seems quite complicated to me.

Well, honestly, the range support in std.datetime isn't very good. The core
problem that overcomplicates it is that the Interval needs to know which
direction you want to iterate in, and then the helper functions tend to need
to know it too in order to work properly. Also, the time point type being
used also tends to get duplicated a fair bit. So, you end up with annoyingly
repetitive code. The helper function intended for this use case is

https://dlang.org/phobos/std_datetime_interval.html#everyDuration

So, you'd get something more like

auto interval = Interval!Date(Date(2016, 1, 1), Date(2018, 1, 1));
auto range = interval.fwdRange(everyDuration!Date(days(1)));

But if you're just going to use the range in a foreach loop, then you might
as well just use a for loop. All of this extra machinery only really starts
being valuable when you start feeding the ranges into range-based functions.
For a simple loop, it's overkill.

- Jonathan M Davis



Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

On Monday, 12 March 2018 at 01:45:54 UTC, Adam D. Ruppe wrote:
I just reformatted it but now the difference should be visible: 
`extern(C)` is missing on your callback.


The scope things might make a difference too, but I know for 
sure extern(C) is necessary on your callback function.


I saw the extern(C) and I believe I tried it before my previous 
post, but dismissed it because I saw no difference in compiler 
behavior.  In any case declaring


extern (C) int compar(const (void *) p1, const (void *) p2) {
   ... // as before
}

still gives the error:

function core.stdc.stdlib.qsort (scope void* base, ulong nmemb, 
ulong size, extern (C) int function(scope const(void*), scope 
const(void*)) @system compar) is not callable using argument 
types (void*, ulong, ulong, extern (C) int function(const(void*) 
p1, const(void*) p2))


It only went away with

extern (C) int compar(scope const (void *) p1, scope const (void 
*) p2)


Could you explain or direct me to something that elucidates why 
the "scope" qualifiers are needed?  And is there something else 
that is necessary inside compar() or are the "scope"s just for 
decorative purposes?


Joe


Date range iteration

2018-03-11 Thread Jordan Wilson via Digitalmars-d-learn

I wanted to iterate through a date range, so I initially tried:
iota(Date(2016,1,1),Date(2018,1,1),dur!"days"(1));

That wouldn't compile, which is fair enough I guess.

So I tried a for loop:
for (auto i = Date(2016,1,1); i < Date(2018,1,1); 
i+=dur!"days"(1)){}


That seemed to work fine, but I remember reading "for loops are 
bad" somewhere. So I looked for a range type mechanism, and I 
think it's this:
foreach (i; Interval!Date 
(Date(2016,1,1),Date(2018,1,1)).fwdRange ( (a) { return 
a+dur!"days"(1); })){}


My question is if the third way is the proper way of stepping 
through a period of time? It just seems quite complicated to me.


Thanks,

Jordan


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Mar 12, 2018 at 01:04:06AM +, Joe via Digitalmars-d-learn wrote:
> On Sunday, 11 March 2018 at 23:26:04 UTC, Stefan Koch wrote:
> > You have to pass a pointer to the function.
> > Otherwise it'll be a parenthsis-less call.
> > use :  qsort(recs, num_recs, (Record *).sizeof, );
> 
> After passing a pointer, getting some other error messages, I changed
> the call to
> 
> qsort(cast(void *)recs, num_recs, cast(size_t)(Record *).sizeof,
> );
> 
> and the latest error is:
> 
> Error: function core.stdc.stdlib.qsort (scope void* base, ulong nmemb, ulong
> size, extern (C) int function(scope const(void*), scope const(void*))
> @system compar) is not callable using argument types (void*, ulong, ulong,
> int function(const(void*) p1, const(void*) p2))
> 
> I fail to see which argument is causing the problem now.
[...]

I wonder if the problem is because qsort expects a C linkage function
(`extern (C) int function(...)`), but you're passing a D linkage (i.e.,
native) function to it.  You can't do that, because the order of
arguments in a D linkage function may differ from a C linkage function,
and could potentially cause a subtle bug if you're not expecting the
arguments in a different order. (I actually ran into this myself, in a
different context where there was no type enforcement like there is
here, and it took me a long time to track down the problem.)

If indeed this is the problem, try adding `extern (C)` to your D
function to make it compatible with C linkage, and that should do the
trick.  I think.


T

-- 
If you look at a thing nine hundred and ninety-nine times, you are perfectly 
safe; if you look at it the thousandth time, you are in frightful danger of 
seeing it for the first time. -- G. K. Chesterton


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 12 March 2018 at 01:04:06 UTC, Joe wrote:

and the latest error is:


D's error messages are so bad and shouldn't be hard to fix. It 
kills me that basic every-day functionality like this isn't a 
priority to the core devs. I even wrote a patch myself that would 
call this out but it didn't fit the code style so rejected. Ugh. 
But behold:


(scope void* base,
ulong nmemb,
ulong size,
extern (C) int function(scope const(void*), scope const(void*)) 
@system compar)


(void*,
ulong,
ulong,
int function(const(void*) p1, const(void*) p2))



I just reformatted it but now the difference should be visible: 
`extern(C)` is missing on your callback.


The scope things might make a difference too, but I know for sure 
extern(C) is necessary on your callback function.


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

On Sunday, 11 March 2018 at 23:26:04 UTC, Stefan Koch wrote:

You have to pass a pointer to the function.
Otherwise it'll be a parenthsis-less call.
use :  qsort(recs, num_recs, (Record *).sizeof, );


After passing a pointer, getting some other error messages, I 
changed the call to


qsort(cast(void *)recs, num_recs, cast(size_t)(Record 
*).sizeof, );


and the latest error is:

Error: function core.stdc.stdlib.qsort (scope void* base, ulong 
nmemb, ulong size, extern (C) int function(scope const(void*), 
scope const(void*)) @system compar) is not callable using 
argument types (void*, ulong, ulong, int function(const(void*) 
p1, const(void*) p2))


I fail to see which argument is causing the problem now.

Joe


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Stefan Koch via Digitalmars-d-learn

On Sunday, 11 March 2018 at 23:12:30 UTC, Joe wrote:

I'm getting a compiler error in a qsort() call as follows:

qsort(recs, num_recs, (Record *).sizeof, compar);

Record is a struct, recs is a fixed array of pointers to 
Record's and num_recs is a size_t that holds the number of 
valid records.


compar is this:

int compar(const void *p1, const void *p2)
{
import core.stdc.string : strcmp;
const Record **rp1 = cast(Record **)p1;
const Record **rp2 = cast(Record **)p2;

return strcmp((*rp1).name.ptr, (*rp2).name.ptr);
}

The error is: Error: function testd.compar (const(void*) p1, 
const(void*) p2) is not callable using argument types ()


I don't quite understand what those parentheses mean: is it 
implying "no arguments" and if so, where would one provide 
arguments?


Joe


You have to pass a pointer to the function.
Otherwise it'll be a parenthsis-less call.
use :  qsort(recs, num_recs, (Record *).sizeof, );


core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

I'm getting a compiler error in a qsort() call as follows:

qsort(recs, num_recs, (Record *).sizeof, compar);

Record is a struct, recs is a fixed array of pointers to Record's 
and num_recs is a size_t that holds the number of valid records.


compar is this:

int compar(const void *p1, const void *p2)
{
import core.stdc.string : strcmp;
const Record **rp1 = cast(Record **)p1;
const Record **rp2 = cast(Record **)p2;

return strcmp((*rp1).name.ptr, (*rp2).name.ptr);
}

The error is: Error: function testd.compar (const(void*) p1, 
const(void*) p2) is not callable using argument types ()


I don't quite understand what those parentheses mean: is it 
implying "no arguments" and if so, where would one provide 
arguments?


Joe


Re: How do you call an eponymous template that has a secondary template arg?

2018-03-11 Thread aliak via Digitalmars-d-learn

On Sunday, 11 March 2018 at 13:44:38 UTC, Basile B. wrote:


The first version works here:

```
template aliasOf(T) {
enum aliasOf(alias a) = is(typeof(a) == T);
}

string s;

pragma(msg, allSatisfy!(aliasOf!string, s, "string"));
```



I can see that my description was a little confusing, sorry about 
that, I meant to ask how would you call that without using the 
allSatisfy meta template. If I were to call it as a stand alone, 
ie:


writeln(aliasOf!stringtemplate?>);


I hope that makes it clearer.


Now on the fact that what is done is correct is another story.
If the literal passed is supposed to be a type then it's 
clearly wrong.

You'd have to mix it:

```
template aliasOf(T)
{
template aliasOf(alias a)
{
mixin("alias A = " ~ a ~ ";");
enum aliasOf = is(A == T);
}
}

alias myString1 = string;
alias myString2 = string;

pragma(msg, allSatisfy!(aliasOf!string, "myString1", 
"myString2"));

```


Aye, I see what you mean, but it is supposed to be a literal of a 
specific type. I.e. 3, "some string", SomeType(), etc.


So aliasOf!int.aliasOf!3 // true

Also, if I define it like this:

template aliasOf(T) {
auto aliasOf(U)(U) { return is(U == T); }
}

Then at least I can call it like:

writeln(aliasOf!int(3)); // prints true

But then I can't do:

allSatisfy!(aliasOf!int, 3)

I guess because it's a function now and not a template anymore so 
can't be used by allSatisfy.








Re: Inner Classes vs. Inner Structs

2018-03-11 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, March 11, 2018 13:19:39 Mike Franklin via Digitalmars-d-learn 
wrote:
> This works:
>
> ```
> class S {
>  int n, m;
>  int sum() { return n + m; }
>  Inner!(sum) a;
>
>  class Inner(alias f){
>  auto get() {
>  return f();
>  }
>  }
> }
> ```
>
> This doesn't:
>
> ```
> struct S {
>  int n, m;
>  int sum() { return n + m; }
>  Inner!(sum) a;
>
>  struct Inner(alias f){
>  auto get() {
>  return f(); // Error: this for sum needs to be type S
> not type Inner!(sum)
>  }
>  }
> }
> ```
>
> The only difference between the two is one one uses classes, the
> other uses structs.  My question is, under the current semantics
> of D, shouldn't the two work the same?  That is, shouldn't the
> inner struct in the second example have an implicit context
> reference to the outer struct?  Is this a bug?

No, it's on purpose, and the only reason that non-static, nested classes
have access to the class they're declared in is for compatibility with Java,
which doesn't have structs. Also, I suspect that if D were being designed
now, it would treat nested classes the same as nested structs rather than
treating nested structs like it currently does nested classes. Some of D's
design has a number of Java-isms because of when D was first started and the
fact that it didn't have some of features that it has now. Certainly, if we
included the feature at this point if we were redesigning the language, I
expect that it would only be to make porting Java code easier.

Regardless, changing the current behavior would break code, so I doubt that
it's going to change. IIRC, DWT relies on the behavior with classes (since
it's code ported from Java), and while I question that all that much D code
outside of DWT takes advantage of non-static, nested classes, I suspect that
having non-static, nested structs suddenly act differently from static,
nested structs would break a fair bit of D code. There is of course no way
to know how much code would break with either change, but I doubt that
Walter would agree to the potential code breakage in either direction.

- Jonathan M Davis



Re: UFCS in generic libraries, silent hijacking, and compile errors.

2018-03-11 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, March 11, 2018 08:39:54 aliak via Digitalmars-d-learn wrote:
> On Saturday, 10 March 2018 at 23:00:07 UTC, Jonathan M Davis
> > issue in practice. That doesn't mean that it's never a problem,
> > but from what I've seen, it's very rarely a problem, and it's
> > easy to work around if you run into a particular case where it
> > is a problem.
>
> Ya, it's easy to work around but the caveat there is you need to
> realize it's happening first, and add that to that it's "rarely a
> problem" and well ... now it seems scary enough for this to
> mentioned somewhere I'd say.

You're talking about a situation where you used a function whose parameters
match that of a member function exactly enough that a member function gets
called instead of a free function. That _can_ happen, but in most cases,
there's going to be a mismatch, and you'll get a compiler error if the type
defines a member function that matches the free function. I don't think that
I have ever seen that happen or ever seen anyone complain about it. The only
case I recall along those lines was someone who was trying to use a free
function that they'd decided to call front instead of something else, and it
had parameters beyond just the input range, so that programmer got
compilation errors when they tried to use it in their range-based functions.

I think that this is really a theoretical concern and not a practical one.
Certainly, it's really only going to potentially be an issue in library code
that gets used by a ton of folks with completely unexpected types. If it's
in your own code, you're usually well aware of what types are going to be
used with a generic function, and proper testing would catch the rare case
where there would be a problem. If you're really worried about it, then just
don't use UFCS, but for better or worse, it seems to be the case that the
vast majority of D programmers use UFCS all the time and don't run into
problems like this.

> > The one case that I am aware of where best practice is to avoid
> > UFCS is with put for output ranges, but that has nothing to
> > with your concerns here. Rather, it has to do with the fact
> > that std.range.primitives.put has a lot of overloads for
> > handling various arguments (particularly when handling ranges
> > of characters), and almost no one implements their output
> > ranges with all of those overloads. So, if you use put with
> > UFCS, you tend to run into problems if you do anything other
> > than put a single element of the exact type at a time, whereas
> > the free function handles more cases (even if they ultimately
> > end up calling that member function with a single argument of
> > the exact type). We probably shouldn't have had the free
> > function and the member function share the same name.
>
> Oh, can you share a short example here maybe? Not sure I followed
> completely
>
> Is it basically:
>
> // if r is output range
>
> r.put(a, b) // don't do this?
>
> put(r, a, b) // but do this?
>
> (Cause compilation error)

Essentially yes, though you're passing too many arguments to put. There are
cases where put(output, foo) will compile while output.put(foo) will not. In
particular, std.range.primitives.put will accept both individual elements to
be written to the output range and ranges of elements to be written, whereas
typically, an output range will be written to only accept an element at a
time. It's even more extreme with output ranges of characters, because the
free function put will accept different string types and convert them, and
even if the programmer who designed the output range added various overloads
to put for completeness, it's enough extra work to deal with all of the
various character types that they probably didn't. And put also works with
stuff like delegates (most frequently used with a toString that accepts an
output range), which don't have member functions. So, if you write your
generic code to use the member function put, it's only going to work with
user-defined types that define the particular overload(s) of put that you're
using in your function, whereas if you use the free function, you have more
variety in the types of output ranges that your code works with, and you
have more ways that you can call put (e.g. passing a range of elements
instead of a single element).

> How about if it's not part of the overload set, but is looked up
> if the function does not exist in the overload set. What would
> the problems there be?
>
> Basically I don't see a reason why we wouldn't want the following
> to work:
>
> struct S { void f() {} }
> void f(S s, int i) {}
> S().f(3); // error

So, are you complaining that it's an error, or you want it to be an error?
As it stands, it's an error, because as far as the compiler is concerned,
you tried to call a member function with an argument that it doesn't accept.

If you want that code to work, then it would have to add the free function
to the overload set while somehow leaving out the overloads 

Re: How do you call an eponymous template that has a secondary template arg?

2018-03-11 Thread Basile B. via Digitalmars-d-learn

On Sunday, 11 March 2018 at 12:05:56 UTC, aliak wrote:

Eg:

template aliasOf(T) {
enum aliasOf(alias a) = is(typeof(a) == T);
}

The use case for this is for std.meta.allSatisfy for variadic 
args, i.e.


template T(values...) if (allSatisfy!(aliasOf!string, values) { 
... }


But how do you call that template otherwise?

I've tries:

* aliasOf!int!"string" // multiple ! arguments are not allowed
* (aliasOf!int)!"string" // error c-style cast
* aliasOf!int.aliasOf!"string" // template isAliasOf(alias a) 
does not have property 'isAliasOf


I can work around this by:

template typeOf(T) {
enum isAliasedBy(alias a) = is(typeof(a) == T);
}

and then do:

template T(values...) if 
(allSatisfy!(typeOf!string.isAliasedBy, values) { ... }


But I like the readability of the former better if there's a 
way to achieve it?


Cheers
- Ali


The first version works here:

```
template aliasOf(T) {
enum aliasOf(alias a) = is(typeof(a) == T);
}

string s;

pragma(msg, allSatisfy!(aliasOf!string, s, "string"));
```

Now on the fact that what is done is correct is another story.
If the literal passed is supposed to be a type then it's clearly 
wrong.

You'd have to mix it:

```
template aliasOf(T)
{
template aliasOf(alias a)
{
mixin("alias A = " ~ a ~ ";");
enum aliasOf = is(A == T);
}
}

alias myString1 = string;
alias myString2 = string;

pragma(msg, allSatisfy!(aliasOf!string, "myString1", 
"myString2"));

```


Re: Forwarding arguments through a std.algorithm.map

2018-03-11 Thread Stefan Koch via Digitalmars-d-learn

On Saturday, 10 March 2018 at 20:48:06 UTC, Nordlöw wrote:

If I have a function

bool f(Rs...)(Rs rs)

is it somehow possible to map and forward all its arguments 
`rs` to another function


bool g(Rs...)(Rs rs);

through a call to some map-and-forward-like-function 
`forwardMap` in something like


bool f(Rs...)(Rs rs)
{
alias someArbitraryFun = _ => _;
return g(forwardMap!(someArbitraryFun)(rs));
}

?

What should the definition of forwardMap look like?

Does Phobos contain something like this already?


there is staticMap.


Inner Classes vs. Inner Structs

2018-03-11 Thread Mike Franklin via Digitalmars-d-learn

This works:

```
class S {
int n, m;
int sum() { return n + m; }
Inner!(sum) a;

class Inner(alias f){
auto get() {
return f();
}
}
}
```

This doesn't:

```
struct S {
int n, m;
int sum() { return n + m; }
Inner!(sum) a;

struct Inner(alias f){
auto get() {
return f(); // Error: this for sum needs to be type S 
not type Inner!(sum)

}
}
}
```

The only difference between the two is one one uses classes, the 
other uses structs.  My question is, under the current semantics 
of D, shouldn't the two work the same?  That is, shouldn't the 
inner struct in the second example have an implicit context 
reference to the outer struct?  Is this a bug?


Thanks for the help,
Mike


Re: Error compiling with DUB (dmd) since yesterday dub update

2018-03-11 Thread Seb via Digitalmars-d-learn

On Sunday, 11 March 2018 at 07:17:58 UTC, Mario wrote:
On Sunday, 11 March 2018 at 07:11:09 UTC, rikki cattermole 
wrote:

On 11/03/2018 8:02 PM, Mario wrote:
On Sunday, 11 March 2018 at 06:59:32 UTC, rikki cattermole 
wrote:

On 11/03/2018 7:55 PM, Mario wrote:

[...]


Are you aware that it is compiling with ldc?


Actually, I didn't even realize XD. I'm a newbie in VibeD and 
DLang, should I change it? Why did compiling work yesterday?


Thanks in advance


Workaround switch to dmd.
Real solution please file a bug for Botan and attach your log 
in.


Thank you, I followed your advice and I created an issue on the 
GitHub project: https://github.com/etcimon/botan/issues/42


Or simply use the built-in openssl 1.1?


How do you call an eponymous template that has a secondary template arg?

2018-03-11 Thread aliak via Digitalmars-d-learn

Eg:

template aliasOf(T) {
enum aliasOf(alias a) = is(typeof(a) == T);
}

The use case for this is for std.meta.allSatisfy for variadic 
args, i.e.


template T(values...) if (allSatisfy!(aliasOf!string, values) { 
... }


But how do you call that template otherwise?

I've tries:

* aliasOf!int!"string" // multiple ! arguments are not allowed
* (aliasOf!int)!"string" // error c-style cast
* aliasOf!int.aliasOf!"string" // template isAliasOf(alias a) 
does not have property 'isAliasOf


I can work around this by:

template typeOf(T) {
enum isAliasedBy(alias a) = is(typeof(a) == T);
}

and then do:

template T(values...) if (allSatisfy!(typeOf!string.isAliasedBy, 
values) { ... }


But I like the readability of the former better if there's a way 
to achieve it?


Cheers
- Ali



Re: Forwarding arguments through a std.algorithm.map

2018-03-11 Thread Seb via Digitalmars-d-learn

On Saturday, 10 March 2018 at 20:48:06 UTC, Nordlöw wrote:

If I have a function

bool f(Rs...)(Rs rs)

is it somehow possible to map and forward all its arguments 
`rs` to another function


bool g(Rs...)(Rs rs);

through a call to some map-and-forward-like-function 
`forwardMap` in something like


bool f(Rs...)(Rs rs)
{
alias someArbitraryFun = _ => _;
return g(forwardMap!(someArbitraryFun)(rs));
}

?

What should the definition of forwardMap look like?

Does Phobos contain something like this already?


Not sure whether I understand what you are looking for, but 
std.functional is your friend here I think pipe/compose is the 
function you are searching for.


https://dlang.org/phobos/std_functional.html#forward
https://dlang.org/phobos/std_functional.html#partial
https://dlang.org/phobos/std_functional.html#pipe


Re: UFCS in generic libraries, silent hijacking, and compile errors.

2018-03-11 Thread aliak via Digitalmars-d-learn
On Saturday, 10 March 2018 at 23:00:07 UTC, Jonathan M Davis 
wrote:


The idea is that the type can provide its own version of the 
function that is better optimized for it - e.g. it could 
potentially provide a member function find that is more 
efficient for it than std.algorithm.searching.find. That's 
actually the only technical reason why UFCS is superior to the 
normal function call syntax.


I think this may have hit the nail on the spot. So basically my 
thinking is that if you're going to use UFCS inside a generic 
function where you can't know what kind of methods the type has, 
do not do it unless you want this particular behavior or if your 
intent is to use a type's known API.


issue in practice. That doesn't mean that it's never a problem, 
but from what I've seen, it's very rarely a problem, and it's 
easy to work around if you run into a particular case where it 
is a problem.


Ya, it's easy to work around but the caveat there is you need to 
realize it's happening first, and add that to that it's "rarely a 
problem" and well ... now it seems scary enough for this to 
mentioned somewhere I'd say.




The one case that I am aware of where best practice is to avoid 
UFCS is with put for output ranges, but that has nothing to 
with your concerns here. Rather, it has to do with the fact 
that std.range.primitives.put has a lot of overloads for 
handling various arguments (particularly when handling ranges 
of characters), and almost no one implements their output 
ranges with all of those overloads. So, if you use put with 
UFCS, you tend to run into problems if you do anything other 
than put a single element of the exact type at a time, whereas 
the free function handles more cases (even if they ultimately 
end up calling that member function with a single argument of 
the exact type). We probably shouldn't have had the free 
function and the member function share the same name.


Oh, can you share a short example here maybe? Not sure I followed 
completely


Is it basically:

// if r is output range

r.put(a, b) // don't do this?

put(r, a, b) // but do this?

(Cause compilation error)




Is there something I'm not seeing as to why UFCS is not part 
of the overload set, and is there a way other than not using 
UFCS to prevent the silent hijacking?


If it were part of the overload set, then you have problems 
calling member functions, particularly because there is no way 
to call a member function other than with UFCS, whereas you can 
call free functions without UFCS, and if you _really_ want to 
be sure that a very specific function is called, then you can 
even give its entire module path when calling it. When UFCS was 
introduced, it was decided that having member functions always 
win out would cause the fewest problems.


- Jonathan M Davis


Ah yes, ok this makes sense.

Follow up:

How about if it's not part of the overload set, but is looked up 
if the function does not exist in the overload set. What would 
the problems there be?


Basically I don't see a reason why we wouldn't want the following 
to work:


struct S { void f() {} }
void f(S s, int i) {}
S().f(3); // error

Thanks!