Re: How to write a counterpart to C++ std::invoke that works with both free functions and methods?

2020-10-04 Thread 60rntogo via Digitalmars-d-learn
On Tuesday, 29 September 2020 at 01:19:48 UTC, Adam D. Ruppe 
wrote:

On Sunday, 27 September 2020 at 05:22:36 UTC, 60rntogo wrote:

How would I check if it is actually a free function?

but this doesn't even compile since I defined add inside my 
main function


ah that's not a free function!!


OK, I see. That makes sense I suppose. Thanks for putting this 
together, but I'm afraid that I managed to break it again and 
this time it is really baffling.


---
module foo;

auto invoke(alias fun, Args...)(Args args)
{
  static if(__traits(isStaticFunction, fun) || __traits(isNested, 
fun))

return fun(args);
  else
return __traits(child, args[0], fun)(args[1 .. $]);
}

unittest
{
  import std : approxEqual;
  assert(invoke!approxEqual(2.0, 2.001));
}
---

This gives me these errors:

---
source/foo.d(6,48): Error: aggregate or function expected instead 
of approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 
0.01, V maxAbsDiff = 1e-05)
source/foo.d(9,41): Error: template std.math.approxEqual cannot 
deduce function from argument types !()(double), candidates are:
/usr/include/dmd/phobos/std/math.d(8479,6):approxEqual(T, 
U, V)(T value, U reference, V maxRelDiff = 0.01, V maxAbsDiff = 
1e-05)
source/foo.d(15,28): Error: template instance 
foo.invoke!(approxEqual, double, double) error instantiating

---

Confusingly, these errors disappear if I include the unit test in 
my main file (i.e., just add it to the code you posted) rather 
than foo.d or if I use a function like add defined in the module 
instead of imported approxEqual. Any ideas?


Re: How to write a counterpart to C++ std::invoke that works with both free functions and methods?

2020-09-26 Thread 60rntogo via Digitalmars-d-learn
On Saturday, 26 September 2020 at 23:23:13 UTC, Adam D. Ruppe 
wrote:

As a result, you `add` works fine


I'm afraid not. __traits(isStaticFunction, add) is false, I think 
it's because it checks if it is a static member function of some 
struct/class. How would I check if it is actually a free 
function? I tried


isAggregateType!(__traits(parent, add))

but this doesn't even compile since I defined add inside my main 
function and __traits(parent, add) evaluates to main, but 
isAggregateType expects a type as an argument.


Re: conflicting alias in package module

2020-09-26 Thread 60rntogo via Digitalmars-d-learn

On Sunday, 27 September 2020 at 03:33:20 UTC, Mike Parker wrote:

package.d is for your external interface.


Fair enough, thanks.


How to write a counterpart to C++ std::invoke that works with both free functions and methods?

2020-09-26 Thread 60rntogo via Digitalmars-d-learn

I tried this:

---
auto invoke(alias fun, Args...)(Args args)
{
  return fun(args);
}
---

which works with free functions:

---
int add(int a, int b)
{
  return a + b;
}

assert(invoke!add(1, 2) == 3);
---

but with a method:

---
struct Foo
{
  bool isValid(int a)
  {
return a > 0;
  }
}

auto foo = Foo();
assert(invoke!isValid(foo, 3));
---

I get the error "undefined identifier isValid". How can I make 
this work?


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

2020-09-26 Thread 60rntogo via Digitalmars-d-learn

On Friday, 25 September 2020 at 18:58:54 UTC, H. S. Teoh wrote:
You probably need to use the long-form of templates, with 
separate function declarations, to accomplish this. E.g.:


...


Alright, but your example still contains shouldReturnByRef which 
presumably I need to implement myself. But that's an optimization 
detail that I'd rather leave up to the compiler, is that possible?


Re: conflicting alias in package module

2020-09-26 Thread 60rntogo via Digitalmars-d-learn
On Saturday, 26 September 2020 at 15:12:47 UTC, Steven 
Schveighoffer wrote:

Instead:

import pack.foo : Foo;

Works.


OK, sure. It's just that the motivation behind doing public 
imports in package.d is that I can write "import pack" instead of 
"import pack.foo". I guess it simply doesn't work within the 
package itself.




