Re: can not find the error: Error: TypeInfo cannot be used with -betterC

2019-07-17 Thread aliak via Digitalmars-d-learn

On Wednesday, 17 July 2019 at 15:52:39 UTC, Newbie2019 wrote:

when build my project with -betterC, it throw this error:

Error: TypeInfo cannot be used with -betterC

There is no location information about it,  how can I find what 
code cause this ?


You usually get that *extrememly* unhelpful error message when 
you use anything that uses TypeInfo. So it can be quite hard to 
figure out.


Did it start happening after you added a class or did something 
with exceptions? At least those would cause that error.


segfault in ldc release only - looks like some kind of optimization bug?

2019-07-22 Thread aliak via Digitalmars-d-learn

Hi,

so I had this weird bug that was driving me crazy and only 
segfaulted with ldc in release build - (I'm using ldc 1.16.0).


This is the code that segfaults. All parts seem to be necessary 
for it to happen, or at least I think so. I've gone in circles 
minimizing so I've probably missed something. But this seems to 
be it:


import std;

struct W(T) {
T value;
ref inout(T) front() inout { return value; }
}

auto ref get(T)(W!T value) {
return value.front;
}

struct S {
string a;
}

void main() {
S[string] aa;
aa = ["one" : S("a")];
auto b = W!S(aa["one"]).get;
writeln(b);
}

Running with ldc and -O3 crashes: "ldc2 -O3 -run source.d"

Some things I've noticed:
- if you remove the call to .get and use .value directly, the 
crash goes

- if you remove the inout specifier on front(), the crash goes
- if you remove the ref specifier on front(), the crash goes
- if you don't call writeln(b), the crash goes
- if you don't use the s returned by the aa, the crash goes
- if you *add* a return qualifier on the "front" function, the 
crash goes away


(what is that return thing btw and when do you use it?)

Any ideas?



Re: segfault in ldc release only - looks like some kind of optimization bug?

2019-07-22 Thread aliak via Digitalmars-d-learn

On Tuesday, 23 July 2019 at 00:36:49 UTC, Exil wrote:

auto ref get(T)(W!T value) {
return value.front;
}

You're returning a reference to a temporary that gets deleted 
at the end of the function's scope. The "auto ref" here will be 
a "ref".


. oh ... shit you're right.

Ok so this was minimized from this:

const config = Config.ghApp(ghDomain)
.orElseThrow!(() => new Exception(
"could not find config for domain 
'%s'".format(ghDomain)

));

Where Config.ghApp return an Optional!GhApp, and orElseThrow 
checks if a range has is not empty and returns front. The front 
in Optional is defined as the front above...


So is that an incorrect idiom to use when writing a library then? 
I pretty sure I've seen it in phobos too.


Slapping return on the function also fixes it. Is that the 
correct way to write a .front?


Thanks!


dip1000, perhaps annotate with return, and vibe-d

2019-07-24 Thread aliak via Digitalmars-d-learn

Trying to get dip1000 flag in use. I have this error:

Error: returning Optional(null, false).this(value) escapes a 
reference to parameter value, perhaps annotate with return


in this function:

public auto some(T)(auto ref T value) {
return Optional!T(value); // <-- error on this line
}

And it's instantiated from here:

static Optional!T fromRepresentation(Json value) {
  if (value == Json.undefined) {
return no!T;
  }
  return some(deserializeJson!T(value)); // <-- instantiated from 
here

}

I put the qualifier "return" on the parameter to some, but did 
nothing. And I put it on Optional.this() as well, but I'm not 
sure where I'm supposed to put it.


The constructor for Optional takes an auto ref T ... I'm not sure 
that makes sense. Does it make sense to take a constructor 
parameter that is copied in to the struct by auto ref if you're 
not calling .move on it explicitly?


And as for vibe-d, I get this when compiling with dip1000:

Also, vibe-d gives me this: 
../../../.dub/packages/vibe-core-1.6.2/vibe-core/source/vibe/internal/traits.d(391,2): Error: static assert:  "FileStream does not implement method "read" of type @safe ulong(scope ubyte[] dst, IOMode mode)"


Has anyone seen that or used vibed with dip1000?


Re: dip1000, perhaps annotate with return, and vibe-d

2019-07-25 Thread aliak via Digitalmars-d-learn

On Wednesday, 24 July 2019 at 16:23:48 UTC, Paul Backus wrote:

On Wednesday, 24 July 2019 at 12:54:51 UTC, aliak wrote:

[...]


It should go on the constructor's parameter; i.e.,

this(auto return ref T value) { /* ... */ }

Under the hood, a constructor actually returns the constructed 
value by reference, so the actual signature of the above 
constructor seen by the lifetime checker is:


ref Optional!T __ctor(auto return ref T value)

You can see this for yourself with something like `pragma(msg, 
typeof(Optional!T.__ctor))`.


Thanks! The under the hood stuff was good to know!

I was putting it in the right place but it seems to still have 
been complaining. Ah well. I guess an auto ref on a constructor 
doesn't really make sense anyway.


Any way to move in @disabled this(this) type in to a wrapping template?

2019-07-25 Thread aliak via Digitalmars-d-learn
Basically, can template W be made to handle an S that can't be 
copied?


import std;

static struct S {
int i;
@disable this(this);
this(int i) { this.i = i; }
}

struct W(T) {
T value;
this(T value) {
this.value = value;
}
}

auto wrap(T)(T value) {
return W!T(value);
}

void main() {
auto a = wrap(S(3));
}

I tried doing something like:

W!T construct(Args...)(auto ref Args args) {
  import std.algorithm: move;
  auto value = T(args);
  W!T w;
  w.value = move(value);
  return move(opt);
}


Re: Any way to move in @disabled this(this) type in to a wrapping template?

2019-07-25 Thread aliak via Digitalmars-d-learn

On Thursday, 25 July 2019 at 19:35:36 UTC, aliak wrote:
Basically, can template W be made to handle an S that can't be 
copied?


import std;

static struct S {
int i;
@disable this(this);
this(int i) { this.i = i; }
}

struct W(T) {
T value;
this(T value) {
this.value = value;
}
}

auto wrap(T)(T value) {
return W!T(value);
}

void main() {
auto a = wrap(S(3));
}

I tried doing something like:

W!T construct(Args...)(auto ref Args args) {
  import std.algorithm: move;
  auto value = T(args);
  W!T w;
  w.value = move(value);
  return move(opt);
}


So this works - are there any problems with it?

struct W(T) {
T value;
this(T value) {
static if (isMutable!T)
this.value = value.move;
else
this.value = value;
}
}

auto wrap(T)(T value) {
static if (isMutable!T)
return W!T(value.move);
else
return W!T(value);
}

Shouldn't this be happening by default? When would you not want 
that to happen?


Re: Any way to move in @disabled this(this) type in to a wrapping template?

2019-07-25 Thread aliak via Digitalmars-d-learn

On Thursday, 25 July 2019 at 21:23:33 UTC, Paul Backus wrote:

On Thursday, 25 July 2019 at 20:38:59 UTC, aliak wrote:

On Thursday, 25 July 2019 at 19:35:36 UTC, aliak wrote:
Basically, can template W be made to handle an S that can't 
be copied?


import std;

static struct S {
int i;
@disable this(this);
this(int i) { this.i = i; }
}

[...]


So this works - are there any problems with it?

struct W(T) {
T value;
this(T value) {
static if (isMutable!T)
this.value = value.move;
else
this.value = value;
}
}

auto wrap(T)(T value) {
static if (isMutable!T)
return W!T(value.move);
else
return W!T(value);
}

Shouldn't this be happening by default? When would you not 
want that to happen?


The way I handle this is with `auto ref` and 
`core.lifetime.forward`:


import core.lifetime: forward;

struct W(T)
{
T value;
this()(auto ref T value)
{
this.value = forward!value;
}
}

auto wrap(T)(auto ref T value)
{
return W!T(forward!value);
}

@safe unittest
{
static struct NoCopy { @disable this(this); }
assert(__traits(compiles, {
auto test = wrap(NoCopy());
}));
assert(!__traits(compiles, {
auto lval = NoCopy(); auto test = lval;
}));
}

Interactive: https://run.dlang.io/is/kDJyYC

It's not very well documented, but `forward` does essentially 
the same thing as your `static if` + `move` combination.


Note that with both your version and mine, you will run into 
the same problem I did of `move` making it impossible to use 
instances of `W` in static initializers and CTFE. [1] The best 
compromise I was able to come up with was to only call move if 
`isCopyable!T == false`, which doesn't really solve the 
problem, but at least contains it.


[1] https://github.com/pbackus/sumtype/issues/22


Haha. Ironic. Thanks, again :)

Though, if you use auto ref, and you check if it's mutable and 
not copyable and then move, then that means you could potentially 
be applying move to an object on behalf of the clients


auto a = MyUnmovableType()
auto b = LibraryType(a);
writeln(a); // ??

If this is a problem, I guess a __traits(isRef, parameter) check 
along with mutable and copyable could help. Then if client want 
it moved they could call move explicitly.


Re: cannot use local __lambda1 as parameter to non-global template

2019-07-26 Thread aliak via Digitalmars-d-learn

On Friday, 26 July 2019 at 16:20:10 UTC, aliak wrote:
Can someone help me understand the details around why this 
fails?


import std;

struct W(T) {
T value;
auto hook(handlers...)() {
return handlers[0](value);
}
}

template f(handlers...) {
auto ref f(T)(auto ref T value) {
return value.hook!handlers;
}
}

@nogc void main() {
auto a = W!int(3);
auto b = a.f!((_) => "yes");
}

If I specifically type the lambda I pass in to f (i.e. (int _) 
=> "yes") then it works. Or if I make hook a global template 
that takes a W!T as the first parameter it also works. Is there 
a work around for this?


Err sorry, that was ldc pre the 5710 bug fix. In DMD I get this:

Error: @nogc function D main cannot call non-@nogc function 
onlineapp.main.f!(W!int).f


I guess it's allocating a delegate somewhere. Can I fix that?


Re: cannot use local __lambda1 as parameter to non-global template

2019-07-26 Thread aliak via Digitalmars-d-learn

On Friday, 26 July 2019 at 16:21:52 UTC, aliak wrote:

On Friday, 26 July 2019 at 16:20:10 UTC, aliak wrote:
Can someone help me understand the details around why this 
fails?


import std;

struct W(T) {
T value;
auto hook(handlers...)() {
return handlers[0](value);
}
}

template f(handlers...) {
auto ref f(T)(auto ref T value) {
return value.hook!handlers;
}
}

@nogc void main() {
auto a = W!int(3);
auto b = a.f!((_) => "yes");
}

If I specifically type the lambda I pass in to f (i.e. (int _) 
=> "yes") then it works. Or if I make hook a global template 
that takes a W!T as the first parameter it also works. Is 
there a work around for this?


Err sorry, that was ldc pre the 5710 bug fix. In DMD I get this:

Error: @nogc function D main cannot call non-@nogc function 
onlineapp.main.f!(W!int).f


I guess it's allocating a delegate somewhere. Can I fix that?


I can do this but ugh:

import std;

struct W(T) {
T value;
static auto hook(handlers...)(auto ref typeof(this) self) {
return handlers[0](self.value);
}
}

template f(handlers...) {
auto ref f(T)(auto ref T value) {
return value.hook!handlers(value);
}
}

@nogc void main() {
auto a = W!int(3);
auto b = a.f!((_) => "yes");
}


cannot use local __lambda1 as parameter to non-global template

2019-07-26 Thread aliak via Digitalmars-d-learn

Can someone help me understand the details around why this fails?

import std;

struct W(T) {
T value;
auto hook(handlers...)() {
return handlers[0](value);
}
}

template f(handlers...) {
auto ref f(T)(auto ref T value) {
return value.hook!handlers;
}
}

@nogc void main() {
auto a = W!int(3);
auto b = a.f!((_) => "yes");
}

If I specifically type the lambda I pass in to f (i.e. (int _) => 
"yes") then it works. Or if I make hook a global template that 
takes a W!T as the first parameter it also works. Is there a work 
around for this?


Re: Passing nested template function

2019-08-10 Thread aliak via Digitalmars-d-learn

On Saturday, 10 August 2019 at 17:45:43 UTC, Prateek Nayak wrote:
A nested function can be passed to another function evident 
from this example: https://run.dlang.io/is/6waRkB


However if the nested function is a template function, it 
raises an error

https://run.dlang.io/is/PQhkwl
The error being: cannot get frame pointer to the nested function

Is there a way to pass a nested template function to a function 
declared outside the outer function scope?


This looks like it could be a bug to me. If you explicitly 
instantiate the nested template and call dispatch like 
dispatch!(nested!0) then it works.


An alias template parameter can accept both a template and an 
instantiated template. I.e.


template X(T) {}
alias A = X; // ok
alias B = X!int; // ok

So it's unclear what should happen. At the least, the defaulted 
argument should be applied at the call site (Func(a)).