Re: conflicting alias in package module

2020-09-26 Thread 60rntogo via Digitalmars-d-learn
On Saturday, 26 September 2020 at 13:45:21 UTC, Steven 
Schveighoffer wrote:
A selective import is equivalent to aliasing (to the public) 
the symbol as if it were defined in that scope.


You have to label it as private if you want it to be private.


Are you saying that I should write this in bar.d?

private import pack : Foo;

This still gives the same error.



conflicting alias in package module

2020-09-26 Thread 60rntogo via Digitalmars-d-learn

I have a package with the following structure:

pack
|- foo.d
|- bar.d
|- package.d

and the modules look like this:

---
module pack.foo;

struct Foo {}
---
module pack.bar;

import pack : Foo;
---
module pack;

public import pack.foo, pack.bar;
---

and this is an error: "struct pack.foo.Foo at 
source/pack/foo.d(3,1) conflicts with alias pack.bar.Foo at 
source/pack/bar.d(3,8)". I seems like the import in package.d 
sees Foo both in pack.foo and pack.bar, but I don't understand 
why this happens since the import in bar.d is private, isn't it?


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

2020-09-25 Thread 60rntogo via Digitalmars-d-learn
On Friday, 25 September 2020 at 15:21:22 UTC, Steven 
Schveighoffer wrote:
If the input is not ref, you should not return by ref, because 
then you would be returning a reference to local stack data 
that is about to be destroyed.


Yes, I understand that. What I'm really after at this point is 
that I would like to write a clever mixin that would handle all 
of these decisions for me. It should generate a function that 
takes arguments and returns the result by value or const 
reference depending on what is more appropriate for the given 
types. I was under the impression that this could be accomplished 
using in or some other qualifiers.


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

2020-09-25 Thread 60rntogo via Digitalmars-d-learn
On Friday, 25 September 2020 at 14:21:59 UTC, Steven 
Schveighoffer wrote:

in does not mean "take by reference", it means "scope const"


I'm not sure that I really understand scope, but I read 
https://dlang.org/spec/function.html#param-storage as saying "in 
means take by value or reference depending on what is better 
optimized". Is that not what we want here?


It depends on if you want to return a copy. If you want to 
return a reference if the source is a reference, use auto ref 
on the return as well. But if you still want to protect the 
internal data, it would have to be const.


Right, again I'm wondering if there is a way of saying "just 
figure out if it's more optimal to return by value or const 
reference".


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

2020-09-25 Thread 60rntogo via Digitalmars-d-learn
On Friday, 25 September 2020 at 13:15:27 UTC, Steven 
Schveighoffer wrote:
I don't know, you can search for and report it here: 
https://issues.dlang.org


I find it quite hard to search for anything here, but I couldn't 
find anything similar so I submitted a bug report.



You can use auto ref to alleviate that:

int x()(auto ref Foo f) // needs to be a template for auto ref 
to work


That's a good point, thanks. Since we are on that topic, how 
would that differ from the following?


int x(in Foo f)

And going further, if instead of int I wanted to return something 
that might also be expensive to copy, what would be the best way 
to declare the function?


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

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

This is a bug in the language.


Is this a known bug? If not, it should be reported.

I came up with an answer to my original question that sort of 
works:


---
module foo;

struct Foo
{
  private int x;
}

int x(Foo f)
{
  return f.x;
}
---

The downside is that if I don't want to import all of foo at 
once, then I have to import both Foo and x, but then I can read x 
from outside the module and modify it form inside as I wanted. 
Are there any drawbacks of this approach that I'm not seeing?


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

2020-09-23 Thread 60rntogo via Digitalmars-d-learn

On Wednesday, 23 September 2020 at 19:26:43 UTC, aliak wrote:

Yeah, you can make a property setter:

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


I'm aware of this, but it does not achieve what I asked for. It 
only allows me to assign to _x, it doesn't give me a reference to 
x, so I cannot use it with say += or any other function that 
takes int by mutable reference.


Is it possible to "overload" based on visibility?

2020-09-23 Thread 60rntogo via Digitalmars-d-learn
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:


---
module foo;

struct Foo
{
  private int _x;

  int x() const
  {
return _x;
  }
}
---

If I have an instance of Foo outside of the module I can read the 
value of _x using the property method x, but I can only modify it 
from inside the module using the name _x. This is exactly the 
kind of encapsulation that I often want, but I'm wondering if 
this could be improved a little.


It would be nice if I didn't have to remember if I need to use _x 
or x depending on the context. Instead I would like to use only 
one name, say x, from both inside and outside of the module and 
have compiler complain if I'm trying to modify it from the 
outside.


My naive attempt was this:

---
import std : writeln;

private int _x;

private ref int x() return
{
  writeln("ref int");
  return _x;
}

int x() const
{
  writeln("int");
  return _x;
}
---

At first I didn't even expect this to compile, but it does and I 
can call these methods. I believe an overload is chosen based on 
the type qualifier of a Foo instance. What is truly unexpected is 
that if I call x on a mutable object even outside of the module, 
then the first overload is called!


So my questions are:

1. Can I achieve my original goal of being able to refer to _x by 
one name, so that I have read only access from outside the module 
and read/write access from inside?
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.


Re: another question on hidden mixin names

2020-09-17 Thread 60rntogo via Digitalmars-d-learn
On Thursday, 17 September 2020 at 22:07:54 UTC, Simen Kjærås 
wrote:

Usually, that would be:

struct V {
int x;

mixin assign!"+" a;
mixin assign!"-" b;
alias opOpAssign = a.opOpAssign;
alias opOpAssign = b.opOpAssign;
}

However, I can't seem to get that working. It seems to be an 
instance of this issue:

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


Yes, I tried that. It didn't work so I assumed that it must have 
been wrong. Is this a bug in the compiler or an issue in the 
language specification?