Note though that neither versions will work on ldc or gdc 
however. Because there's a bug [0] that has only been fixed in 
for dmd.


[0] https://github.com/dlang/dmd/pull/9282


advise about safety of using move in an opAssign with __traits(isRef

2019-08-16 Thread aliak via Digitalmars-d-learn
Hi, I'm trying to fix a use-case where you have a wrapper 
template type (it's an optional) and the wrapping type has 
@disable this(this). And having this scenario work:


struct S {
  @disable this(this);
}
Optional!S fun() {...}

Optional!S a;
a = fun.move;

Now that won't work because of the disabled copy, but you can 
either:


1) Add an explicit move function in the Optional type:
struct Optional {
  auto move(ref Optional!T target) {
import std.algorithm: move;
return move(this, target);
  }
}

Then you  could do:
fun.move(field);

First of all I find the readability confusing, so there's no way 
to know if fun is moving in to field or field is moving in to 
fun. But OTOH it matches the phobos move(T src, T target). So 
conventionally maybe ok. Also it's explicit, so it makes it clear 
at the call site that a move is happening.


2) use isRef inside opAssign like this:

void opAssign(auto ref Optional!T lhs) {
  static if (__traits(isRef, lhs)) {
this._value = lhs._value;
  } else {
import std.algorithm: move;
move(lhs._value, this._value);
  }
}

Then you could just do:

field = fun

And it'll just work since fun returns an rvalue. The second 
solution it seems like it'll just work correctly with the static 
if guard. But I'm not sure if there're any gotchas I should be 
aware of?


Any advice?



Re: advise about safety of using move in an opAssign with __traits(isRef

2019-08-17 Thread aliak via Digitalmars-d-learn

On Friday, 16 August 2019 at 14:29:26 UTC, Paul Backus wrote:

On Friday, 16 August 2019 at 08:07:28 UTC, aliak wrote:

[...]


Even simpler:

void opAssign(auto ref Optional!T rhs) {
import core.lifetime: forward;
this._value = forward!rhs;
}


That doesn't work with private members unfortunately :( - i.e. 
this.value = forward!(rhs._value) - member inaccessible.


Is there a known workaround for that? If not then should I just 
copy the implementation in place to be correct?


Re: advise about safety of using move in an opAssign with __traits(isRef

2019-08-18 Thread aliak via Digitalmars-d-learn

On Saturday, 17 August 2019 at 16:43:51 UTC, Paul Backus wrote:

On Friday, 16 August 2019 at 08:07:28 UTC, aliak wrote:
Hi, I'm trying to fix a use-case where you have a wrapper 
template type (it's an optional) and the wrapping type has 
@disable this(this). And having this scenario work:


struct S {
  @disable this(this);
}
Optional!S fun() {...}

Optional!S a;
a = fun.move;

Now that won't work because of the disabled copy


Are you sure? I tried to reproduce the error you're describing, 
and I couldn't do it. The following compiles and runs without 
any issues:


struct Wrapper(T) { T value; }
struct NoCopy { @disable this(this); }

Wrapper!NoCopy fun()
{
return Wrapper!NoCopy();
}

void main()
{
Wrapper!NoCopy a;
a = fun(); // already an rvalue, so moved implicitly
}

Can you give a more complete example of the problem you're 
having?


You'll get the error if you define an opAssign:

struct Wrapper(T) {
T value;
void opAssign(U : T)(Wrapper!U other) {
this.value = other.value;
}
}

struct S {
  @disable this(this);
}

Wrapper!S fun() { return Wrapper!S(S()); }

void main() {
Wrapper!S a;
a = fun;
}




deep copying a struct

2019-09-06 Thread aliak via Digitalmars-d-learn

Are there any library APIs that allow this:

struct S {
int[] arr;
}

void main() {
const a = S([1,2,3]);
S b = a.copy; // deep dup/copy
}


I'd also like to avoid implementing a copy constructor for each 
type.


Re: deep copying a struct

2019-09-06 Thread aliak via Digitalmars-d-learn

On Friday, 6 September 2019 at 10:37:16 UTC, aliak wrote:

Are there any library APIs that allow this:


I just put this together. Any holes other the AA related ones?

Will it work with classes?

auto dupDeep(T)(ref T thing) {
import std.range: ElementType;
import std.traits: hasAliasing, Unqual, isArray;

static if (isArray!T) {
Unqual!(ElementType!T)[] copy;
foreach (elem; thing) {
copy ~= elem.dupDeep;
}
} else static if (hasAliasing!T) {
Unqual!T copy;
foreach (i, field; thing.tupleof) {
copy.tupleof[i] = field.dupDeep;
}
} else {
Unqual!T copy;
copy = thing;
}
return copy;
}



Spawning a process, then killing it on SIGINT

2019-11-23 Thread aliak via Digitalmars-d-learn
Is there a way to go about killing a process after spawning it on 
a SIGINT?


I can't do this for e.g. because kill is not @nogc.

Pid currentSpawnedPid;
extern(C) void killCurrentPidHandler(int sig) nothrow @nogc 
@system {

  kill(currentSpawnedPid, sig);
}

int main() {
  currentSpawnedPid = spawnProcess(["docker-compose", "up"], 
stdin, stdout, stderr);

  signal(SIGINT, &killCurrentPidHandler);
  return wait(currentSpawnedPid);
}

Any other ways to go about this?

Cheers,
- Ali


Re: Spawning a process, then killing it on SIGINT

2019-11-24 Thread aliak via Digitalmars-d-learn

On Saturday, 23 November 2019 at 10:09:51 UTC, mipri wrote:

On Saturday, 23 November 2019 at 09:54:48 UTC, aliak wrote:
Is there a way to go about killing a process after spawning it 
on a SIGINT?


I can't do this for e.g. because kill is not @nogc.


Well, this works:

import std;
import core.stdc.signal;

extern(C) int kill(int pid, int sig) nothrow @nogc @system;

int currentSpawnedPid;
extern(C) void killCurrentPidHandler(int sig) nothrow @nogc 
@system {

  if (currentSpawnedPid > 1)
kill(currentSpawnedPid, sig);
}

int main() {
  auto pid = spawnProcess(["sleep", "50s"], stdin, stdout, 
stderr);

  currentSpawnedPid = pid.processID;
  signal(SIGINT, &killCurrentPidHandler);
  return wait(pid);
}


Thanks, looks like I'll have to go that route.


Re: Spawning a process, then killing it on SIGINT

2019-11-24 Thread aliak via Digitalmars-d-learn
On Saturday, 23 November 2019 at 12:19:27 UTC, Steven 
Schveighoffer wrote:

On 11/23/19 4:54 AM, aliak wrote:
Is there a way to go about killing a process after spawning it 
on a SIGINT?


I can't do this for e.g. because kill is not @nogc.

Pid currentSpawnedPid;
extern(C) void killCurrentPidHandler(int sig) nothrow @nogc 
@system {

   kill(currentSpawnedPid, sig);
}

int main() {
   currentSpawnedPid = spawnProcess(["docker-compose", "up"], 
stdin, stdout, stderr);

   signal(SIGINT, &killCurrentPidHandler);
   return wait(currentSpawnedPid);
}

Any other ways to go about this?


Yeah, fix phobos. kill should be @nogc/nothrow, and probably 
@safe.


-Steve


Looked in to it, seems step one is getting phobos compiling with 
dip1008 :/

Kill uses enforce.


How to wait for a shell process to finish on ctrl+c before exiting?

2019-11-24 Thread aliak via Digitalmars-d-learn
I'm writing some command line tooling stuff, and one of the 
command spins up a docker compose file (which in short, spins up 
some services and aggregates the output of each service to 
stdout).


When a user presses ctrl+c, i would like to pass on the ctrl+c to 
the spawned process and wait till it handles ctrl+c and then let 
go of the current process.


So far I have this:

int spawnedPid;

extern(C) int kill(int pid, int sig) nothrow @nogc @system;

extern(C) void interruptHandler(int sig) nothrow @nogc @system {
kill(spawnedPid, sig);
}

int spawnProcessAndWait(string[] cmd) {
auto pid = spawnProcess(cmd, stdin, stdout, stderr);
spawnedPid = pid.processID;
signal(SIGINT, &interruptHandler);
int result = wait(pid);
return wait(pid);
}

It doesn't work. I think the call to kill doesn't wait? Is there 
a way to make it wait?


I can't call kill(Pid) or wait(Pid) inside the interrupt handler 
because those are not @nogc [0].


[0]: 
https://forum.dlang.org/thread/mtikzznfaahiltguv...@forum.dlang.org


Re: How to wait for a shell process to finish on ctrl+c before exiting?

2019-11-25 Thread aliak via Digitalmars-d-learn

On Sunday, 24 November 2019 at 16:05:14 UTC, mipri wrote:

On Sunday, 24 November 2019 at 15:44:00 UTC, aliak wrote:

[...]


This might be useful:
---
#! /usr/bin/env rdmd
import std;
import core.stdc.signal;

[...]


waitpid, of course! Thanks agin :)


Re: How to wait for a shell process to finish on ctrl+c before exiting?

2019-11-25 Thread aliak via Digitalmars-d-learn
On Sunday, 24 November 2019 at 17:04:49 UTC, Steven Schveighoffer 
wrote:

On 11/24/19 10:44 AM, aliak wrote:

[...]


Hm.. are you sure that ctrl-c isn't also sending the signal to 
your child process? I thought it did.


-Steve


Yesh, you're right. That extra kill is unnecessary and was 
actually causing problems. So thanks for that!


Re: Referance usage in async function

2019-11-30 Thread aliak via Digitalmars-d-learn

On Saturday, 30 November 2019 at 13:45:00 UTC, kerdemdemir wrote:

I have simplified my problem which can be seen below.

import std.stdio;
import vibe.core.core;
import vibe.core.concurrency;
import vibe.data.json;

void main()
{
int[] list;

bool ListManipulator(ref int[] list)
{
list ~= 2;
list ~= 4;
return true;
}

bool ListManipulatorPointer( int[]* list)
{
*list ~= 2;
*list ~= 4;
return true;
}


auto future = vibe.core.concurrency.async(&ListManipulator, 
list);

future.getResult();

writeln(list); > prints empty list

future = 
vibe.core.concurrency.async(&ListManipulatorPointer, &list);

future.getResult();

writeln(list); > prints [2,4]
}


Why passing the pointer works meanwhile passing as reference 
does nothing? I feel that is more D issue than vibe.d which I 
can learn something I hope.


Erdem


Looks like a bug in vibe: 
https://github.com/vibe-d/vibe-core/blob/master/source/vibe/core/concurrency.d#L1141


The function async doesn't use auto ref on ARGS. So the arguments 
are value copies through. If it used auto ref all the way through 
then it'd probably work:


---
import std;

void async(CALLABLE, ARGS...)(CALLABLE callable, auto ref ARGS 
args) {

callable(args);
}

void main() {
int[] list;
bool ListManipulator(ref int[] list) {
list ~= 2;
list ~= 4;
return true;
}

async(&ListManipulator, list);
writeln(list);
}


Re: Hum Humm, Typedef

2019-12-01 Thread aliak via Digitalmars-d-learn

On Saturday, 30 November 2019 at 18:15:47 UTC, Treebeard wrote:
Hoom, hum, I met a dark forest of complains from the compilers 
here.


[...]


/me thinks it's a bug

Pushed a pr. Let's see.

https://github.com/dlang/phobos/pull/7298


How do you find the struct types in a module? - getting Error: unknown

2020-02-13 Thread aliak via Digitalmars-d-learn

Hi,

I'm trying to get a typed list of structs in my current module 
that matches certain criteria. Something like:


module mod;

struct X {}
struct Y {}

alias allTypes = ListOfTypes!mod;

But I'm having a bit of trouble. I have this so far:

template ListOfTypes(alias T) {
import std.meta;
enum isStruct(string m) = is(mixin(m) == struct);
enum types = Filter!(isStruct, __traits(allMembers, T));
alias toType(string m) = mixin(m);
alias all = staticMap!(toType, types);
alias CommandGroupsOf = all;
}

pragma(msg, ListOfTypes!mod);

But that causes an error I've never seen before:

Error: unknown, please file report on issues.dlang.org
onlineapp.d(30,1):while evaluating `pragma(msg, 
CommandGroupsOf!(mod))`



Any workarounds or maybe insight in to the error?




Re: How do you find the struct types in a module? - getting Error: unknown

2020-02-13 Thread aliak via Digitalmars-d-learn
On Thursday, 13 February 2020 at 15:38:37 UTC, Steven 
Schveighoffer wrote:

On 2/13/20 9:47 AM, aliak wrote:

[...]


Not sure about your error, but here is a working version (don't 
use mixins, use __traits(getMember)):


import std.meta;
template ListOfStructs(alias mod)
{
enum isStruct(string m) = is(__traits(getMember, mod, m) == 
struct);

alias getMember(string m) = __traits(getMember, mod, m);
alias ListOfStructs = staticMap!(getMember, 
Filter!(isStruct, __traits(allMembers, mod)));

}

-Steve


It works without the mixin indeed! Thank you!


Is deprecating a template supposed to work?

2020-02-20 Thread aliak via Digitalmars-d-learn

Is this suppose to give a deprecation error message?

deprecated("a")
alias A(T) = B!T;

template B(T) {
alias B = T;
}

void main() {
A!int a; // should this cause a message "a" ?
}

??

Or am I using it wrong maybe?


Re: Is deprecating a template supposed to work?

2020-02-20 Thread aliak via Digitalmars-d-learn
On Thursday, 20 February 2020 at 23:21:23 UTC, MoonlightSentinel 
wrote:

On Thursday, 20 February 2020 at 22:31:16 UTC, aliak wrote:

Is this suppose to give a deprecation error message?

deprecated("a")
alias A(T) = B!T;

template B(T) {
alias B = T;
}

void main() {
A!int a; // should this cause a message "a" ?
}

??

Or am I using it wrong maybe?


It's a bug, see https://issues.dlang.org/show_bug.cgi?id=20190


Ah, I see. Thanks!


Re: in not working for arrays is silly, change my view

2020-03-02 Thread aliak via Digitalmars-d-learn
On Monday, 2 March 2020 at 15:50:08 UTC, Steven Schveighoffer 
wrote:

On 3/2/20 6:39 AM, JN wrote:
On Saturday, 29 February 2020 at 21:56:51 UTC, Ali Çehreli 
wrote:
Because you mentioned canFind, I think you want the semantics 
to be "is there an element with this value." If so, it would 
be confusing to use the same operator for two different 
things: For associative arrays, it means "is there an element 
accessible with this key."


Does it? I always viewed it as "is this value in list of keys"


Array keys are the element index..

So essentially:

int[int] c1;
int[] c2 = new int[4];
c1[3] = 10;
c2[3] = 10;

assert(3 in c1); // true
assert(3 in c2); // what should this do?

-Steve


If in were to mean "is this value in list of keys" then to be 
consistent:


3 in c2 == 3 < c2.length


Re: in not working for arrays is silly, change my view

2020-03-02 Thread aliak via Digitalmars-d-learn
On Monday, 2 March 2020 at 15:47:26 UTC, Steven Schveighoffer 
wrote:

On 3/2/20 6:52 AM, Andrea Fontana wrote:
On Saturday, 29 February 2020 at 20:11:24 UTC, Steven 
Schveighoffer wrote:
1. in is supposed to be O(lg(n)) or better. Generic code may 
depend on this property. Searching an array is O(n).


Probably it should work if we're using a "SortedRange".


int[] a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
auto p = assumeSorted(a);

assert(3 in p);




That could work. Currently, you need to use p.contains(3). opIn 
could be added as a shortcut.


It only makes sense if you have it as a literal though, as 
p.contains(3) isn't that bad to use:


assert(3 in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].assumeSorted);

-Steve


There's no guarantee that checking if a value is in a sorted list 
is any faster than checking if it's in a non sorted list. It's 
why sort usually switches from a binary-esque algorithm to a 
linear one at a certain size. The list could potentially need to 
be _very_ large for p.contains to make a significant impact over 
canFind(p) AFAIK.


Here's a small test program, try playing with the numbers and see 
what happens:


import std.random;
import std.range;
import std.algorithm;
import std.datetime.stopwatch;
import std.stdio;

void main()
{
auto count = 1_000;
auto max = int.max;

alias randoms = generate!(() => uniform(0, max));

auto r1 = randoms.take(count).array;
auto r2 = r1.dup.sort;
auto elem = r1[uniform(0, count)];

benchmark!(
() => r1.canFind(elem),
() => r2.contains(elem),
)(1_000).writeln;
}

Use LDC and -O3 of course. I was hard pressed to get the sorted 
contains to be any faster than canFind.


This begs the question then: do these requirements on in make any 
sense? An algorithm can be log n (ala the sorted search) but 
still be a magnitude slower than a linear search... what has the 
world come to 🤦‍♂️


PS: Why is it named contains if it's on a SortedRange and canFind 
otherwise?




Re: in not working for arrays is silly, change my view

2020-03-02 Thread aliak via Digitalmars-d-learn
On Monday, 2 March 2020 at 21:33:37 UTC, Steven Schveighoffer 
wrote:

On 3/2/20 3:52 PM, aliak wrote:
On Monday, 2 March 2020 at 15:47:26 UTC, Steven Schveighoffer 
wrote:

On 3/2/20 6:52 AM, Andrea Fontana wrote:
On Saturday, 29 February 2020 at 20:11:24 UTC, Steven 
Schveighoffer wrote:
1. in is supposed to be O(lg(n)) or better. Generic code 
may depend on this property. Searching an array is O(n).


Probably it should work if we're using a "SortedRange".


int[] a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
auto p = assumeSorted(a);

assert(3 in p);




That could work. Currently, you need to use p.contains(3). 
opIn could be added as a shortcut.


It only makes sense if you have it as a literal though, as 
p.contains(3) isn't that bad to use:


assert(3 in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].assumeSorted);