btw, I'm somewhat surprised by your use of a template this 
parameter 
(https://dlang.org/spec/template.html#template_this_parameter). 
Generally this will work, but you're probably better off with


ref auto opOpAssign(string op)(typeof(this) rhs) if (op == 
op_)


I learned it from here: http://ddili.org/ders/d.en/mixin.html, 
could you elaborate on why this is not advisable?


another question on hidden mixin names

2020-09-17 Thread 60rntogo via Digitalmars-d-learn
I suspect that this is similar to the issue I asked about here: 
https://forum.dlang.org/post/vukxaqprjbyrdpiou...@forum.dlang.org, but I can't figure it out.


This compiles:

---
private mixin template assign(string op_)
{
  ref auto opOpAssign(string op, this RHS)(RHS rhs) if (op == op_)
  {
mixin("x " ~ op ~ "= rhs.x;");
return this;
  }
}

struct V
{
  int x;

  mixin assign!"+";
  // mixin assign!"-";
}

unittest
{
  auto v = V(2);
  v += v;
  assert(v.x == 4);
}
---

However, if I uncomment the second mixin, there is an error "v is 
not a scalar, it is a V". I guess I somehow need to merge these 
overloads, but I don't know how.


Re: importing a symbol without specifying a subpackage name

2020-09-16 Thread 60rntogo via Digitalmars-d-learn
On Wednesday, 16 September 2020 at 13:33:34 UTC, Adam D. Ruppe 
wrote:

They define an additional file

std/package.d


Thanks for a quick answer. I suspected it must have been 
something like that, except that I tried doing this in foo.d and 
then the compiler yelled at me.


importing a symbol without specifying a subpackage name

2020-09-16 Thread 60rntogo via Digitalmars-d-learn
I have noticed that if I want to import 
std.algorithm.searching.find, each of the following will work:


---
import std.algorithm.searching : find;
import std.algorithm : find;
import std : find;
---

(Although, the last one is probably not the greatest idea.) 
However, if I write my own module:


---
module foo.bar;

struct Bar {}
---

then saying "import foo : Bar;" yields an error "module foo is in 
file 'foo.d' which cannot be read". I'm curious, how is this 
behavior achieved in the standard library?


Re: default arguments for const ref parameters in extern C++ functions

2020-09-14 Thread 60rntogo via Digitalmars-d-learn

On Monday, 14 September 2020 at 17:11:59 UTC, k2aj wrote:
AFAIK the only way to have default ref arguments is to use a 
global variable:

---
extern(C++) struct Foo
{
  int x;
}
immutable foo1 = Foo(1);
extern(C++) void fun(const ref Foo foo = foo1);
---


Thanks. This appears to work, but feels like a hack. I can live 
with that, but I'm still wondering if there is a more idiomatic 
way of solving the problem.


Re: default arguments for const ref parameters in extern C++ functions

2020-09-14 Thread 60rntogo via Digitalmars-d-learn

On Monday, 14 September 2020 at 12:44:34 UTC, 60rntogo wrote:

---
struct Foo
{
  int x;
}

extern(C++) void fun(const ref Foo foo = Foo(1));
---


I suppose this should have been:

---
extern(C++):

struct Foo
{
  int x;
}

void fun(const ref Foo foo = Foo(1));
---

Not that it changes the question in any way.


default arguments for const ref parameters in extern C++ functions

2020-09-14 Thread 60rntogo via Digitalmars-d-learn
I'm trying to use a C++ library that has a function declared like 
this:


---
struct Foo
{
  int x;
};

void fun(const Foo& foo = Foo(1));
---

I have translated this to a D declaration:

---
struct Foo
{
  int x;
}

extern(C++) void fun(const ref Foo foo = Foo(1));
---

This yields an error: "Foo(1) is not an lvalue and cannot be 
modified". I suppose this makes sense with how D references work, 
but I have no control over how the C++ function is declared. What 
can I do with this?


Re: Why does a directly defined constructor hide a mixed-in constructor?

2020-09-13 Thread 60rntogo via Digitalmars-d-learn

On Sunday, 13 September 2020 at 13:10:15 UTC, Adam D. Ruppe wrote:
This is pretty useful in a lot of cases but kinda annoying with 
overloading. To overload, you must use `alias` to merge the 
overload sets. For constructors, you need to use the name 
`__ctor` instead of `this` to make it compile:


Yes, that works. Thanks!


Why does a directly defined constructor hide a mixed-in constructor?

2020-09-13 Thread 60rntogo via Digitalmars-d-learn

This code:

---
mixin template X()
{
  int[2] x;

  this(int[2] x...)
  {
this.x = x;
  }
}

struct Foo
{
}

struct Bar
{
  mixin X;

  this(Foo foo)
  {
this.x = [0, 0];
  }
}

void main()
{
  auto bar = Bar(1, 2);
}
---

produces the following error:

---
source/app.d(27,17): Error: constructor app.Bar.this(Foo foo) is 
not callable using argument types (int, int)
source/app.d(27,17):cannot pass argument 1 of type int to 
parameter Foo foo

---

However, if I directly insert the contents of X into Bar instead 
of mixing it in, it compiles just fine. What's going on here?


Re: tupleof seems to break encapsulation

2020-09-04 Thread 60rntogo via Digitalmars-d-learn

On Friday, 4 September 2020 at 17:36:00 UTC, Jacob Carlborg wrote:
It's useful for serialization and, as you can see in your 
example, for debugging as well. `writeln` will print the values 
of the fields in a struct, even for private fields.


I wouldn't dispute that it is useful, but that's besides the 
point. If I declare something private, it's usually because I 
want to preserve certain invariants and I want the compiler to 
provide a guarantee that I don't accidentally violate them. As it 
stands, the compiler cannot guarantee that if I use tupleof.


I don't really have an issue with read-only access to private 
fields (but arguments could be made against it) and then 
serialization would still be possible. However, if my struct is 
supposed to maintain invariants, then any attempt at 
deserialization that naively reads from a tuple without 
establishing these invariants should fail to compile.


tupleof seems to break encapsulation

2020-09-04 Thread 60rntogo via Digitalmars-d-learn

Consider the following code.

foo.d
---
module foo;

struct Foo
{
  private int i;
}
---

main.d
---
void main()
{
  import std.stdio;
  import foo;

  auto x = Foo();
  writeln(x);
  // ++x.i;
  ++x.tupleof[0];
  writeln(x);
}
---

As expected, the commented line does not compile. If I uncomment 
it, I get the error "no property i for type foo.Foo". However, 
the rest of the code compiles just fine and outputs:

---
Foo(0)
Foo(1)
---

This appears to defeat the purpose of declaring i private. What 
am I missing?