There's no guarantee that checking if a value is in a sorted 
list is any faster than checking if it's in a non sorted list. 
It's why sort usually switches from a binary-esque algorithm 
to a linear one at a certain size.


Well of course! A binary search needs Lg(n) comparisons for 
pretty much any value, whereas a linear search is going to end 
early when it finds it. So there's no guarantee that searching 
for an element in the list is going to be faster one way or the 
other. But Binary search is going to be faster overall because 
the complexity is favorable.


Overall tending towards infinity maybe, but not overall on the 
average case it would seem. Branch prediction in CPUs changes 
that in that with a binary search it is always a miss. Whereas 
with linear it's always a hit.




The list could potentially need to be _very_ large for 
p.contains to make a significant impact over canFind(p) AFAIK.


Here's a small test program, try playing with the numbers and 
see what happens:


import std.random;
import std.range;
import std.algorithm;
import std.datetime.stopwatch;
import std.stdio;

void main()
{
     auto count = 1_000;
     auto max = int.max;

     alias randoms = generate!(() => uniform(0, max));

     auto r1 = randoms.take(count).array;
     auto r2 = r1.dup.sort;
     auto elem = r1[uniform(0, count)];


auto elem = r1[$-1]; // try this instead



     benchmark!(
     () => r1.canFind(elem),
     () => r2.contains(elem),
     )(1_000).writeln;
}

Use LDC and -O3 of course. I was hard pressed to get the 
sorted contains to be any faster than canFind.


This begs the question then: do these requirements on in make 
any sense? An algorithm can be log n (ala the sorted search) 
but still be a magnitude slower than a linear search... what 
has the world come to 🤦‍♂️


PS: Why is it named contains if it's on a SortedRange and 
canFind otherwise?




A SortedRange uses O(lgn) steps vs. canFind which uses O(n) 
steps.


canFind is supposed to tell the reader that it's O(n) and 
contains O(lgn)?




If you change your code to testing 1000 random numbers, instead 
of a random number guaranteed to be included, then you will see 
a significant improvement with the sorted version. I found it 
to be about 10x faster. (most of the time, none of the other 
random numbers are included). Even if you randomly select 1000 
numbers from the elements, the binary search will be faster. In 
my tests, it was about 5x faster.


Hmm... What am I doing wrong with this code? And also how are you 
compiling?:


void main()
{
auto count = 1_000_000;
auto max = int.max;

alias randoms = generate!(() => uniform(0, max - 1));

auto r1 = randoms.take(count).array;
auto r2 = r1.dup.sort;
auto r3 = r1.dup.randomShuffle;

auto results = benchmark!(
() => r1.canFind(max),
() => r2.contains(max),
() => r3.canFind(max),
)(5_000);

results.writeln;
}


$ ldc2 -O3 test.d && ./test
[1 hnsec, 84 μs and 7 hnsecs, 0 hnsecs]



Note that the compiler can do a lot more tricks for linear 
searches, and CPUs are REALLY good at searching sequential 
data. But complexity is still going to win out eventually over 
heuristics. Phobos needs to be a general library, not one that 
only caters to certain situations.


General would be the most common case. I don't think extremely 
large (for some definition of large) lists are the more common 
ones. Or maybe they are. But I'd be surprised. I also don't think 
phobos is a very data-driven library. But, that's a whole other 
conversation :)




-Steve





Re: in not working for arrays is silly, change my view

2020-03-02 Thread aliak via Digitalmars-d-learn
On Monday, 2 March 2020 at 23:27:22 UTC, Steven Schveighoffer 
wrote:


What I think is happening is that it determines nobody is using 
the result, and the function is pure, so it doesn't bother 
calling that function (probably not even the lambda, and then 
probably removes the loop completely).


I'm assuming for some reason, the binary search is not flagged 
pure, so it's not being skipped.


Apparently you're right: 
https://github.com/dlang/phobos/blob/5e13653a6eb55c1188396ae064717a1a03fd7483/std/range/package.d#L11107




If I change to this to ensure side effects:

bool makeImpure; // TLS variable outside of main

...

auto results = benchmark!(
() => makeImpure = r1.canFind(max),
() => makeImpure = r2.contains(max),
() => makeImpure = r3.canFind(max),
)(5_000);

writefln("%(%s\n%)", results); // modified to help with the 
comma confusion


I now get:
4 secs, 428 ms, and 3 hnsecs
221 μs and 9 hnsecs
4 secs, 49 ms, 982 μs, and 5 hnsecs

More like what I expected!


A damn! And here I was thinking that branch prediction made a 
HUGE difference! Ok, I'm taking my tail and slowly moving away 
now :) Let us never speak of this again.




-Steve





Re: Safely wrapping an uncopyable struct to implement an interface

2020-03-04 Thread aliak via Digitalmars-d-learn

On Wednesday, 4 March 2020 at 12:03:48 UTC, Gregor Mückl wrote:

Hi!

I've just created a situation in my code that is summarized by 
the following example. I don't know how to solve it with @safe 
code.


A third party library provides a struct that is not copyable:

// provided by third party
struct Foo {
@disable this() @safe;
@disable this(ref return scope Foo other) @safe;

void magic() @safe;
}

What I want to do is to provide a safe wrapper around it that 
adapts to another interface:


// intended common interface
interface IWrapper {
void bar() @safe;
}

Now, the obvious way to wrap this fails:

class FooWrapper : IWrapper {
Foo f;

this(Foo f) @safe {
this.f = f; // this fails because it would be a copy
}

override void bar() @safe
{
f.magic();
}
}

If Foo were a class, f would be a reference and everything 
would be fine. But f is a struct that can't be copied and 
taking a pointer to f makes FooWrapper obviously unsafe. How 
could I solve this?


I've come up with a workaround for my actual use case that 
doesn't need to use the uncopyable struct this way. But I'm 
curious if I'm missing something regarding references to 
structs.


You can use move maybe? : 
https://dlang.org/library/std/algorithm/mutation/move.html


So

this.f = f.move;

But you should be aware that it could cause problems when f has 
pointers to its internals. I.e. if Foo had a pointer to it's own 
member then the value of of that pointer to me "copied" over to 
this.f, but the address of the member in this.f is different that 
the original f's member address.






Re: Pattern matching via switch?

2020-03-14 Thread aliak via Digitalmars-d-learn

On Saturday, 14 March 2020 at 19:04:28 UTC, 12345swordy wrote:

I.E.

switch (object)
case Type1 t1:
case Type2 t2:
case Type3 t3:


You can use the sumtype package 
(https://code.dlang.org/packages/sumtype):


alias T = SumType!(Type1, Type2, Type3);

T(object).match!(
(Type1 t1) => "t1",
(Type2 t2) => "t2",
(Type3 t3) => "t3",
);


Or you can make a quick template like:

template switch_(funs...) {
auto switch_(T)(auto ref T t) {
static foreach (fun; funs) {
static if (is(typeof(fun(T.init {
return fun(t);
}
}
}
}

struct A {}
struct B {}
struct C {}

void main()
{
auto a = C();
a.switch_!(
(A _) => "a",
(B _) => "b",
(C _) => "c",
).writeln;
}

The template above is a quick fix and will have some holes 
though. Off the top of my head if more than one lambda "fits" 
there'll be problems.




Re: dub sourceFiles

2020-04-01 Thread aliak via Digitalmars-d-learn

On Tuesday, 31 March 2020 at 15:23:48 UTC, Anonymouse wrote:
I have a library package that I split up into subpackages, but 
I'm having to do mental gymnastics to make it only compile the 
files I want.


The problem is that even if you specify some `sourceFiles`, it 
will build everything under the sun inside `sourcePaths`, which 
defaults to "source" or "src" depending on availability. 
There's no way to set it to an empty string, or something that 
doesn't exist.


```sdl
name "stuff"
targetType "library"

subPackage {
name "foo"

sourceFiles \
"source/foo.d"
}

subPackage {
name "bar"

sourceFiles \
"source/bar.d" \
"source/common.d"
}
```


$ dub build -v :foo
[...]
/usr/bin/dmd -Isource source/foo.d source/bar.d source/common.d


Since I didn't specify any `sourcePaths`, it here defaults to 
"source" and my subpackage only asking for "foo.d" was handed 
all of the files anyway.


What is the preferred solution here?

1. Use `excludedSourceFiles` and exclude files not to be 
compiled. Mental gymnastics needed when you have 12 files (the 
actual case).
2a. Keep source tree in something that isn't named "source" or 
"src", but keep an empty one around for dub to auto-include 
nothing from. I kind of want to avoid this.
2b. Keep real source files in "source", but declare 
`sourcePaths` to point to a dummy empty "ignoreme" directory.  
Crude but technically works.

3. Something else? Surely I'm not the first to run into this.

I could set up the subpackages to each have its own directory 
(2a), but I'd end up with twelve, not including the empty 
"source" acting as bait for dub.


Maybe this will help you: 
https://github.com/aliak00/dub-subpackages


I think it falls under the something else category. The "lib" 
folder does have a source directory but I'm pretty sure you can 
remove that and it will still work and compile only the sub 
projects you want it to.


But, dub is sometimes a mystery in how it works so shout if the 
above doesn't work!


Re: Integration tests

2020-04-20 Thread aliak via Digitalmars-d-learn

On Friday, 17 April 2020 at 16:56:57 UTC, Russel Winder wrote:

Hi,

Thinking of trying to do the next project in D rather than 
Rust, but…


Rust has built in unit testing on a module basis. D has this so 
no problem.


Rust allows for integration tests in the tests directory of a 
project. These are automatically build and run along with all 
unit tests as part of "cargo test".


Does D have any integrated support for integration tests in the 
way

Rust does?


D does not recognise any special testing directories afaik. But 
you'll get the same affect as in rust if you have your 
integration tests in a file that is not the modules you are 
testing and run it after building the main library - or during 
even.


With Dub it's quite easy to set up, you can see the optional 
package as an example [0]. There's a tests directory that does 
not have access to the optional package's internals. There's also 
a unittest-compat configuration in dub.json that tests the 
package alongside vibed (another d package)


For auto mocking, the only thing I've see that provides some 
functionality is the unit-threaded package. But I've never tried 
it.


[0]: https://github.com/aliak00/optional


Re: Option and Result [was Integration tests]

2020-04-21 Thread aliak via Digitalmars-d-learn

On Tuesday, 21 April 2020 at 16:30:15 UTC, Russel Winder wrote:
On Mon, 2020-04-20 at 20:19 +, aliak via 
Digitalmars-d-learn wrote:


[…]



[0]: https://github.com/aliak00/optional


Rust has Option and Result, and most languages are rapidly 
introducing at least Option if not Result – and yes it is 
almost certain all this comes from Haskell.


Yeah it's a great abstraction that's part of modern languages 
now. Some static languages are even building syntax for it right 
in (e.g. swift, kotlin, v, zig - to name a few).


There've been a few attempts at building a Result type:

https://code.dlang.org/search?q=expect
And here: 
https://github.com/aliak00/ddash/blob/master/utils/source/ddash/utils/expect.d




Is Option intended for adding to Phobos?


Not that I am aware of. There was an attempt to PR an Option type 
way back when which never made it: 
https://github.com/dlang/phobos/pull/3915


There was a post here: 
https://forum.dlang.org/thread/hqtdekjtdgbhhbjgy...@forum.dlang.org





Re: Integration tests

2020-04-22 Thread aliak via Digitalmars-d-learn

On Wednesday, 22 April 2020 at 10:32:48 UTC, Russel Winder wrote:


Now I discover Python, Rust, and Go have far nicer abstractions 
for writing Internet code than D does. Does D really not have a 
TcpListener abstraction?


It really doesn't :(

And D has so much potential as server tech with the potential 
combination of fibers + TLS + shared + static introspection.


The package Vibe-d is quite nice though. I don't know if you've 
tried it but it's very simple to get a listener up with it.




To date all I can get is:

std.socket.SocketOSException@std/socket.d(2792): Unable to bind 
socket: Bad file descriptor


when trying to open a TCP server on 127.0.0.1:5, with 
Python, Rust, or Go it all worked first time. This is really 
sad given D has so many advantages over Rust. :-(





Can't get dub dustmite to work

2020-04-25 Thread aliak via Digitalmars-d-learn
Trying to get dub dustmite to work, but I keep getting "initial 
test fails"


This is the error from a vanilla dub test:

```
result ~wip: building configuration "result-test-unittest"...
inout(SumType!(int, FailureContainer))
../../.dub/packages/sumtype-0.9.4/sumtype/src/sumtype.d(1322,4): 
Error: static assert:  "handler #1 of type Optional!(Exception) 
function(FailureContainer container) pure nothrow @nogc @safe 
never matches"
../../.dub/packages/sumtype-0.9.4/sumtype/src/sumtype.d(1165,14): 
   instantiated from here: matchImpl!(inout(SumType!(int, 
FailureContainer)))
source/result/result.d(136,20):instantiated from here: 
match!(inout(SumType!(int, FailureContainer)))
tests/result.d(20,20):instantiated from here: 
Result!(int, Exception)

dmd failed with exit code 1.
```

Then I run this dub dustmite command:

dub dustmite -b unittest ../dubdust --compiler-regex="never 
matches"


And I get:

```
...
Loading /Users/aliak/dev/dubdust/vibe-d/web/vibe/web/web.d
None => No
Hint: use --no-redirect to see test script output
Hint: read 
https://github.com/CyberShadow/DustMite/wiki#initial-test-fails
object.Exception@DustMite/dustmite.d(295): Initial test fails: 
Test script "/usr/local/Cellar/dub/1.20.0/bin/dub dustmite 
--vquiet --test-package=result --build=unittest --config=library 
\"--compiler=dmd\" \"--compiler-regex=never matches\"" exited 
with exit code 3 (failure)

```

* --no-redirect doesn't work in dub dustmite.
* I tried adding --compiler-status=1 with the same result
* I tired --combined with the same result

My dub.json for the unittest configuration is (incase that 
matters):

{
"name": "unittest",
"importPaths": [
"./tests"
],
"sourcePaths": [
"./tests"
]
},

Thanks for any help!



Re: Can't get dub dustmite to work

2020-04-26 Thread aliak via Digitalmars-d-learn

On Saturday, 25 April 2020 at 19:00:55 UTC, Anonymouse wrote:

On Saturday, 25 April 2020 at 09:38:59 UTC, aliak wrote:

Then I run this dub dustmite command:

dub dustmite -b unittest ../dubdust --compiler-regex="never 
matches"


I have had zero luck with dustmite via dub. I would honestly 
recommend that you create a shell script that does `dub test 
2>&1 | grep "never matches"`, and just use that as a tester 
with dustmite directly.


Ok I got it working with that but it resulted in the wrong output 
(it was a bad test case basically" But expanding the shell script 
to


dub test 2>&1 | grep 'Error: static assert:  \"handler #0 of type 
`Optional!(Exception) function(FailureContainer container) pure 
nothrow @nogc @safe` never matches\"'


now results in

...
Loading ./source/result/failure.d
Loading ./source/result/package.d
Loading ./source/result/result.d
Loading ./tests/result.d
None => No
Hint: use --no-redirect to see test script output
Hint: read 
https://github.com/CyberShadow/DustMite/wiki#initial-test-fails
object.Exception@DustMite/dustmite.d(295): Initial test fails: 
Test script "dub test 2>&1 | grep 'Error: static assert:  
\"handler #0 of type  never matches\"'" exited with exit code 1 
(failure)


??:? _Dmain [0x10c56cf5e]


This is the full dustmite command:

dustmite --force . "dub test 2>&1 | grep 'Error: static assert:  
\"handler #0 of type `Optional!(Exception) 
function(FailureContainer container) pure nothrow @nogc @safe` 
never matches\"'"


Re: Can't get dub dustmite to work

2020-04-26 Thread aliak via Digitalmars-d-learn

On Saturday, 25 April 2020 at 18:52:45 UTC, Andre Pany wrote:


How do you call dub test causing the issue? Maybe there is a 
difference in the configuration/build type.


I'm sorry I didn't follow.

You mean like:

"dub test"

??

I dont pass anything to the -b or -c flag if that's what you mean?



Also a side remark. You cannot use the output of dmd when 
colouring is on. Dmd lies because the backticks used for 
colouring are not shown. But without them, regex search is 
failing.


Yeah, that's a good tip. This output is because of a static 
assert in the sumtype library.




I also wonder whether dub Dustmite should be enhanced to search 
for a plain text too. Because while using regex search there 
might be characters which have a regex meaning while user just 
want a simple text search. This could also cause issues.


Kind regards
Andre





Re: Can't get dub dustmite to work

2020-04-27 Thread Aliak via Digitalmars-d-learn

On Monday, 27 April 2020 at 06:23:08 UTC, Andre Pany wrote:

On Sunday, 26 April 2020 at 22:07:56 UTC, aliak wrote:

On Saturday, 25 April 2020 at 18:52:45 UTC, Andre Pany wrote:

[...]


I'm sorry I didn't follow.

You mean like:

"dub test"

??

I dont pass anything to the -b or -c flag if that's what you 
mean?



[...]


Yeah, that's a good tip. This output is because of a static 
assert in the sumtype library.




Yes, that was my question. `dub test` will use configuration 
`unittest`,
therefore you have to pass the configuration `unittest` to `dub 
dustmite` too.


Kind regards
André


Ah ok. Yes I was passing the unittest confit to dub dustmite.


Re: vibe.d and my first web service

2020-07-18 Thread aliak via Digitalmars-d-learn

On Saturday, 18 July 2020 at 09:10:04 UTC, Mr. Backup wrote:

Hello,

I wanted to create simple web service to start learning more 
about D lang and compare with another languages. I have used 
"dub init -t vibe.d" to create basic example:


[...]


Think it's just Vibe.d:

I had a similar issue: 
https://github.com/vibe-d/vibe.d/issues/2436


And this is still open (default server doesn't clean itself up): 
https://github.com/vibe-d/vibe.d/issues/2245




Re: Is it possible to "overload" based on visibility?

2020-09-23 Thread aliak via Digitalmars-d-learn

On Wednesday, 23 September 2020 at 18:38:53 UTC, 60rntogo wrote:
There are really two questions here, one that I intended to ask 
and one that came out while I was trying to figure out the 
answer. Consider this simple code:


[...]


Yeah, you can make a property setter:

private void x(int newValue) { _x = newValue }

2. Is the behavior that allows me to call the private method 
intended? This is such a blatant violation of encapsulation 
that it feels like a bug either in the language or the 
implementation.


Definitely sounds like a bug! Feels like this has got to be a 
regression because I just tried this:


struct Foo {
private void f() {}
void f(int i) {}
}

And Foo.f() is callable from outside the module: 
https://run.dlang.io/is/FVyw7u






Re: Is it possible to "overload" based on visibility?

2020-09-23 Thread aliak via Digitalmars-d-learn
On Wednesday, 23 September 2020 at 19:27:13 UTC, Steven 
Schveighoffer wrote:



This is a bug in the language.


🤯😆



Re: Renaming Flag!"" in API

2020-10-12 Thread aliak via Digitalmars-d-learn

On Monday, 12 October 2020 at 10:24:44 UTC, FreeSlave wrote:

Let's say I use Flag type named 'myflagname' in API like this:

import std.typecons;

void func(Flag!"myflagname" flag)
{
//...
}

void main()
{
func(Yes.myflagname);
}

Later I realize that 'myflagname' is a bad name and I want to 
change it to something else. But if I do so, I break the 
existing code using this API as Flag with different name will 
be a different type and Yes.myflagname and No.myflagname won't 
fit in. I can't use alias as Yes and No relies on string 
literal.
Can this issue overcome somehow? Looks like a fundamental flaw 
with std.typecons.Flag.


One of the reason's Flag is there is because of what's known as 
the boolean trap [0]. If someone changes the name of a parameter, 
that can potentially mean the semantics have changed. Should Flag 
work then? And if it should, why not straight up bool?


https://wiki.qt.io/API_Design_Principles#The_Boolean_Parameter_Trap


Re: UFCS syntax I never saw before.

2018-05-22 Thread aliak via Digitalmars-d-learn
On Monday, 21 May 2018 at 14:19:35 UTC, Steven Schveighoffer 
wrote:

On 5/21/18 8:15 AM, SrMordred wrote:

Right, so this should´n be working I think.


struct SomeStruct
{
    void foo(int);
}

SomeStruct s;
s.foo = 10;


I thought that only with @property this will work.



That was the plan, but it got derailed.

Whoever wrote that original line of code, they need a stern 
talking-to.


-Steve


While wearing the naughty pointy hat and sitting in a corner :p


Re: UFCS syntax I never saw before.

2018-05-22 Thread aliak via Digitalmars-d-learn

On Monday, 21 May 2018 at 18:53:19 UTC, Jonathan M Davis wrote:


writeln = "foo";

is legal, and it's dumb, but it hasn't mattered much in 
practice. So, causing a bunch of code breakage in order to 
disallow it is unlikely to go over well. It would also then 
make getters and setters inconsistent in that setters would 
require @property and getters wouldn't. How much that matters 
is debatable, but it does make such a change less palatable.


[...]



Can't assignment to a function be fixed though? Are there any 
cases where fixing that will cause problems for @property free 
functions because they all must take more that one parameter i 
assume.


It's quite a big wart so we don't have to fix all of @property at 
least, but that should be fixed if fixing it does not crap on 
UFCS and @property free functions.




Re: UFCS syntax I never saw before.

2018-05-24 Thread aliak via Digitalmars-d-learn
On Tuesday, 22 May 2018 at 13:59:16 UTC, Steven Schveighoffer 
wrote:
The derailed plan was to leave alone the ability to call no-arg 
functions without parentheses, but to REQUIRE @property to call 
an argument-taking function with the assignment style.


See the DIP here: https://wiki.dlang.org/DIP23

Written by Walter and Andrei. I can't remember why it didn't 
happen.


-Steve


Aha. Thanks for the link!

It feels like the only difference between a no-arg function that 
is @property and one that is not is that the former could be 
invoked with optional parentheses and the latter should be 
illegal with parentheses.


Whereas an argument taking function marked as @property should 
probably allow read or write operations depending on whether or 
not it's invoked with an implicit first argument or not:


@property int f(int) { ... }
1.f; // read op
f = 1; // write op

And to make parentheses illegal as well of course.




Re: UFCS syntax I never saw before.

2018-05-24 Thread aliak via Digitalmars-d-learn

On Tuesday, 22 May 2018 at 14:33:20 UTC, Jonathan M Davis wrote:
A free function with a single argument works just fine as a 
setter property. e.g. you could do something like


void env(Tuple!(string, string)[] str)
{
// set environment variables
}

env = [tuple("foo", "bar")];

is perfectly legal. I question that there are many cases where 
such a function would be considered good design, but basically 
any case where it would make sense to have a function act like 
a global variable is currently allowed but would be disallowed 
if you couldn't have a setter property with only one argument.


- Jonathan M Davis


That can be attributed with @property if the developer intends 
for it to be used in that way, else should be illegal.





Re: UFCS syntax I never saw before.

2018-05-24 Thread aliak via Digitalmars-d-learn

On Thursday, 24 May 2018 at 22:03:38 UTC, aliak wrote:
It feels like the only difference between a no-arg function 
that is @property and one that is not is that the former could 
be invoked with optional parentheses and the latter should be 
illegal with parentheses.


Edit: err... other way around!





Assigning a method name to a variable and then calling it with an object

2018-05-24 Thread aliak via Digitalmars-d-learn

Hi,

I was essentially trying to do this:

struct S {
  void f() {}
}

auto f = S.f; // f becomes void function(S) ??
S s;
f(s);

Is something like that possible?

Cheers,
- Ali


Re: Assigning a method name to a variable and then calling it with an object

2018-05-24 Thread aliak via Digitalmars-d-learn

On Thursday, 24 May 2018 at 23:08:29 UTC, Basile B. wrote:

On Thursday, 24 May 2018 at 23:03:21 UTC, aliak wrote:

Hi,

I was essentially trying to do this:

struct S {
  void f() {}
}

auto f = S.f; // f becomes void function(S) ??
S s;
f(s);

Is something like that possible?

Cheers,
- Ali


Sure:

```
import std.stdio;

void main(string[] args)
{

struct S {
  void f() {"yeah possible".writeln;}
}

void delegate() f;
f.funcptr = &S.f;
S s;
f.ptr = &s;
s.f();
}
```

It's just that you have to learn the ABI of D delegates.
There are two members: .funcptr (function) and .ptr (context, 
i.e the "this").


ahh, gracias!





Re: WTF! new in class is static?!?!

2018-06-07 Thread aliak via Digitalmars-d-learn

On Thursday, 7 June 2018 at 21:32:54 UTC, Jonathan M Davis wrote:


struct S
{
int* ptr = new int(42);
}



Is that supposed to compile? -> https://run.dlang.io/is/SjUEOu

Error: cannot use non-constant CTFE pointer in an initializer 
&[42][0]


Re: How to list all the manifest constants in a class or struct

2018-06-17 Thread aliak via Digitalmars-d-learn

On Sunday, 17 June 2018 at 02:44:38 UTC, Heromyth wrote:

Here is a struct named S:

struct S
{
enum X = 10;
enum Y
{
  i = 10
}
enum Z = "str";
struct S {}
class C {}

static int sx = 0;
__gshared int gx = 0;

shared void g();
}

I want list all then the manifest constants in it.

I searched the std.traits and this forums, but get nothing.
Maybe, my real question is how to get the storage class for a 
member in a class or struct.


Thanks.


I think this bolts.isManifestAssignable [1] will get you 
partially there. The place where it'll fail though is a static 
immutable (since they are assignable to manifest constants) but 
you can filter those by seeing if you can take the address, 
something like:


foreach (m; __traits(allMembers, T)) {
  if (isManifestAssignable!(T, m) && !is(typeof(mixin("&T."~m))) {
// it's a manifest constant ... (?)
  }
}

There of course might be edge cases I can't think of/don't know 
about though.


Cheers,
- Ali

http://bolts.dpldocs.info/bolts.traits.isManifestAssignable.html




Re: UCFS does not work for nested functions?

2018-06-18 Thread aliak via Digitalmars-d-learn
On Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer 
wrote:

On 6/18/18 7:16 AM, Bastiaan Veelo wrote:

On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:

Hi,

Just noticed that using UFCS does not work for nested 
functions, and was wondering whether that's intended, and 
what the rationale behind it is:


I just had the same question.

I can imagine that the context pointer of nested functions 
complicates things, but making `bar` `static` does not help. 
Has anything changed in recent years regarding the difficulty 
of implementing UFCS for nested functions? Would it be easier 
to only support static nested functions?


```
void main() {
     static void bar(int x) {}

     int x;
     x.bar(); // Error: no property 'bar' for type 'int'
}
```


It's never been supported, and likely will not be. I think the 
idea is that you can override expected behavior inside by 
accidentally defining some function locally with the same name.


-Steve


Wondering how this is different than with non-nested functions? 
If a global function has the same name as a member function then 
the member function takes precedence. So wouldn't the same thing 
just apply here if it were supported?


Cheers,
- Ali


Re: scope(success) lowered to try-catch ?

2018-06-18 Thread aliak via Digitalmars-d-learn
On Monday, 18 June 2018 at 12:48:46 UTC, Steven Schveighoffer 
wrote:

On 6/17/18 11:58 PM, Neia Neutuladh wrote:

[...]


Yep, it's a good point. But also not the only way to do this. 
If you are returning void, just a goto would work:


[...]


I'm quite a noob when it comes to compiler stuff, and I see how 
this can be optimized when there're no exceptions, but I wonder 
what scope(success) actually means though without exceptions in 
play. It's just scope(exit) then right or?


Cheers,
- Ali



Re: UCFS does not work for nested functions?

2018-06-18 Thread aliak via Digitalmars-d-learn
On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer 
wrote:
What then can happen is that your local calls can get hijacked 
from outside the module, if someone happens to define something 
later that you happened to import. D tries to avoid such 
possibilities.


There's not much precedent for local symbols being overridden 
by module-level symbols.


-Steve


I thought that happens already with non-nested functions:

module a;

struct A {
  void f(); // assume it's added later
}

module b;
import a;

void f(A) { }
void g() {
  auto x = A();
  a.f(); // this would be calling local f until someone added A.f
}

Or I misunderstood what you said?

Cheers,
- Ali

PS: This is something I've worried about before actually [1] when 
I was more of a noob than now, but I've come to accept I guess :) 
... though I could still be misunderstanding things of course :/


https://forum.dlang.org/post/crcbaautgmrglhzvx...@forum.dlang.org



Re: UCFS does not work for nested functions?

2018-06-18 Thread aliak via Digitalmars-d-learn
On Monday, 18 June 2018 at 19:26:47 UTC, Steven Schveighoffer 
wrote:

On 6/18/18 2:58 PM, aliak wrote:

[...]


It's the same in the fact that your call is silently switched 
to a different call. However, in the current syntax, an 
external entity CANNOT override a local function. When you call 
the nested function, it's the nested function, no matter what 
else occurs outside (even in the local module). There is no 
precedent for local functions to be overridden by module-level 
functions.


[...]


Ah I see. So it's basically that locals take priority, but if you 
allow them to UFCS then that's not true anymore because members 
need to take priority.


Ok yep, that makes sense. Thanks !


template sequence parameters treats member functions differently?

2018-06-24 Thread aliak via Digitalmars-d-learn
Hi, I'm having some issues with template sequence parameters, it 
seems they are not typed as delegates inside a template, but are 
outside. I.e.


template T(V...) {
alias T = typeof(&V[0]);
}

struct S { void f() {} }
S s;

pragma(msg, T!(s.f)); // void function()
pragma(msg, typeof(&s.f)); // void delegate()

How come the output is different? Is it supposed to be the same?

What I'm trying to do is write a template that can give me a 
tuple of types for all values of the sequence passed in, so that 
I can index in to the type tuple. Seems to work well except for 
this member function part, working source here:


https://run.dlang.io/is/TBXHlY

Specifically the commented out line is what I would like to be 
able to get working if possible.


Thanks for any help,
- Ali





Re: Wrapping a forward range in another forward range

2018-06-24 Thread aliak via Digitalmars-d-learn

On Sunday, 24 June 2018 at 20:33:32 UTC, Rudy Raab wrote:
So I have an XLSX (MS Excel 2007+ file format) library that I 
wrote  (https://github.com/TransientResponse/dlang-xlsx) that I 
recently converted from std.xml to dxml. That went well and it 
still works (much faster too).


[...]


I think it's the isSomeChar!(ElementType!R), not the 
isRandomAccessRange (because string isSomeString and !isSomeChar)?


Cheers,
- Ali



Re: overload .

2018-06-25 Thread aliak via Digitalmars-d-learn

On Monday, 25 June 2018 at 13:37:01 UTC, Mr.Bingo wrote:


One can overload assignment and dispatch so that something like

A.x = ... is valid when x is not a typical member but gets 
resolved by the above functions.


Therefore, I can create a member for assignment. How can I 
create a member for getting the value?


A.x = 3; // Seems to get translated in to A.opDispatch!("x")(3)

works but

foo(A.x); // fails and the compiler says x does not exist


I need something consistent with opDot. I am trying to create 
"virtual"(not as in function) fields and I can only get 
assignment but not accessor.


A.x is translated in to A.opDispatch!"x" with no args. So I guess 
you can overload or you can static if on a template parameter 
sequence:


import std.stdio;
struct S {
auto opDispatch(string name, Args...)(Args args) {
static if (!Args.length) {
return 3;
} else {
// set something
}
}
}
void main()
{
S s;
s.x = 3;
writeln(s.x);
}

Cheers,
- Ali


Re: overload .

2018-06-25 Thread aliak via Digitalmars-d-learn

On Monday, 25 June 2018 at 15:39:09 UTC, Mr.Bingo wrote:

On Monday, 25 June 2018 at 13:58:54 UTC, aliak wrote:
A.x is translated in to A.opDispatch!"x" with no args. So I 
guess you can overload or you can static if on a template 
parameter sequence:


import std.stdio;
struct S {
auto opDispatch(string name, Args...)(Args args) {
static if (!Args.length) {
return 3;
} else {
// set something
}
}
}
void main()
{
S s;
s.x = 3;
writeln(s.x);
}

Cheers,
- Ali


Ok, for some reason using two different templated failed but 
combining them in to one passes:


auto opDispatch(string name, T)(T a)
auto opDispatch(string name)()

Maybe it is a bug in the compiler that it only checks one 
opDispatch?


Two opDispatchs as in:

import std.stdio: writeln;
struct S {
void opDispatch(string name, T)(T t) {
writeln(t);
}

auto opDispatch(string name)() {
writeln("ret");
return 4;
}
}

void main() {
S s;
s.x;
s.x = 4;
}

??

The above seems to work fine. Or maybe you meant something else?



Re: template sequence parameters treats member functions differently?

2018-06-25 Thread aliak via Digitalmars-d-learn
On Monday, 25 June 2018 at 15:06:42 UTC, Steven Schveighoffer 
wrote:

On 6/24/18 5:19 PM, aliak wrote:

[...]


No, because the alias is an alias to the function, not the 
delegate.


The act of taking the address creates the delegate, where the 
delegate's ptr is the context pointer (i.e. s), and the funcptr 
is the function that accepts the pointer (i.e. S.f).


When you pass in s.f to an alias, you are actually passing in 
S.f. It's the fact that you are looking in the *namespace* of s 
when you do the alias. The &s.f is special for the compiler, 
and can't be deferred to later.


Ahh, I see. Ah well. So not really much i can do here with this 
then I guess. Thanks for explaining though!




BUT, I'm thinking this may be fixable, as it's inconsistent 
with inner functions:


auto foo(alias x)() { return x(); }

struct S
{
   int bar() { return 42; }

   // int baz() { return foo!bar; } // nope
}

void main()
{
   S s;

   int bar() { return 42; }

   assert(foo!bar() == 42); // ok
   // assert(foo!(s.bar) == 42); // nope

   int baz() { return s.bar; }
   assert(foo!baz() == 42); // ok!
}

I don't see any reason why the alias is to the function and not 
the contexted function. I don't see how it's any different from 
the ones which use inner functions.


-Steve


I can only agree - me no see either. And having no clue as to how 
the compiler is implemented, I cannot even conjecture :)




Re: template sequence parameters treats member functions differently?

2018-06-25 Thread aliak via Digitalmars-d-learn
On Monday, 25 June 2018 at 18:59:37 UTC, Steven Schveighoffer 
wrote:

On 6/25/18 2:51 PM, aliak wrote:
On Monday, 25 June 2018 at 15:06:42 UTC, Steven Schveighoffer 
wrote:


I don't see any reason why the alias is to the function and 
not the contexted function. I don't see how it's any 
different from the ones which use inner functions.


I can only agree - me no see either. And having no clue as to 
how the compiler is implemented, I cannot even conjecture :)




Well, it's worth an enhancement request in any case.

-Steve


doneo: https://issues.dlang.org/show_bug.cgi?id=19026


anyway to pass the context of an inner type to a template so it can be constructed?

2018-06-27 Thread aliak via Digitalmars-d-learn

This currently fails unless you mark the class as static:

auto construct(T)() {
return new T;
}
void main() {
class C {}
auto s = construct!C;
}

So wondering if there's anything that can be done to get the 
above working?



Or if there isn't then how could the compiler be enhanced to 
allow for something like this if possible?


===
The use case is for a non-nullable type, where I want to 
guarantee that the value inside will never be null. I can't do it 
for inner classes though. And I can't allow the user to do 
something like:


void main() {
class C {}
auto s = construct(new C);
}

Because I can't guarantee that's not null.


Cheers,
- Ali


Re: anyway to pass the context of an inner type to a template so it can be constructed?

2018-06-27 Thread aliak via Digitalmars-d-learn

On Wednesday, 27 June 2018 at 14:01:03 UTC, Alex wrote:

On Wednesday, 27 June 2018 at 12:02:10 UTC, aliak wrote:

===
The use case is for a non-nullable type, where I want to 
guarantee that the value inside will never be null. I can't do 
it for inner classes though. And I can't allow the user to do 
something like:


void main() {
class C {}
auto s = construct(new C);
}

Because I can't guarantee that's not null.


Cheers,
- Ali


Is there any reason, why you don't want to use a struct? An 
instance of such is never null, still having access to its 
context, if it is a function.


Sorry, by non-nullable I meant not null. It's that construct 
produces a wrapper type that has an internal value that I want to 
guarantee is not null. So whether T is a struct or class is 
dependent on the user of construct.


- Ali


Re: anyway to pass the context of an inner type to a template so it can be constructed?

2018-06-27 Thread aliak via Digitalmars-d-learn

On Wednesday, 27 June 2018 at 19:28:37 UTC, Timoses wrote:

Can't seem to avoid using mixin in main..


hehe yeah I see, didn't think of trying mixins, worth a shot! It 
seems like you had fun at least ;)





Re: Nullable!T with T of class type

2018-06-28 Thread aliak via Digitalmars-d-learn

On Thursday, 28 June 2018 at 18:10:07 UTC, kdevel wrote:
On Tuesday, 26 June 2018 at 21:54:49 UTC, Jonathan M Davis 
wrote:
[H]onestly, I don't understand why folks keep trying to put 
nullable types in Nullable in non-generic code.


How do you signify that a struct member of class type is 
optional?


So there're no optional type in D (ala Swift, Kotlin, Scala, 
etc).  There are a number of workarounds you can use to achieve 
the same type of behavior.


You can use ranges to denote "some" value or no value (empty 
range). But it's a bit inconvenient and the APIs to get that 
running say nothing about intent.


You can create a lightweight Maybe type: 
https://stackoverflow.com/questions/27241908/maybe-types-in-d


I've implemented an optional type as well that includes safe 
dispatching, but it's not @nogc right now -> 
https://github.com/aliak00/optional


I think there's another optional type on dub somewhere as well.

But using Nullable!T just defers the problem that optional solves:

if (nullable.isNull) {
  nullable.get.doSomething();
}

vs:

if (ptr !is null) {
  ptr.doSomething();
}

meh...

It's more of a tool to allow you to give any type nullability 
semantics.


Cheers,
- Ali


what's the correct way to handle unicode? - trying to print out graphemes here.

2018-07-03 Thread aliak via Digitalmars-d-learn
Hi, trying to figure out how to loop through a string of 
characters and then spit them back out.


Eg:

foreach (c; "👩‍👩‍👦‍👦🏳️‍🌈") {
  writeln(c);
}

So basically the above just doesn't work. Prints gibberish.

So I figured, std.uni.byGrapheme would help, since that's what 
they are, but I can't get it to print them back out? Is there a 
way?


foreach (c; "👩‍👩‍👦‍👦🏳️‍🌈".byGrapheme) {
  writeln(c.);
}

And then if I type the loop variable as dchar,  then it seems  
that the family empji is printed out as 4 faces - so the code 
points I guess - and the rainbow flag is other stuff (also its 
code points I assume)


Is there a type that I can use to store graphemes and then output 
them as a grapheme as well? Or do I have to use like lib ICU 
maybe or something similar?


Cheers,
- Ali


Re: what's the correct way to handle unicode? - trying to print out graphemes here.

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

On Tuesday, 3 July 2018 at 13:32:52 UTC, aliak wrote:
Hi, trying to figure out how to loop through a string of 
characters and then spit them back out.


Eg:

foreach (c; "👩‍👩‍👦‍👦🏳️‍🌈") {
  writeln(c);
}

So basically the above just doesn't work. Prints gibberish.

So I figured, std.uni.byGrapheme would help, since that's what 
they are, but I can't get it to print them back out? Is there a 
way?


foreach (c; "👩‍👩‍👦‍👦🏳️‍🌈".byGrapheme) {
  writeln(c.);
}

And then if I type the loop variable as dchar,  then it seems  
that the family empji is printed out as 4 faces - so the code 
points I guess - and the rainbow flag is other stuff (also its 
code points I assume)


Is there a type that I can use to store graphemes and then 
output them as a grapheme as well? Or do I have to use like lib 
ICU maybe or something similar?


Cheers,
- Ali


Hehe I guess the forum really is using D :p

The two graphemes I'm talking about (which seem to not be 
rendered correctly above) are:


family emoji: https://emojipedia.org/family-woman-woman-boy-boy/
rainbow flag: https://emojipedia.org/rainbow-flag/



Re: what's the correct way to handle unicode? - trying to print out graphemes here.

2018-07-04 Thread aliak via Digitalmars-d-learn
On Tuesday, 3 July 2018 at 14:43:37 UTC, Steven Schveighoffer 
wrote:

On 7/3/18 10:37 AM, ag0aep6g wrote:

On Tuesday, 3 July 2018 at 13:32:52 UTC, aliak wrote:

foreach (c; "👩‍👩‍👦‍👦🏳️‍🌈") {
  writeln(c);
}

So basically the above just doesn't work. Prints gibberish.


Because you're printing one UTF-8 code unit (`char`) per line.

So I figured, std.uni.byGrapheme would help, since that's 
what they are, but I can't get it to print them back out? Is 
there a way?


foreach (c; "👩‍👩‍👦‍👦🏳️‍🌈".byGrapheme) {
  writeln(c.);
}


You're looking for `c[]`. But that won't work, because std.uni 
apparently doesn't recognize those as grapheme clusters. The 
emojis may be too new. std.uni is based on Unicode version 
6.2, which is a couple years old.


Oops! I didn't realize this, ignore my message about reporting 
a bug.


I still think it's very odd for printing a grapheme to print 
the data structure.


-Steve



Aha, ok I see. Many gracias!

Though, seems by a couple years old you mean 6 years! :) Is 
updating unicode stuff to the latest a matter of some config file 
somewhere with the code point configurations that result in 
specific graphemes? Feels kinda ... quite bad that we're 6 years 
behind the current standard.


Also, any reason (technical or otherwise) that we have to slice a 
grapheme to get it printed? Or just no one implemented something 
like toString or the like? It's quite non intuitive as it is 
right now IMO. I can't really imagine anyone figuring out that 
they have to slice a grapheme to get it to print 🤔


Cheers,
- Ali


Re: what's the correct way to handle unicode? - trying to print out graphemes here.

2018-07-04 Thread aliak via Digitalmars-d-learn

On Tuesday, 3 July 2018 at 14:37:32 UTC, Adam D. Ruppe wrote:

On Tuesday, 3 July 2018 at 13:32:52 UTC, aliak wrote:

[...]


What system are you on? Successfully printing this stuff 
depends on a lot of display details too, like writeln goes to a 
terminal/console and they are rarely configured to support such 
characters by default.


You might actually be better off printing it to a file instead 
of to a display, then opening that file in your browser or 
something, just to confirm the code printed is correctly 
displayed by the other program.



  [...]


prolly just printing `c` itself would work and if not try `c[]`

but then again it might see it as multiple graphemes, idk if it 
is even implemented.


Just 'c' didn't but 'c[]' seems like the thing to do! Thankies!

Terminal on osx, and yeah you're right. Seems like just trying to 
paste rainbow flag right in to terminal results in the 3 separate 
code points




How to get an inout constructor working with a template wrapper

2018-07-22 Thread aliak via Digitalmars-d-learn

Hi,

In the code below:

struct W(T) {
T val;
this(T val) inout {
this.val = val;
}
}

class C {}

void main() {
   W!C a = new C;
   immutable W!C b = new C;
}

W!C a = new C results in: "Error: cannot implicitly convert 
expression val of type C to inout(C)."


If I remove the inout on the constructor then the error is on the 
other line and is: "Error: mutable method W!(C).W.this is not 
callable using a immutable object"


If the class is changed to a struct through,  then the 
constructor with inout works on both lines in main above.


So I guess this has something to do with reference types (As the 
same behaviour is exhibited if T == int*) What's the recommended 
way to handle this?


Cheers,
- Ali


Re: How to get an inout constructor working with a template wrapper

2018-07-23 Thread aliak via Digitalmars-d-learn

On Sunday, 22 July 2018 at 23:11:09 UTC, Ali Çehreli wrote:
Without much confidence on my side, first, I think you need to 
make the constructor parameter inout(T) as well. Otherwise, you 
may be making a const(W!T) initialized with a non-const T.


After that, I like the "type constructor" syntax in main_alt() 
below (which works) but a better approach is to use a 
convenience function like wrap() below:


struct W(T) {
T val;
this(inout(T) val) inout {
this.val = val;
}
}

class C {}

void main_alt() {
auto a = W!C(new C);
auto b = immutable W!(immutable C)(new C);
}

auto wrap(T)(inout T t) {
return inout(W!T)(t);
}

void main() {
auto a = wrap(new C);
auto b = wrap(new immutable(C));
}

Ali
"taklitlerinden sakınınız" :o)


Thank you Ali! That helped :) I've gotten most of it sorted out 
now, and the factory wrap is definitely the way to go, it also 
turned out that inout(T) and inout T (so inout without parens) 
was surprisingly different (maybe it's a bug? - to test you can 
remove the parens around U on line 3 in this sample: 
https://run.dlang.io/is/gd5oxW


Also over there, line 24:

auto si = wrap!(immutable int)(3);

seems to be giving problems. Any ideas there? Error is:

onlineapp.d(8): Error: inout on return means inout must be on a 
parameter as well for pure nothrow @nogc @safe 
inout(W!(immutable(int)))(immutable(int) t)
onlineapp.d(23): Error: template instance 
`onlineapp.wrap!(immutable(int))` error instantiating


To make it compile successfully you can either:

1) Chance immutable to const, then it works for some reason.
2) Change the line to: "auto si = wrap(cast(immutable int)3);" - 
i.e. do not explicitly provide type information.


Cheers,
- Ali



Re: How to get an inout constructor working with a template wrapper

2018-07-23 Thread aliak via Digitalmars-d-learn

On Monday, 23 July 2018 at 12:02:58 UTC, aliak wrote:

https://run.dlang.io/is/gd5oxW


Sorry wrong link!

This one is correct -> https://run.dlang.io/is/azxmGN


How to avoid inout type constructor with Optional type wrapper undoing string type

2018-07-23 Thread aliak via Digitalmars-d-learn

Hi,

I'm playing around with an Optional wrapper type. It stores a 
type T and a bool that defines whether a value is defined or not:


struct Optional(T) {
  T value;
  bool defined = false;
  this(U : T)(auto ref inout(U) value) inout {
this.value = value;
this.defined = true;
  }
}

To facilitate it's use I have two type constructors:

inout(Optional!T) some(T)(auto ref inout(T) value) {
return inout(Optional!T)(value);
}

Optional!T no(T)() {
return Optional!T();
}

The above produces a problem when working with strings. Basically 
the type information gets slightly altered so you can't do this:


auto a = [no!string, some("hello")];

You get a type mismatch:

* no!string = Optional!string
* some("hello") = immutable(Optional!(char[]))

I've created a short code gist, so basically I'm wondering how to 
get it to compile without changing what's in main()


https://run.dlang.io/is/BreNdZ

I guess I can specialize on string type T, but this is a more 
general problem that can be shown with:


struct S {}
alias Thing = immutable S;
Thing thing = S();

auto x = some(thing);
auto y = no!Thing;
auto arr = [x, y]; // no can do buddy

Cheers,
- Ali


Re: How to avoid inout type constructor with Optional type wrapper undoing string type

2018-07-23 Thread aliak via Digitalmars-d-learn

On Monday, 23 July 2018 at 19:02:02 UTC, Jacob Carlborg wrote:


This [1] compiles the first example but not the second.

[1] https://run.dlang.io/is/SJ02kP


Aye it does, but it also sets T to always const which is 
unfortunately impractical for my use case :(




Re: How to avoid inout type constructor with Optional type wrapper undoing string type

2018-07-23 Thread aliak via Digitalmars-d-learn

On Monday, 23 July 2018 at 19:22:13 UTC, aliak wrote:

On Monday, 23 July 2018 at 19:02:02 UTC, Jacob Carlborg wrote:


This [1] compiles the first example but not the second.

[1] https://run.dlang.io/is/SJ02kP


Aye it does, but it also sets T to always const which is 
unfortunately impractical for my use case :(


Ok, now I'm totally confused. Defining an extra type constructor 
makes everything work. I.e add a const one to the inout one:


auto defined(T)(const auto ref T value) {
return W!T(value);
}

and everything works!

Can anyone say why that is?


Re: How to avoid inout type constructor with Optional type wrapper undoing string type

2018-07-23 Thread aliak via Digitalmars-d-learn

On Monday, 23 July 2018 at 19:31:42 UTC, aliak wrote:
Ok, now I'm totally confused. Defining an extra type 
constructor makes everything work. I.e add a const one to the 
inout one:


auto defined(T)(const auto ref T value) {
return W!T(value);
}

and everything works!

Can anyone say why that is?


Boh, seems other problems crop up now as doing this:

auto a = defined!(int*)(null);

produces error:

onlineapp.d(13): Error: inout constructor 
onlineapp.W!(int*).W.__ctor!(int*).this creates const object, not 
mutable
onlineapp.d(30): Error: template instance 
`onlineapp.defined!(int*)` error instantiating


https://run.dlang.io/is/BWYxA8


Re: Initialise non-copyable, non-default-constrauctable member struct

2018-07-27 Thread aliak via Digitalmars-d-learn

On Friday, 27 July 2018 at 12:11:37 UTC, Peter Particle wrote:

Question is related to this:
https://dlang.org/spec/struct.html#disable_default_construction

struct S {
int x;
@disable this(); // Disables default construction
@disable this(this); // Disable copying

this(int v) { x = v; }
}

struct T {
float y;
S s;
@disable this(); // Disables default construction
@disable this(this); // Disable copying

this(float v) {
y = v;

s = S(cast(int)v);// tried option 1
s.__ctor(cast(int)v); // tried option 2

}
}

Error: struct `S` is not copyable because it is annotated with 
`@disable`

in both cases.

Is there some way around this problem?


This works on the latest dmd:

struct S {
int x;
@disable this(); // Disables default construction
@disable this(this); // Disable copying

this(int v) { x = v; }
}

struct T {
float y;
S s;
@disable this(); // Disables default construction
@disable this(this); // Disable copying

this(float v) {
y = v;
s = S(cast(int)v);
}
}

void main() {
auto s = T(3);
}

https://run.dlang.io/is/lLrUiq


Re: Initialise non-copyable, non-default-constrauctable member struct

2018-07-27 Thread aliak via Digitalmars-d-learn

On Friday, 27 July 2018 at 13:05:07 UTC, aliak wrote:

https://run.dlang.io/is/lLrUiq


Sorry: https://run.dlang.io/is/20FUoj



How come isMutable returns true for structs that cannot be modified

2018-07-27 Thread aliak via Digitalmars-d-learn

import std.traits: isMutable;
struct S {
immutable int i = 3;
}

pragma(msg, isMutable!S);

void main() {
S s;
s = S();
}

And is there a trait that takes the transitivity of immutability 
in to account?


Cheers,
- Ali


Re: How to get an inout constructor working with a template wrapper

2018-07-27 Thread aliak via Digitalmars-d-learn

On Monday, 23 July 2018 at 14:46:32 UTC, Timoses wrote:

On Monday, 23 July 2018 at 12:02:58 UTC, aliak wrote:

[...]


Both of these seem to work (as you pointed out)

// immutable(W!int)
auto si = wrap!(int)(cast(immutable)3); // or 
wrap(cast(immutable)3);

// W!(immutable(int))
auto si2 = W!(immutable int)(3);


[...]


I don't know why

wrap!(immutable int)(3);

is not working. The error message

"Error: inout on return means inout must be on a parameter 
as well for pure nothrow @nogc @safe 
inout(W!(immutable(int)))(return immutable(int) t)"


sounds very odd and not at all helpful, at least regarding that 
removing immutable from the template argument works.



[...]


The depths of D. Why does the following only work with "return 
ref"?


struct W(T) {
T val;
this(U : T)(auto ref inout U val) inout {
pragma(msg, typeof(val));
this.val = val;
}
}

// Fails without "return ref" (escaping t warning...)
auto wrap(T)(return ref inout T t) {
return inout W!T(t);
}

class C {}

void main() {
immutable C ci = new immutable C;
auto i = wrap(im);
pragma(msg, typeof(i));
}


Ok, thanks to Simen from another post [0], I just figured out 
what the correct constructor and factory method for a template 
wrapper should be:


https://run.dlang.io/is/S4vHzL

struct W(T) {
T val;
this(U : T, this This)(auto ref U val) {
this.val = val;
}
}

auto wrap(T)(auto ref T t) {
return W!T(t);
}

Seems to catch all cases!

[0]: 
https://forum.dlang.org/thread/hxbeektmpnmfdbvjr...@forum.dlang.org


Re: How come isMutable returns true for structs that cannot be modified

2018-07-27 Thread aliak via Digitalmars-d-learn
On Friday, 27 July 2018 at 14:48:06 UTC, Steven Schveighoffer 
wrote:

On 7/27/18 9:10 AM, aliak wrote:

import std.traits: isMutable;
struct S {
     immutable int i = 3;
}

pragma(msg, isMutable!S);

void main() {
     S s;
     s = S();
}


isMutable only takes the type into account, it doesn't look to 
see if all the internals are mutable.


It literally is this:

enum bool isMutable(T) = !is(T == const) && !is(T == immutable) 
&& !is(T == inout);


And is there a trait that takes the transitivity of 
immutability in to account?


I think you are looking for 
https://dlang.org/phobos/std_traits.html#isAssignable


-Steve


Ah! Yes I think I am. Thanks!




Re: How to get an inout constructor working with a template wrapper

2018-07-28 Thread aliak via Digitalmars-d-learn
On Friday, 27 July 2018 at 14:38:27 UTC, Steven Schveighoffer 
wrote:

On 7/27/18 9:29 AM, aliak wrote:
Ok, thanks to Simen from another post [0], I just figured out 
what the correct constructor and factory method for a template 
wrapper should be:


https://run.dlang.io/is/S4vHzL

struct W(T) {
     T val;
     this(U : T, this This)(auto ref U val) {
     this.val = val;
     }
}

auto wrap(T)(auto ref T t) {
     return W!T(t);
}

Seems to catch all cases!


And instantiate a new template for all mutabilities. Whereas 
inout would only instantiate one (and disallows modification of 
val if not const or immutable).


-Steve


If you change the ctor to be inout then you get (from the link 
above):


onlineapp.d(4): Error: cannot implicitly convert expression val 
of type onlineapp.C to inout(C)
onlineapp.d(28): Error: template instance 
`onlineapp.W!(C).W.__ctor!(C)` error instantiating
onlineapp.d(4): Error: cannot implicitly convert expression val 
of type S1 to inout(S1)
onlineapp.d(44): Error: template instance 
`onlineapp.W!(S1).W.__ctor!(S1)` error instantiating
onlineapp.d(4): Error: cannot implicitly convert expression val 
of type onlineapp.C to inout(C)
onlineapp.d(9): Error: template instance 
`onlineapp.W!(C).W.__ctor!(C)` error instantiating

onlineapp.d(52):instantiated from here: wrap!(C)
onlineapp.d(4): Error: cannot implicitly convert expression val 
of type const(C) to inout(const(C))
onlineapp.d(9): Error: template instance 
`onlineapp.W!(const(C)).W.__ctor!(const(C))` error instantiating

onlineapp.d(53):instantiated from here: wrap!(const(C))

Am I applying inout incorrectly?


Re: How to avoid inout type constructor with Optional type wrapper undoing string type

2018-07-28 Thread aliak via Digitalmars-d-learn
On Friday, 27 July 2018 at 14:52:20 UTC, Steven Schveighoffer 
wrote:

On 7/23/18 2:39 PM, aliak wrote:

Hi,

I'm playing around with an Optional wrapper type. It stores a 
type T and a bool that defines whether a value is defined or 
not:


struct Optional(T) {
   T value;
   bool defined = false;
   this(U : T)(auto ref inout(U) value) inout {
     this.value = value;
     this.defined = true;
   }
}


Don't use inout here. The point of inout on the constructor is 
to *transfer* the mutability of the parameter to the struct 
instance. But you want to simply copy the type into the struct 
(an immutable(Optional!T) is quite useless, no?)


Just use U, not inout(U), and don't put inout on the 
constructor.


-Steve


But then it only works for mutable Optional right? Why would an 
immutable(Optional!T) be useless? Data can be "forever" empty or 
a certain value.


Re: How to get an inout constructor working with a template wrapper

2018-07-28 Thread aliak via Digitalmars-d-learn
On Friday, 27 July 2018 at 14:34:54 UTC, Steven Schveighoffer 
wrote:
The problem here is that inout(immutable(int)) is equivalent to 
immutable(int).


That is, all flavors of mutability are equivalent to 
immutable(int):


/*mutable*/(immutable(int)) => immutable(int)
  const(immutable(int)) => immutable(int)
  immutable(immutable(int)) => immutable(int)

So the compiler really looks at your wrap instantiation like 
this;


inout(W!(immutable(int))) wrap(immutable(int) t)


Ah ok, so the compiler remove inout behind me back here? (And 
then tells me it needs to be there? :p)




which triggers the (really bad) message.

I'd ask, why are you even worrying about explicit 
instantiation? Why not just wrap(3)?


Just because I don't see why it should not work really. Why not 
allow wrap!(immutable int)(3)?




or (if you really want to test it) wrap(immutable(int)(3))?



To make it compile successfully you can either:

1) Chance immutable to const, then it works for some reason.


Because immutable(const(int)) => immutable(int), so the 
compiler can't remove the inout behind your back.


2) Change the line to: "auto si = wrap(cast(immutable int)3);" 
- i.e. do not explicitly provide type information.


Yep, do this :)

Note that the point of inout is 2-fold:

1. reduce template instantiations. In fact, wrap!int works for 
const, mutable and immutable int.
2. ENSURE that the data isn't modified, even in the case of 
mutable parameters.


Thanks for the explanations! For some reason it's hard to get it 
all to *just work* right now without the template this. But it's 
probably some minor detail I'm just overlooking...




-Steve





Re: How to avoid inout type constructor with Optional type wrapper undoing string type

2018-07-29 Thread aliak via Digitalmars-d-learn
On Sunday, 29 July 2018 at 12:30:58 UTC, Steven Schveighoffer 
wrote:

On 7/28/18 6:06 PM, aliak wrote:

[...]


What I meant was that string is actually mutable (the data 
isn't mutable, but the string can be re-assigned to another 
one), so Optional!string is more useful than 
immutable(Optional!(char[])). I shouldn't have said that 
immutable(Optional!T) is useless, you are right, and it 
wouldn't make sense for the defined flag to change there anyway.


[...]


Ah right. So it seems inout is removing head qualifiers on by-val 
parameters?


Filed what I think I understood from this:

https://issues.dlang.org/show_bug.cgi?id=19125


Re: How to get an inout constructor working with a template wrapper

2018-07-29 Thread aliak via Digitalmars-d-learn
On Sunday, 29 July 2018 at 12:45:48 UTC, Steven Schveighoffer 
wrote:


Am I applying inout incorrectly?


No, you need to apply it to wrap as well. I can't get 
run.dlang.io to work for posting a link, so here is my modified 
version:




Ah bugger, right!

Ok so there's no way to make explicit instantiation involving 
immutable work in the face of an inout parameter? Seems rather 
inconsistent no?


https://issues.dlang.org/show_bug.cgi?id=19126

Thanks,
- Ali


Disabling opAssign in a type disabled all the opAssigns of an aliased type?

2018-07-30 Thread aliak via Digitalmars-d-learn

Is this a bug?

If not is there a workaround?

I would like for the alias this to function as a normal A type 
unless B specifically disables certain features, but it seems 
weird that disabling one opAssign disables all of them inside the 
aliases type but not in the aliasing type?



struct A {
void opAssign(int) {}
}
struct B {
A a;
alias a this;
@disable void opAssign(float);
}

void main() {
B b;
b = 3;
}

Error: function `onlineapp.B.opAssign` is not callable because it 
is annotated with @disable


Cheers,
- Ali


Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type?

2018-07-30 Thread aliak via Digitalmars-d-learn

On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote:

On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote:

Is this a bug?

If not is there a workaround?

I would like for the alias this to function as a normal A type 
unless B specifically disables certain features, but it seems 
weird that disabling one opAssign disables all of them inside 
the aliases type but not in the aliasing type?



struct A {
void opAssign(int) {}
}
struct B {
A a;
alias a this;
@disable void opAssign(float);
}

void main() {
B b;
b = 3;
}

Error: function `onlineapp.B.opAssign` is not callable because 
it is annotated with @disable


Cheers,
- Ali


What happens if you omit the @disable line?


Compiles ok then.


Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type?

2018-07-30 Thread aliak via Digitalmars-d-learn

On Monday, 30 July 2018 at 20:20:15 UTC, Alex wrote:

On Monday, 30 July 2018 at 19:33:45 UTC, aliak wrote:

On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote:

On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote:

[...]


What happens if you omit the @disable line?


Compiles ok then.


So... is this a valid workaround? ;)


Hehe. Unfortunately not. It's for a proxy type that I need to 
disallow assignment to. But the proxy type uses alias to a T. So 
if T has a custom opAssign then bye bye functionality.


Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type?

2018-07-30 Thread aliak via Digitalmars-d-learn

On Monday, 30 July 2018 at 20:38:33 UTC, aliak wrote:

On Monday, 30 July 2018 at 20:20:15 UTC, Alex wrote:

On Monday, 30 July 2018 at 19:33:45 UTC, aliak wrote:

On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote:

On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote:

[...]


What happens if you omit the @disable line?


Compiles ok then.


So... is this a valid workaround? ;)


Hehe. Unfortunately not. It's for a proxy type that I need to 
disallow assignment to. But the proxy type uses alias to a T. 
So if T has a custom opAssign then bye bye functionality.


The actual code is here if you're curious:

https://github.com/aliak00/optional/pull/16/commits/93d51d790d313be3b108df2bd8b3699adc898bd0

Right now I've only:

@disable this(); // Do not allow user creation of a Dispatcher
@disable this(this) {} // Do not allow blitting either

But I also want to

@disable void opAssign(U)(Dispatcher!U)

So that you can't reassign to the Dispatcher (i.e. proxy type)

But if I do that then the opAssigns in the Optional!T cease 
functioning.




Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type?

2018-07-30 Thread aliak via Digitalmars-d-learn

On Monday, 30 July 2018 at 20:54:28 UTC, Simen Kjærås wrote:

On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote:

Is this a bug?

If not is there a workaround?

I would like for the alias this to function as a normal A type 
unless B specifically disables certain features, but it seems 
weird that disabling one opAssign disables all of them inside 
the aliases type but not in the aliasing type?



struct A {
void opAssign(int) {}
}
struct B {
A a;
alias a this;
@disable void opAssign(float);
}

void main() {
B b;
b = 3;
}

Error: function `onlineapp.B.opAssign` is not callable because 
it is annotated with @disable



The workaround is to not disable opAssign. :p

Since this does work for other member functions that opAssign, 
I'm gonna say it's a bug - please file it in Bugzilla.


A perhaps better workaround than the above is to wrap A's 
opAssigns. Sadly, this can't be done with template mixins, 
since they don't overload with non-mixins. It can be done with 
string mixins, however. It's also possible to encapsulate all 
this in a nice little template:


struct A {
void opAssign(int) {}
void opAssign(float) {}
}
struct B {
A a;
alias a this;
@disable void opAssign(float);
mixin(wrap!(B, "opAssign"));
}

string wrap(T, string methodName)() {
enum targetName = __traits(getAliasThis, T)[0];
return `import std.traits : Parameters, ReturnType;
static foreach (e; __traits(getOverloads, 
typeof(`~targetName~`), "`~methodName~`"))
static if (!is(typeof({static 
assert(__traits(isDisabled, getOverload!(typeof(this), 
"`~methodName~`", Parameters!e)));})))

ReturnType!e `~methodName~`(Parameters!e args) {
return __traits(getMember, `~targetName~`, 
"`~methodName~`")(args);

}`;
}

template getOverload(T, string name, Args...) {
import std.traits : Parameters;
import std.meta : AliasSeq;
template impl(overloads...) {
static if (overloads.length == 0) {
alias impl = AliasSeq!();
} else static if (is(Parameters!(overloads[0]) == 
Args)) {

alias impl = overloads[0];
} else {
alias impl = impl!(overloads[1..$]);
}
}
alias getOverload = impl!(__traits(getOverloads, T, name));
}

unittest {
B b;
b = 3;
static assert(!__traits(compiles, b = 3f));
}

And that's enough magic for me for one night.

--
  Simen


Heheh  Amazing! In today's episode of extreme D (why is that 
not a thing?), we give you a "nice little template" :p


https://issues.dlang.org/show_bug.cgi?id=19130

Would it take much to fix it up to use with templated opAssigns 
as well?


I tried for a bit and got stuck with trying to get parameters and 
now I'm giving up for the time being.


struct A {
void opAssign(int) {}
void opAssign()(float) {}
}
struct B(T) {
A a;
alias a this;
@disable void opAssign(U)(B!U);

import std.traits : Parameters, ReturnType;
static foreach (t; __traits(getOverloads, A, "opAssign", 
true)) {

static if (is(typeof(t.stringof))) {
pragma(msg, t.stringof, " - ", Parameters!t);
} else {
pragma(msg, typeof(t), " - ", Parameters!t);
}
}
}

The Parameters!t of the template overloads all come out as "int" 
but only if there's the non-template opAssign(int) in A. If you 
remove that then you get errors. So something is fishy.


Also I realized that it's just 2 opAssigns in the aliased 
Optional!T type for my specific use case so maybe, err... copy 
pasta them in.


Cheers,
- Ali




Re: How to get an inout constructor working with a template wrapper

2018-07-31 Thread aliak via Digitalmars-d-learn
On Tuesday, 31 July 2018 at 12:37:34 UTC, Steven Schveighoffer 
wrote:

On 7/29/18 1:46 PM, aliak wrote:
On Sunday, 29 July 2018 at 12:45:48 UTC, Steven Schveighoffer 
wrote:


Am I applying inout incorrectly?


No, you need to apply it to wrap as well. I can't get 
run.dlang.io to work for posting a link, so here is my 
modified version:




Ah bugger, right!

Ok so there's no way to make explicit instantiation involving 
immutable work in the face of an inout parameter? Seems rather 
inconsistent no?


It's not that there's no way, the issue is simply that you are 
explicitly instantiating incorrectly.


wrap!int(immutable(int)(3));

-Steve


Ok bear with me, but I'm really confused why 
"wrap!int(immutable(int)(3))" is "correct".


This all seems very inconsistent:

1. wrap!(int)(3); // ok
2. wrap!(const int)(3); // ok
3. wrap!(immutable int)(3); // nope
4. wrap!(int)(3); // ok
5. wrap!(const int)(const(int)(3)); // ok
6. wrap!(immutable int)(immutable(int)(3)); // ok!

So for 3, compiler sees the instantiation:

 inout(W!(immutable int)) wrap(immutable(int))

If I understood you correctly?

But then what does it see in number 6, which works fine? And why 
is 2 ok if 3 is not? And finally, why can't the compiler leave 
the inout there and then it doesn't need to complain about it?


Cheers,
- Ali


Re: How to get an inout constructor working with a template wrapper

2018-07-31 Thread aliak via Digitalmars-d-learn
On Tuesday, 31 July 2018 at 21:54:54 UTC, Steven Schveighoffer 
wrote:
Because inout is trying to combine all mutability modifiers 
into one. You want to specify the type, not the mutability, in 
the template parameter T.


Ahhh. Ok I see... I think.


This doesn't make sense. Can you post runnable code?


Hehe, ok, so I fell victim to compiler generating an error for 
number 3 and then nothing else :p But yes you're right, if I 
comment out number 3 then 6 errors as well. Sorry my bad!




When I go back to your original failing example, and replace 
the 3 with immutable(int)(3), it still fails.




So for 3, compiler sees the instantiation:

  inout(W!(immutable int)) wrap(immutable(int))

If I understood you correctly?


Yes. You can see for yourself with pragma msg:

pragma(msg, typeof(t)); // immutable(int)



But then what does it see in number 6, which works fine?


I'm skeptical this is the case.

Note that you may only see the instantiation error ONCE.


Yep, you nailed that one.




And why is 2 ok if 3 is not?


because inout(const(T)) cannot have its inout removed.


Because it may be an immutable? Or?

But the complaint is really the issue. Clearly inout is 
specified, so it shouldn't complain that it isn't.


Aye. I guess that's right.



-Steve





Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type?

2018-08-02 Thread aliak via Digitalmars-d-learn

On Tuesday, 31 July 2018 at 07:01:33 UTC, Simen Kjærås wrote:

On Monday, 30 July 2018 at 23:41:09 UTC, aliak wrote:

https://issues.dlang.org/show_bug.cgi?id=19130


Beautiful. :)

Would it take much to fix it up to use with templated 
opAssigns as well?


I spent half an hour doing silly things, then I came up with 
this:


struct A {
void opAssign(int) {}
void opAssign(float) {}
void opAssign(T)(T t) if (is(T == string)) {}
}
struct B {
A a;
alias a this;
@disable void opAssign(float);
mixin(wrap!(B, "opAssign"));
auto opAssign(T...)(T args)
if (__traits(compiles, a.opAssign(args)))
{
// Look ma, no magic!
return a.opAssign(args);
}
}
unittest {
B b;
b = "Foo!";
}

(Remaining code as in my last post)

Yeah, it really is that simple, since specific overloads are 
tried before templates.


--
  Simen


Oh nice! So you don't even need all that mixin magic and can get 
away with:


struct A {
void opAssign(int) {}
@disable void opAssign(float) {}
void opAssign(T)(T t) if (is(T == string)) {}
}

struct B(T) {
A a;
alias a this;
@disable void opAssign(B!T);
mixin(wrap!(B, "opAssign"));
}

string wrap(T, string methodName)() {
enum targetName = __traits(getAliasThis, T)[0];
return `auto `~methodName~`(T...)(T args)
if (__traits(compiles, 
`~targetName~`.`~methodName~`(args))) {

return `~targetName~`.`~methodName~`(args);
}`;
}

void main() {
B!int b;
b = 3;
b = "hello";
static assert(!__traits(compiles, { b = 3f; } ));
static assert(!__traits(compiles, { b = b; } ));
}






Can you tell if an template alias parameter is of a specific template?

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

Hi

Is there a way to tell if an alias is to a template?

I'm writing some algorithms and I need to distinguish between a 
binary predicate that provides "less than" and one that provides 
"equal to" semantics. So I have these two templates:


template eq(alias pred) {
alias eq = pred;
}

template lt(alias pred) {
alias lt = pred;
}

Then in some place:

static if (is(pred == eq)) {
  return eq(a, b);
} else static if (is(pred == lt)) {
  return !lt(a, b) && !lt(b, a); // equality with less than 
predicate

} else {
  // default assumptions about predicate
}

Then I can use it like:

auto a = S!(eq!((a, b) => a == b)) ;
auto a = S!(lt!((a, b) => a < b));

I've tried std.traits.TemplateOf and __traits(isSame and also 
variations of typeof and also traits.isInstanceOf. I wonder if I 
have to parameterize eq and lt over a compile time sequence 
instead?


Any tips to get this working?

Cheers,
- Ali


  1   2   3   >