range.put() to Empty Array Causes Error?

2018-06-17 Thread Vijay Nayar via Digitalmars-d-learn

This code breaks with the following error:
void main()
{
import std.range;
int[] vals = [];
vals.put(3);
}
/src/phobos/std/range/primitives.d(2328): Attempting to fetch the 
front of an empty array of int


The following code has no error:
void main()
{
import std.range;
int[] vals = [1];
vals.put(3);
}

Why is range.put() not allowed for empty arrays?




Preferred Alias Declaration Style

2018-06-27 Thread Vijay Nayar via Digitalmars-d-learn
Most of the documentation at 
https://dlang.org/spec/declaration.html#alias uses examples of 
the form:  `alias aliasName = other;`, where `aliasName` becomes 
the new name to reference `other`.  Alternatively, one may write 
`alias other aliasName;`.  My understanding is that the syntax 
with `=` is the preferred one stylistically.


However, when it comes to `alias this` declarations, the only 
syntax supported is `alias other this;`, and one cannot write 
`alias this = other;`.


Does this mean that the `alias other aliasName;` syntax is 
preferred, or does it simply mean that this is a low priority 
issue that hasn't been addressed yet?


Implicit Template Parameters Cannot Decipher Aliases?

2018-04-25 Thread Vijay Nayar via Digitalmars-d-learn
I have encountered a problem where whenever I attempt to use a 
templated function with alias that partially limits the type of 
the arguments, the program fails to compile.  But if I avoid 
using an alias, the same function can infer all arguments.


Is this working as intended or have I encountered a bug or 
missing feature?


Example below:

```
/**
 * Demonstrate an unexpected compiler error when using implicit 
template parameters

 * combined with aliases to partially instantiate templates.
 */

struct Vector(ElemT, size_t SizeV) {
private:
  ElemT[SizeV] _data;
public:
  @property
  ElemT[SizeV] data() {
return _data;
  }

  ElemT opIndex(size_t i) {
return _data[i];
  }
}

// A helper alias to partially set a portion of compile-time 
arguments.

template Vector3(ElemT) {
  alias Vector3 = Vector!(ElemT, 3);
}

T addAllWithAlias(T)(Vector3!T v1) {
  T sum = 0;
  foreach (T v; v1.data) {
sum += v;
  }
  return sum;
}

T addAll(T)(Vector!(T, 3) v1) {
  T sum = 0;
  foreach (T v; v1.data) {
sum += v;
  }
  return sum;
}

void main() {
  auto v1 = Vector3!double([1.0, 2.0, 3.0]);
  assert(v1[1] == 2.0);

  addAllWithAlias(v1); // Error!
  // template.d(35): Error: template template.addAllWithAlias 
cannot deduce function from

  // argument types !()(Vector!(double, 3LU)), candidates are:
  //   template.d(24):
template.addAllWithAlias(T)(Vector3!T v1)


  addAll(v1);  // OK.
}
```


Re: Implicit Template Parameters Cannot Decipher Aliases?

2018-04-25 Thread Vijay Nayar via Digitalmars-d-learn

On Wednesday, 25 April 2018 at 07:39:28 UTC, Vijay Nayar wrote:


  addAllWithAlias(v1); // Error!


One more note, this following line works correctly.


 addAllWithAlias!double(v1);  // OK.


Re: Implicit Template Parameters Cannot Decipher Aliases?

2018-04-25 Thread Vijay Nayar via Digitalmars-d-learn

On Wednesday, 25 April 2018 at 10:25:11 UTC, Simen Kjærås wrote:
In the general case, the issue is unsolvable, since the 
relationship between template parameters and alias results may 
be arbitrarily complex. A simple degenerate case is this:


Ok, wow, you weren't kidding. That becomes really complex really 
fast.


In that case, is the general rule of thumb that programmers 
should not use aliases for templated types when specifying 
template function parameters?  No implicit type inference is done 
on the return type or on local variables, so these alias seem 
fine enough there. Or should they just be entirely avoided to 
avoid these kinds of problems?


Re: assigment to null class object member compiled? is this a bug?

2018-10-19 Thread Vijay Nayar via Digitalmars-d-learn

On Friday, 19 October 2018 at 06:53:32 UTC, dangbinghoo wrote:

hi,

why the code bellow compiles?

---
import std.stdio;
class A {
int m;
}

void main() {
A a;
a.m = 1;
}
---

and running this code get:

`segmentation fault (core dumped)  ./test`

I consider this couldn't be compiled according to book Programming Language>.


The latest dmd (2.082) and LDC2 behaves the same.


Technically the code you have is syntactically correct.  You are 
permitted to create a class variable without assigning it to a 
class object.  (Assigning it to a class object would look like "A 
a = new A();")


Which section of The D Programming Language book makes you think 
this would not compile?  I have the book as well, but I'm not 
quite sure what part of the book you're referring to.


Re: Can Scope Be Used for Anonymous Objects?

2018-10-17 Thread Vijay Nayar via Digitalmars-d-learn

On Wednesday, 17 October 2018 at 20:41:24 UTC, Ali Çehreli wrote:

On 10/17/2018 01:24 PM, Vijay Nayar wrote:

I have a snippet of code like this:
     scope chordAngle = new S1ChordAngle(_center, 
other._center);

     return _radius + other._radius >= chordAngle;

The reason the "scope" temporary variable exists is to avoid a 
heap allocation and instead prefer a value be created on the 
stack.  Is there a way to do this inline?


Something like:
     return _radius + other._radius >= scope new 
S1ChordAngle(_center, other._center);


I think it's possible but what you're looking for is 
std.typecons.scoped. 'scope' does not do what you think it does.


import std.typecons : scoped;

class C {
int i;
this(int i) {
this.i = i;
}
int foo() {
return i;
}
}

bool bar() {

auto c = scoped!C(42);
return 42 == c.foo();
}

bool bar_2() {
return 42 == scoped!C(42).foo();
}

void main() {
bar();
bar_2();
}

Ali


This particular use of "scope" I overheard at the last DConf, and 
I believe it has been added to the official documentation here:  
https://dlang.org/spec/expression.html#new_expressions


If a NewExpression is used as an initializer for a function 
local variable with
scope storage class, and the ArgumentList to new is empty, 
then the instance is
allocated on the stack rather than the heap or using the 
class specific allocator.


I didn't know about the std.typecons scoped, it looks really 
useful, especially when you want to only create the object when 
short-circuiting fails, like in the middle of an "||" expression.


One drawback of "scoped", however, is that it doesn't appear to 
warn you if you accidentally let the reference escape out of the 
function, unlike a scope variable.


Re: Can Scope Be Used for Anonymous Objects?

2018-10-17 Thread Vijay Nayar via Digitalmars-d-learn
On Wednesday, 17 October 2018 at 20:51:29 UTC, Stanislav Blinov 
wrote:
On Wednesday, 17 October 2018 at 20:24:56 UTC, Vijay Nayar 
wrote:

I have a snippet of code like this:
scope chordAngle = new S1ChordAngle(_center, 
other._center);

return _radius + other._radius >= chordAngle;

The reason the "scope" temporary variable exists is to avoid a 
heap allocation and instead prefer a value be created on the 
stack.  Is there a way to do this inline?


Why, exactly, is a trivial thing like this even a class?


Porting C++ code which unfortunately makes heavy use of 
inheritance.  I originally had this as a struct until I much 
later stumbled into the other classes that were inheriting from 
it.


Can Scope Be Used for Anonymous Objects?

2018-10-17 Thread Vijay Nayar via Digitalmars-d-learn

I have a snippet of code like this:
scope chordAngle = new S1ChordAngle(_center, other._center);
return _radius + other._radius >= chordAngle;

The reason the "scope" temporary variable exists is to avoid a 
heap allocation and instead prefer a value be created on the 
stack.  Is there a way to do this inline?


Something like:
return _radius + other._radius >= scope new 
S1ChordAngle(_center, other._center);


Re: New With Struct and Getting Class Object Pointers

2018-10-03 Thread Vijay Nayar via Digitalmars-d-learn
On Sunday, 30 September 2018 at 11:11:09 UTC, Nicholas Wilson 
wrote:

On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote:
Is there a way to either have a constant reference to a class 
that can be set to a new value, or is there a way to convert 
the class variable to a class pointer?


Alex has mentioned Rebindable, which is the answer to your 
first question.

To answer your second question, no

class A {}

A a:

`a` is always a (possibly null) reference to a class instance. 
You can have pointers to class references (which is what `` 
gives you) but that has two indirections between the variable 
and the data, which if you want high perf is probably not what 
you are looking for.


Thanks everyone for the insight.  I also finished reading 
Jonathan's article: 
http://jmdavisprog.com/articles/why-const-sucks.html


I've run into just about every single problem described there, 
but had no idea just how deep the problem goes.  So it was a 
depressing read, but I'm glad to have the deeper understanding.  
I'm definitely more open now to see what "__mutable" could offer 
as was discussed at DConf2018, though I'm curious about how it 
would remain compatible with "immutable".


New With Struct and Getting Class Object Pointers

2018-09-30 Thread Vijay Nayar via Digitalmars-d-learn

I have two brief questions.

Code that uses "new" to create struct objects appears to compile 
and run. Is this an actual language feature, to get structs on 
the heap?


void main()
{
struct S {int data = 1;}
S* s1 = new S();
S* s2 = s1;
S s3 = *s1;  // Still copies on assignment.
s3.data = 2;
assert(s1.data != s3.data);
}

Second question. const class variables may not be re-assigned, so 
if you need a variable that may be reassigned, but may never 
modify the underlying object, a const pointer can be useful.  
However, it seems that when gets the address of a class variable, 
you do not get the underlying address of the class object.


How do you get a pointer to the underlying class object?  Example 
of the problem:


void main()
{
import std.stdio;
class A { int data = 3; }
A a = new A();

void f(A a) {
a.data = 4;
writeln(" = ", , ", a.data = ", a.data);
}

f(a);
writeln(" = ", , ", a.data = ", a.data);
}

// Output:
 = 7FFEA6BA3158, a.data = 4  // Addresses are different, from 
different class variables.
 = 7FFEA6BA3180, a.data = 4  // But the same underlying class 
object.


Especially if I'm several levels down the call stack, how do I 
get a pointer to the underlying class object?


Re: New With Struct and Getting Class Object Pointers

2018-09-30 Thread Vijay Nayar via Digitalmars-d-learn
On Sunday, 30 September 2018 at 09:16:42 UTC, Nicholas Wilson 
wrote:

On Sunday, 30 September 2018 at 07:29:00 UTC, Vijay Nayar wrote:


Second question. const class variables may not be re-assigned, 
so if you need a variable that may be reassigned, but may 
never modify the underlying object, a const pointer can be 
useful.  However, it seems that when gets the address of a 
class variable, you do not get the underlying address of the 
class object.


 = 0x7ffd0800acb8, a = 0x7fd6b05b, a.data=4
 = 0x7ffd0800acd0, a = 0x7fd6b05b, a.data=4

 The stack ^   the heap^data on the heap^
The address of the variable a on the stack has different values 
across function calls, its value (the reference to the class 
data) remains the same, as does the data itself.


Is there a way to either have a constant reference to a class 
that can be set to a new value, or is there a way to convert the 
class variable to a class pointer?


For example:

void main()
{
class Thing {}
class ThingSaver {
// A const(Thing) could not be changed in 
setThing().

const(Thing)* t;

void setThing(in Thing thing) {
t = thing;  // ERROR converting to pointer type!
}
const(Thing) getThing() const {
return *t;
}
}

Thing t1 = new Thing();

ThingSaver saver = new ThingSaver();
saver.setThing(t1);
const(Thing) t2 = saver.getThing();
}


Re: New With Struct and Getting Class Object Pointers

2018-09-30 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 30 September 2018 at 10:28:25 UTC, Alex wrote:

On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote:
Is there a way to either have a constant reference to a class 
that can be set to a new value, or is there a way to convert 
the class variable to a class pointer?


I think, what you are facing here, is the different notion of 
const, as used from C++. The reasoning about it is described 
for example here:

http://jmdavisprog.com/articles/why-const-sucks.html
Jonathan is much better therein as I am.

However, there are approaches to solve what you want to do. For 
example, there is a Rebindable around:

https://dlang.org/library/std/typecons/rebindable.html

´´´
import std.stdio;
import std.typecons;

void main()
{
class Thing {int dummy; }
class ThingSaver {
/*
A const(Thing) could not be changed in setThing(),
but a Rebindable can be reassigned, keeping t const.
*/
Rebindable!(const Thing) t;

void setThing(in Thing thing) {
t = thing;  // No pointers in use :)
}
const(Thing) getThing() const {
return t;
}
}

Thing t1 = new Thing();

ThingSaver saver = new ThingSaver();
saver.setThing(t1);
//saver.t.dummy = 5; fails as expected.
const(Thing) t2 = saver.getThing();
}
´´´
I hope, I got your idea right...


That pretty much hits the nail on the head, and you're exactly 
right about where my understanding was coming from (C++).  In 
fact, I'm moving a lot of code from C++ to D and finding 
equivalents for a lot of high-performance index classes, which 
end up using this kind of pattern.


Now I need to take the time to grok this article!



Re: What is the Utility of Parent Class Method Hiding in Inheritance?

2019-01-16 Thread Vijay Nayar via Digitalmars-d-learn
On Wednesday, 16 January 2019 at 17:01:06 UTC, Steven 
Schveighoffer wrote:

On 1/14/19 2:30 PM, Neia Neutuladh wrote:

On Mon, 14 Jan 2019 09:10:39 +, Vijay Nayar wrote:

  a.foo(1);  // issues runtime error (instead of calling
A.foo(int))


Calling the function doesn't issue any sort of error. 
Overriding one
overload without overloading or explicitly aliasing in the 
rest issues a

compile-time error.

If you got a runtime error instead, please create a bug report.

I ran into this the other day, where I had a function of the 
same name
in a child class, and found that all functions in the parent 
of the same

name now became hidden, unless I add an alias statement.


If the functions from the parent class are hidden but your 
code compiles,

please create a bug report.



Well, for sure, the documentation needs to be updated!

It was 2.068 that removed the HiddenFuncError, and made this a 
compile error instead. If your compiler is that or newer, 
definitely file a bug report.


-Steve


It's a compile error, and it says that one should use alias as 
well.  I was just surprised and I hadn't thought of why this 
alias would be needed.  Based on the recommendation I found the 
language documentation, but there was no link to the article 
explaining the rationale.  But I'm glad I read that article, it 
makes a lot more sense now.


Re: Best Way to Pass Template Typed Alias Parameters for Functions?

2018-12-23 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 23 December 2018 at 18:31:24 UTC, Alex wrote:

On Sunday, 23 December 2018 at 18:13:25 UTC, Vijay Nayar wrote:
For example, if you have a const function in your container 
like "T find() const", and this function needs to use that 
comparator, then you're out of luck because the compiler 
doesn't know that the comparator function is const and will 
not modify the objects being compared.


Last time I ran into this problem, my solution was simply to 
give up on const. But now I'm running into it again and trying 
to think through it again before giving up again.


Hm... still not sure... ;)
This would compile and run:

´´´
import std.experimental.all;

size_t myHashFunction(int a) { return cast(size_t) a; }

void main()
{
auto b = new B!(int, myHashFunction);
b.arr = 42.iota.array;
assert(b.find == 1);
}

class B(T, alias HashF)
{
T[] arr;

T find() const
{
foreach(el; arr)
{
if(HashF(el))
{
return el;
}
}
assert(0);
}
}
´´´


You're right, it does compile. I'm a bit surprised. I wonder if 
this is a relatively recent improvement in the language, because 
last time I ran into this I had no such luck. But after seeing 
that your example did work, I figured one could try to get the 
best of both worlds by using a strongly-typed wrapper function in 
one's class.  So far it seems to work:


import std.traits;

class A(KeyT, alias HashF) {
  // Strongly-typed wrapper around template value parameter 
'HashF'.

  static size_t hash(in KeyT key) {
return HashF(key);
  }
  static this() {
static assert(isCallable!HashF, "Hash function is not 
callable!");
static assert(Parameters!(HashF).length == 1, "Hash function 
must take 1 argument.");

static assert(is(Parameters!(HashF)[0] : const(KeyT)),
"Hash parameter must be const.");
static assert(is(typeof(HashF(KeyT.init)) : size_t),
"Hash function must return size_t type.");
  }

  KeyT data;
  size_t getHash() const {
return hash(data);
  }
}

void main() {
auto a = new A!(int, (int a) => cast(size_t) a);
a.data = 5;
a.getHash();
}


Best Way to Pass Template Typed Alias Parameters for Functions?

2018-12-23 Thread Vijay Nayar via Digitalmars-d-learn
I have a few cases where I would like to pass in a function as a 
value to a template, but I want to ensure that the function takes 
certain kinds of parameters, is a const function, or matches any 
other set of conditions.


What is the best way to do this? Just to avoid any potential 
confusion, I've included a few examples below. I'm using explicit 
functions rather than lambdas just avoid any possibility of types 
being incorrectly inferred.


size_t myHashFunction(int a) { return cast(size_t) a; }

void main() {
class A(KeyT, HashF) { }
auto a = new A!(int, myHashFunction);
// ^ onlineapp.d: Error: template instance `A!(int, 
myHashFunction)`

// does not match template declaration `A(KeyT, HashF)`

// Alias parameter: 
https://dlang.org/spec/template.html#aliasparameters

class B(KeyT, alias HashF) { }
auto b = new B!(int, myHashFunction);
// ^ Works, but we cannot enforce the kind of function passed 
in.


// Typed alias parameter: 
https://dlang.org/spec/template.html#typed_alias_op

class C(KeyT, alias size_t function(KeyT) HashF) { }
auto c = new C!(int, myHashFunction);
// ^ onlineapp.d: Error: template instance `C!(int, 
myHashFunction)`
// does not match template declaration `C(KeyT, alias size_t 
function(KeyT) HashF)`


// Specialization: 
https://dlang.org/spec/template.html#alias_parameter_specialization

class D(KeyT, alias HashF : size_t function(KeyT)) { }
auto d = new D!(int, myHashFunction
// ^ onlineapp.d: Error: template instance `D!(int, 
myHashFunction)`
// does not match template declaration `D(KeyT, alias HashF : 
size_t function(KeyT))`

}

Looking at some of the code in std.algorithm, it seem that static 
asserts are sometimes used for this purpose. Does anyone have a 
solution to this problem of instantiating template classes whose 
parameters are functions?  I have used std.function "unaryFun" 
before, but this has the problem of not being able to specify 
function attributes, like const.


Re: Best Way to Pass Template Typed Alias Parameters for Functions?

2018-12-23 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 23 December 2018 at 19:10:06 UTC, Alex wrote:

On Sunday, 23 December 2018 at 18:53:15 UTC, Vijay Nayar wrote:
You're right, it does compile. I'm a bit surprised. I wonder 
if this is a relatively recent improvement in the language, 
because last time I ran into this I had no such luck. But 
after seeing that your example did work, I figured one could 
try to get the best of both worlds by using a strongly-typed 
wrapper function in one's class.  So far it seems to work:


import std.traits;

class A(KeyT, alias HashF) {
  // Strongly-typed wrapper around template value parameter 
'HashF'.

  static size_t hash(in KeyT key) {
return HashF(key);
  }
  static this() {
static assert(isCallable!HashF, "Hash function is not 
callable!");
static assert(Parameters!(HashF).length == 1, "Hash 
function must take 1 argument.");

static assert(is(Parameters!(HashF)[0] : const(KeyT)),
"Hash parameter must be const.");
static assert(is(typeof(HashF(KeyT.init)) : size_t),
"Hash function must return size_t type.");
  }

  KeyT data;
  size_t getHash() const {
return hash(data);
  }
}

void main() {
auto a = new A!(int, (int a) => cast(size_t) a);
a.data = 5;
a.getHash();
}


I'm not sure, whether you need the static this() part at all, 
as all of the asserts the compiler should do even when they are 
absent...


by isCallable you restrict the HashF to not use IFTI
by calling HashF(key) you ensure implicitely, that 
Parameters!(HashF).length == 1
by having hash(in KeyT key) defined with an "in" you ensured, 
that HashF does not mutate the argument
and by defining size_t getHash() you ensured the return type of 
HashF...


You are correct again! Playing around with using classes and 
functions returning the wrong type or not having a const 
argument, it seems that the compiler will assure that all the 
conditions needed by the wrapper function are satisfied and give 
a clear error.


I don't know when this happened, but this definitely makes the 
language a lot easier to use for these circumstances, and all the 
std.traits stuff in "static this()" can be thrown out.


Re: Best Way to Pass Template Typed Alias Parameters for Functions?

2018-12-23 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 23 December 2018 at 18:04:32 UTC, Alex wrote:

On Sunday, 23 December 2018 at 17:13:49 UTC, Vijay Nayar wrote:
I have a few cases where I would like to pass in a function as 
a value to a template, but I want to ensure that the function 
takes certain kinds of parameters, is a const function, or 
matches any other set of conditions.


I assume you are looking for constraints...
https://dlang.org/concepts.html

Then, case B is the way to go, see
https://run.dlang.io/is/jWU3tr

Case D also looks promising. Not sure, how to formulate the 
specialization right now...


There are a lot of traits you can use for the constraints.
https://dlang.org/phobos/std_traits.html
and
https://dlang.org/spec/traits.html
e.g., for constness there is getFunctionAttributes, which could 
be useful.


I've been playing with the idea of specifying the constraints or 
using "static assert" in the constructor. They are good options, 
but there's a few cases where they fall a bit short.  For 
example, imagine you have a container class that needs a 
comparator function to be able to compare the items in the 
container.  While you can use std.traits to assure the right kind 
of function is passed in, that information does not make its way 
into the type system.


For example, if you have a const function in your container like 
"T find() const", and this function needs to use that comparator, 
then you're out of luck because the compiler doesn't know that 
the comparator function is const and will not modify the objects 
being compared.


Last time I ran into this problem, my solution was simply to give 
up on const. But now I'm running into it again and trying to 
think through it again before giving up again.


Re: How do you debug @safe @nogc code? Can't figure out how to print.

2018-11-22 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 18 November 2018 at 11:00:26 UTC, aliak wrote:
On Saturday, 17 November 2018 at 21:56:23 UTC, Neia Neutuladh 
wrote:

On Sat, 17 Nov 2018 21:16:13 +, aliak wrote:

[...]


I meant something like:

void debugln(T...)(T args) @nogc
{
  import std.stdio;
  debug(MyProject) writeln(args);
}

You use that function instead of writeln in your 
@nogc-compatible templates:


void callFunc(alias func)()
{
  debugln("about to call function!");
  func();
  debugln("done calling function!");
}

Then I can write:

@nogc:
void foo() { printf("hello world\n"); }
void main() { callFunc!foo(); }


Aha! I misunderstood what you meant. Yes that's actually 
simpler that what I was doing :D Thanks!


Alternatively, you can use the core.stc libraries, which do not 
depend on the GC, for debugging.  
https://dlang.org/phobos/core_stdc_stdio.html#.printf


Re: Converting an integer to a string with std.format.

2019-01-07 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 6 January 2019 at 21:53:31 UTC, Per Nordlöw wrote:
When converting a single integer to a string is `formatValue` 
preferred over `formattedWrite` in terms of compilation and 
run-time performance?


Also, if you do not need to write to a stream or a range and just 
need the value, `format("%s", value)` works as well as std.conv's 
`to!string(value)`.


But between the two functions, it seems that the only difference 
is that `formattedWrite` only accepts the exact values that go on 
the output range (such as an integer), and `formatValue` has 
extra logic to convert structs, classes, and unions into strings 
by calling their `toString()` method.


What is the Utility of Parent Class Method Hiding in Inheritance?

2019-01-14 Thread Vijay Nayar via Digitalmars-d-learn

https://dlang.org/spec/function.html#function-inheritance

Consider this snippet from the documentation:

class A
{
int foo(int x) { ... }
int foo(long y) { ... }
}

class B : A
{
override int foo(long x) { ... }
}

void test()
{
B b = new B();
b.foo(1);  // calls B.foo(long), since A.foo(int) not 
considered

A a = b;

a.foo(1);  // issues runtime error (instead of calling 
A.foo(int))

}


I ran into this the other day, where I had a function of the same 
name in a child class, and found that all functions in the parent 
of the same name now became hidden, unless I add an alias 
statement.


After a bit of reading, I understood the rule and how it works, 
but what I'm missing is the "why".  Why is it desirable to hide 
methods from a parent class which have the same name (but 
different arguments) as a method in a class?


Re: How to attach function attributes to delegate type?

2019-03-01 Thread Vijay Nayar via Digitalmars-d-learn

On Wednesday, 27 February 2019 at 20:45:33 UTC, Alex wrote:
On Wednesday, 27 February 2019 at 20:03:15 UTC, Q. Schroll 
wrote:
For any type constructors like const, I can use ConstOf!T to 
get `T` with const attached. For a delegate/function type DG, 
e.g. int delegate(int), how can I get the @safe version of 
that type, i.e. int delegate(int) @safe?


I tried

alias SafeOf(DG) = DG @safe;

but it didn't compile.

The case is not @safe-specific; it's the same for all function 
attributes.


At https://p0nce.github.io/d-idioms/

there is a demonstration for @nogc:

´´´
import std.traits;

// Casts @nogc out of a function or delegate type.
auto assumeNoGC(T) (T t) if (isFunctionPointer!T || 
isDelegate!T)

{
enum attrs = functionAttributes!T | FunctionAttribute.nogc;
return cast(SetFunctionAttributes!(T, functionLinkage!T, 
attrs)) t;

}
´´´

Didn't try this for other cases, however...


When I need particular attributes, such as for a comparator, but 
also need to pass in a function as a template argument, one 
approach I've started to adopt is to only call this function from 
within a wrapper that has all the properties I want.


For example:

import std.stdio;

class MyThing(T, alias LessF) {
  // This wrapper defines the conditions for a valid LessF.
  @safe @nogc
  private static bool less(in T t1, in T t2) {
return LessF(t1, t2);
  }
}

void main()
{
  MyThing!(int, (a, b) => a < b) a;  // Compiles fine!
  MyThing!(int, (a, b) {
writeln("Not @nogc!");  // Compiler error!
return a < b;
  }) b;
}

The error looks like this, which is fairly readable too.

onlineapp.d(6): Error: `@nogc` function 
`onlineapp.main.MyThing!(int, (a, b)

{
writeln("Not @nogc!");
return a < b;
}
).MyThing.less` cannot call non-@nogc function


DDoc Reference Links point to /docs/docs instead of /docs?

2022-02-21 Thread Vijay Nayar via Digitalmars-d-learn

Greetings everyone,

I have a question regarding the use of [relative 
links](https://dlang.org/spec/ddoc.html#reference_links) in DDoc. 
According to the specification, you can include a reference to an 
object that is in scope using square brackets, e.g. `[Object]`.


One of my current projects is to add support to 
[Avro](https://avro.apache.org/docs/current/index.html) in D, and 
I encountered something unusual. Consider the following code 
snippets.


```d
// File: source/avro/parser.d
module avro.parser;
class Parser {
  /// Builds a [Schema] using a path to a ".avsc" file.
  public Schema parseFile(string fileName) {
// ...
  }
```

```d
// File: source/avro/schema.d
module avro.schema;
class Schema {
  // ...
}
```

When I build the documentation using `dub build -b docs`, which 
creates a bunch of individual `.html` files under the `docs` 
folder, but there is no `index.html` or anything else. I start by 
browsing to `file:///home/vnayar/projects/avro-d/docs/parser.html`


The documentation for the `Parser::parseFile` creates a link like 
so:

```html


  
  
  
Builds a class="code">Schema using a path to a ".avsc" file.

  

```

However, when I click the `Schema` link in my browser, the 
relative link of `docs/schema.html` actually is relative to the 
current file, thus, it takes me to 
`file:///home/vnayar/projects/avro-d/docs/docs/schema.html#Schema`. Because the folder `docs/docs` does not exist, I just get a file-not-found error.


Am I using DDocs incorrectly?


Function Parameters without Names?

2022-02-19 Thread Vijay Nayar via Digitalmars-d-learn
I encountered an odd bug in a project of mine which is 
illustrated in the example below:


```d
class Thing {
  int val;
  this(int) {
this.val = val;
  }
}

void main()
{
  auto t = new Thing(3);
  assert(t.val != 3);
}
```

The problem is that the parameter of the constructor actually has 
no name at all. Thus, the statement `this.val = val` simply sets 
the member variable to its own value, thus it stays the same as 
`int.init`.


According to the 
[specification](https://dlang.org/spec/function.html), this is 
permissible via the following grammar rules: `FuncDeclaration` => 
`FuncDeclarator` => `FuncDeclaratorSuffix` => `Parameters` => 
`ParameterList` => `Parameter` => `Declarator` => 
`ParameterAttributes_opt Type`.


What is the main motivator to allow parameters with no names? Do 
they get an automatic implied name like `_` or something?


Re: Detecting ElementType of OutputRange

2022-02-26 Thread Vijay Nayar via Digitalmars-d-learn
On Saturday, 26 February 2022 at 11:44:35 UTC, Stanislav Blinov 
wrote:

https://dlang.org/phobos/std_range_primitives.html#isOutputRange


This method requires the caller to explicitly declare the output 
range element type, which I was hoping to have to avoid, if it 
can be detected using reasonable assumptions.


Re: Detecting ElementType of OutputRange

2022-02-26 Thread Vijay Nayar via Digitalmars-d-learn
On Saturday, 26 February 2022 at 12:39:51 UTC, Stanislav Blinov 
wrote:


Considering that `put` is quite typically implemented as a 
template, I don't think that would be possible in general.


That is what I found as well, for example, the implementation of 
`put` from `Appender` and `RefAppender`, thus the algorithm fails 
to detect the `put` methods.


The question is, do you really need that? Your 
`BufferedOutputRange` can test the underlying range using 
`isOutputRange` in its own implementation of `put`, where the 
type of element is known, i.e. to test whether it can 
bulk-write a slice (or a range of) elements or has to make 
per-element calls to `put`.


This is exactly what I was doing, having the user pass in the 
element type themselves, and then the BufferedOutputRange check 
for both `isOutputRange!(ORangeT, ElemT)` and 
`is(typeof(ORangeT.init.put([ ElemT.init ])))`. In short, 
`isOutputRange` has many ways to be satisfied, 
(https://dlang.org/phobos/std_range_primitives.html#.put), but I 
want to restrict things further to only output streams that can 
do a bulk put.


Thanks for you advice. While automatic detection would be a nice 
convenience, it's not a deal breaker and it's also not 
unreasonable to expect the caller to know the element type they 
are inserting either.





Re: Cannot Call Super-Class Overloaded Function If Class has Function Override?

2022-03-01 Thread Vijay Nayar via Digitalmars-d-learn

On Tuesday, 1 March 2022 at 09:06:59 UTC, vit wrote:

On Tuesday, 1 March 2022 at 08:40:12 UTC, Vijay Nayar wrote:
I've randomly encountered a strange error, and I cannot find 
any explanation for it in the official documentation of syntax.


[...]


Here is more info (3.): 
https://docarchives.dlang.io/v2.078.0/spec/function.html#function-inheritance


Very well spotted, thank you for that!

I'm a bit surprised at this behavior though. Do you happen to 
know why it is considered bad to take into account the overloads 
of a super-class when resolving a call in a derived-class?


Cannot Call Super-Class Overloaded Function If Class has Function Override?

2022-03-01 Thread Vijay Nayar via Digitalmars-d-learn
I've randomly encountered a strange error, and I cannot find any 
explanation for it in the official documentation of syntax.


Essentially, a class cannot call function overload in a 
super-class if the class itself contains an override. Is this a 
bug? Is this on purpose? Take a look at `B.otherThing()` below.


``` d
void main()
{
  abstract class A {
// An abstract method for sub-classes
abstract void doThing(string a, size_t b);
// A convenience helper.
void doThing(string a) {
  doThing(a, a.length);
}
  }

  class B : A {
// If this overload exists, something strange happens...
override
void doThing(string a, size_t b) {
}

void otherThing() {
  // Error: `B.doThing(string a, ulong b)`
  // is not callable using argument
  // types `(string)`
  doThing("hello");

  super.doThing("hello");  // OK
}
  }
}
```


Re: DDoc Reference Links point to /docs/docs instead of /docs?

2022-02-21 Thread Vijay Nayar via Digitalmars-d-learn

On Monday, 21 February 2022 at 16:58:43 UTC, Adam D Ruppe wrote:

On Monday, 21 February 2022 at 15:35:41 UTC, Vijay Nayar wrote:

I'm a bit surprised I've never heard of `adrdox` before now.


yeah i don't advertise much. it is what runs on my dpldocs.info 
website though which auto-generates docs for dub packages.


Regarding ddoc, should I submit a bug report? If so, is ddoc 
considered part of the compiler?


Yeah, it is part of dmd, so you can file on issues.dlang.org if 
you want.


Bug reported here: https://issues.dlang.org/show_bug.cgi?id=22803


Re: DDoc Reference Links point to /docs/docs instead of /docs?

2022-02-21 Thread Vijay Nayar via Digitalmars-d-learn

On Monday, 21 February 2022 at 13:18:01 UTC, Adam D Ruppe wrote:
tbh ddoc is pretty bad, you should try my `dub run adrdox` 
instead which also creates html but its links actually work.


I gave it a try and I must say that the documentation is 
formatted in a very good way, and as you said, all the links 
work. I'm a bit surprised I've never heard of `adrdox` before 
now. Thank you kindly for that!


Regarding ddoc, should I submit a bug report? If so, is ddoc 
considered part of the compiler?


Detecting ElementType of OutputRange

2022-02-26 Thread Vijay Nayar via Digitalmars-d-learn
I was working on a project where it dealt with output ranges, but 
these ranges would ultimately sink into a source that would be 
inefficient if every single `.put(T)` call was made one at a time.


Naturally, I could make a custom OutputRange for just this 
resource, but I also got the idea that I could make a generalized 
`BufferedOutputRange` that would save individual `.put(T)` calls 
into memory until a threshold is reached, and then make one bulk 
call to the output stream it wraps with a single `.put(T[])` call.


While working on the template for this buffering OutputRange, I 
originally used `ElementType` on the output range I was given, 
hoping to detect what type of `.put(T)` is permitted. However, I 
found out that `ElementType` only works for input ranges as you 
can see here: 
https://github.com/dlang/phobos/blob/6bf43144dbe956cfc16c00f0bff7a264fa62408e/std/range/primitives.d#L1265


Trying to find a workaround, I ultimately created this, and  my 
question is, is using such a template a good idea or a terrible 
idea? Is it safe to assume that ranges should have a put method 
that may take arrays that I can detect? Should I give up on the 
idea of detecting the OutputRange type, and instead require the 
programmer to explicitly declare the output type for fear of them 
using a range that doesn't take arrays?


Here is the source of what I was thinking of, let me know your 
thoughts:


``` d
import std.range;
import std.traits;

// A specialization of std.range.ElementType which also considers 
output ranges.

template ElementType(R)
if  (is(typeof(R.put) == function))  // Avoid conflicts with 
std.range.ElementType.

{
  // Static foreach generates code, it is not a true loop.
  static foreach (t; __traits(getOverloads, R, "put")) {
pragma(msg, "Found put method, params=", 
Parameters!(t).length);

// Because all code gets generated, we use a 'done' alias to
// tell us when to stop.
static if (!is(done)) {
  // Attempts to save Parameters!(t) into a variable fail, so 
it is repeated.
  static if (Parameters!(t).length == 1 && 
is(Parameters!(t)[0] T : T[])) {

pragma(msg, "put for array found");
// Setting the name of the template replaces calls
// to ElementType!(...) with T.
alias ElementType = T;
alias done = bool;
  } else static if (Parameters!(t).length == 1 && 
is(Parameters!(t)[0] T)) {

pragma(msg, "put for single found");
alias ElementType = T;
alias done = bool;
  }
}
  }
  static if (!is(done)) {
alias ElementType = void;
  }
}

unittest {
  // Works for simple 1-element puts for structs.
  struct Ham0(T) {
void put(T d) {}
  }
  assert(is(ElementType!(Ham0!float) == float));

  // Works for classes too, which have array-based puts.
  class Ham1(T) {
void put(T[] d) {}
  }
  assert(is(ElementType!(Ham1!float) == float));

  // Distracting functions are ignored, and if single & array
  // puts are supported, the element type is still correct.
  struct Ham2(T) {
void put() {}
void put(float f, T[] d) {}
void put(T[] d) {}
void put(T d) {}
  }
  assert(is(ElementType!(Ham2!int) == int));
}
```


Re: How to create delegates with an independent scope?

2022-03-30 Thread Vijay Nayar via Digitalmars-d-learn

On Wednesday, 30 March 2022 at 12:53:10 UTC, vit wrote:

use two delegates :)

```d
(){
// Deliberately create a copy to keep in delegate scope.
string myStr = i.dup;
			// The delegate will hopefully carry this copy around in its 
own scope.

funcs ~= (() => myStr ~ " sandwich");
}();
```


Very interesting. Both this and creating a "function creator 
function" work, and it seems clear that functions create their 
own scopes. However, it seems that loops do not, is that correct? 
 Maybe I was thrown off by the surrounding `{ }`, but I had 
assumed that loops created their own scopes.


How to create delegates with an independent scope?

2022-03-30 Thread Vijay Nayar via Digitalmars-d-learn

Consider the following code example:

```d
import std.stdio;

void main()
{
  alias DelegateT = string delegate();

  // An array of delegates, each has their own scope.
  DelegateT[] funcs;
  foreach (i; ["ham", "cheese"]) {
// Deliberately create a copy to keep in delegate scope.
string myStr = i.dup;
// The delegate will hopefully carry this copy around in its 
own scope.

funcs ~= (() => myStr ~ " sandwich");
  }

  foreach (f; funcs) {
writeln(f());
  }
}
```

The expected output is: "ham sandwich" and then "cheese sandwich".

The actual output is: "cheese sandwich" and then "cheese 
sandwich".


It seems that the variable `myStr` is in a sort of shared scope 
for both functions in the array, and the last value written to it 
dominates.


How do I create a delegate that acts like a 
[closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures), that is, it carries with it the environment in which it was created?


Can std.variant be used with std.container.rbtree?

2022-04-01 Thread Vijay Nayar via Digitalmars-d-learn

Consider the following program:
```d
void main()
{   
  import std.stdio;
  import std.container.rbtree;
  import std.variant;

  // alias Type = int;  // Works with no problem.
  alias Type = Variant; // Produces error.

  auto rbTree = new RedBlackTree!(Type);
  rbTree.stableInsert(Type(3));
  rbTree.stableInsert(Type(2));
  rbTree.stableInsert(Type(4));
  foreach (v; rbTree.upperBound(Type(2))) {
writeln(v);
  }
}
```

A `RedBlackTree` constructs and runs perfectly fine using "int" 
as the data type, but it seems to blow up as soon as I use 
`std.variant : Variant`.


```
Compilation output (1: )

/dlang/dmd/linux/bin64/../../src/phobos/std/container/rbtree.d(1116): Error: `@safe` 
function `std.container.rbtree.RedBlackTree!(VariantN!32LU, "a < b", 
false).RedBlackTree.toHash` cannot call `@system` function 
`std.container.rbtree.RBRange!(RBNode!(VariantN!32LU)*).RBRange.front`
/dlang/dmd/linux/bin64/../../src/phobos/std/container/rbtree.d(682):
`std.container.rbtree.RBRange!(RBNode!(VariantN!32LU)*).RBRange.front` is 
declared here
/dlang/dmd/linux/bin64/../../src/phobos/std/container/rbtree.d(1116): Error: 
destructor `std.variant.VariantN!32LU.VariantN.~this` is not `nothrow`
/dlang/dmd/linux/bin64/../../src/phobos/std/container/rbtree.d(1113): Error: function 
`std.container.rbtree.RedBlackTree!(VariantN!32LU, "a < b", 
false).RedBlackTree.toHash` may throw but is marked as `nothrow`
onlineapp.d(10): Error: template instance 
`std.container.rbtree.RedBlackTree!(VariantN!32LU, "a < b", 
false)` error instantiating

```

This may seem like a strange thing to do, but it is useful when 
trying to have set of indexes, each of which is used on a 
different data field. The set of indexes can share a common 
data-type using Variant, which allows one to do things like have 
associative arrays of indexes which you can look up by field name.


However, it looks like `Variant` doesn't have the various 
attributes desired by `RedBlackTree`. Is there a way to make them 
compatible? Do I need to avoid std.container.rbtree and make my 
own which doesn't require these attributes, or do I need to 
implement my own version of Variant using a union and try to make 
it safe/nothrow/etc.?


Re: Can std.variant be used with std.container.rbtree?

2022-04-02 Thread Vijay Nayar via Digitalmars-d-learn

On Saturday, 2 April 2022 at 10:03:19 UTC, JG wrote:
You need an order on the elements in a red black tree. Am I 
correct in thinking you want a container of the form given a 
key (a string) recover some data (of different types). If so 
make the elements you store in the red black tree tuples (k,d) 
where k is a string and d is a variant. Define the order 
(k1,d1)<(k2,d2) if k1when you search for a key you get the pair and take the second 
part. I hope this makes sense.


This is correct, although it seems that Variant is not suitable 
for this purpose. The data structure roughly looks like this:


- FieldName (string) => Index
- Index has PrimaryKey (Variant) and a Value (also Variant)
- Index Entries are a tuple of the form (PrimaryKey, Value)

Each index is roughly used by passing in a value, and it spits 
out a range of PrimaryKeys that are equal, lessThan, or 
greaterThan that value depending on what's needed.


The special Entry data type (rather than just the raw value) was 
added because I still need the IDs when I look up values, and I 
think using the Entry is every so slightly more efficient than 
maintaining a separate data structure keeping a set of Ids per 
Value.


Variant itself works well for comparison, because it simply 
passes down the compare operation to the underlying type, but 
it's major flaw seems to be the lack of support for noThrow, 
@safe, etc.


On Saturday, 2 April 2022 at 10:04:49 UTC, vit wrote:

Try use ```std.sumtype```.


Very good suggestion, I haven't tried this before. I'll do some 
digging to see if I can make it work. Because it requires one to 
list the data types in advance, it can work for primary keys, 
however, it may not work in my particular use case because the 
values too that I'm organizing are also Variants. I hope it works.




Re: Can std.variant be used with std.container.rbtree?

2022-04-02 Thread Vijay Nayar via Digitalmars-d-learn

On Saturday, 2 April 2022 at 14:23:31 UTC, Salih Dincer wrote:
If your type includes opCmp() there is no reason not to use 
rbTree.


I am using rbTree, the problem is when I try to use it with 
Variant, at which point it blows up.





Re: Can std.variant be used with std.container.rbtree?

2022-04-02 Thread Vijay Nayar via Digitalmars-d-learn

On Saturday, 2 April 2022 at 10:04:49 UTC, vit wrote:

Try use ```std.sumtype```.


I'm playing with SumType to see how it works, and I must be doing 
something silly, because it fails to compile with the first 
example type I attempted. Consider the following:


```d
import std.sumtype;
import std.algorithm : cmp;

alias VarType = SumType!(double, ubyte[]);

int opCmp(const ref VarType v1, const ref VarType v2) {
  alias doMatch = tryMatch!(
  (ref ubyte[] _1, ref ubyte[] _2) => cmp(_1, _2),
  (_1, _2) => _1 < _2 ? -1 : (_2 < _1 ? 1 : 0));
  return doMatch(v1, v2);
}

void main() {
  VarType b1 = cast(ubyte[]) [0x01, 0x02, 0x03];
  VarType b2 = cast(ubyte[]) [0x01, 0x02, 0x04];
  b1 > b2;
}
```

The `tryMatch` method fails to compile, and instead I get the 
following error:

```d
/dlang/dmd/linux/bin64/../../src/phobos/std/sumtype.d(2004): 
Error: static assert:  "`handlers[0]` of type `int function(ref 
ubyte[] _1, ref ubyte[] _2) pure nothrow @nogc @safe` never 
matches"
/dlang/dmd/linux/bin64/../../src/phobos/std/sumtype.d(1739):  
  instantiated from here: `matchImpl!(const(SumType!(double, 
ubyte[])), const(SumType!(double, ubyte[])))`
onlineapp.d(10):instantiated from here: 
`tryMatch!(const(SumType!(double, ubyte[])), 
const(SumType!(double, ubyte[])))`

```

I'm not super sure why this handler would not match. If I do 
simple types like `double` or `int` it works, it even works with 
`string`, but the moment I include `ubyte[]`, it no longer 
compiles. In this example, I eliminated all other array types 
aside from `ubyte[]`, so there should be no conflicts in theory.




Re: Can std.variant be used with std.container.rbtree?

2022-04-02 Thread Vijay Nayar via Digitalmars-d-learn

On Saturday, 2 April 2022 at 14:35:10 UTC, Vijay Nayar wrote:
The `tryMatch` method fails to compile, and instead I get the 
following error:

```d
/dlang/dmd/linux/bin64/../../src/phobos/std/sumtype.d(2004): 
Error: static assert:  "`handlers[0]` of type `int function(ref 
ubyte[] _1, ref ubyte[] _2) pure nothrow @nogc @safe` never 
matches"

```


Through sheer trial and error, I discovered that changing the 
handler arguments from `ref ubyte[]` to `const ref ubyte[]` the 
error goes away. However, I did not find any information in the 
documentation or code that made this requirement clear. It was 
basically a guess based on the fact that `string` has no trouble 
but `ubyte[]` did, and string is basically just 
`immutable(char[])`.


So far, I'm finding that learning to use `SumType` is 
significantly more cryptic than `Variant`, by a large margin. 
I'll still give it a shot of course, because I want to get past 
this problem.


Re: How to make dub recursively build subPackages?

2022-02-02 Thread Vijay Nayar via Digitalmars-d-learn

On Wednesday, 2 February 2022 at 10:14:25 UTC, Vijay Nayar wrote:

Greetings folks,

In my project, I have a parent package with several 
sub-packages, each of which builds into either a library or an 
executable.


[...]


I should point out there is 1 exception to subPackages not being 
recursive. The `dub clean` command does recurse, and there is 
source code for it here: 
https://github.com/dlang/dub/blob/3abaa4d5b7c3b2c21ab75370cd5330e9ae7bbd12/source/dub/dub.d#L880


How to make dub recursively build subPackages?

2022-02-02 Thread Vijay Nayar via Digitalmars-d-learn

Greetings folks,

In my project, I have a parent package with several sub-packages, 
each of which builds into either a library or an executable.


I first started observing odd problems when I was running `dub 
build`, it would complain about different versions of vibe-d 
present, and it suggested running `dub upgrade`. After doing 
this, I noticed that most subPackages were not actually being 
upgraded.


The only thing I have found thus far is to manually run each 
subPackage one at a time, e.g. `dub :proto; dub :common; ...`.


Is it possible to get `dub upgrade` to recursively work on all 
sub-packages?


My parent package dub.sdl file:
```
name "funnel"
description "An in-memory queryable database for processing 
extreme loads of current data."

authors "Vijay Nayar"
copyright "Copyright © 2019, Vijay Nayar"
license "proprietary"
targetType "none"
targetPath "target"
dependency "funnel:proto" version=">=0.0.0"
dependency "funnel:spout" version=">=0.0.0"
dependency "funnel:stem" version=">=0.0.0"
dependency "funnel:mouth" version=">=0.0.0"
dependency "funnel:common" version=">=0.0.0"
subPackage "./common"
subPackage "./proto"
subPackage "./mouth"
subPackage "./stem"
subPackage "./spout"
```

Each subPackage is structured in the same way, for example, the 
common subPackage:

```
authors "Vijay Nayar"
copyright "Copyright © 2019, Vijay Nayar"
description "Common logic between the mouth and spout components."
license "proprietary"
name "common"
targetType "library"
targetPath "target"
dependency "funnel:proto" version="*"
dependency "poodinis" version="~>8.0.3"
dependency "vibe-d" version="~>0.9.4"
```

I mostly followed the dub documentation in setting up my project. 
https://dub.pm/package-format-sdl.html


Re: How to make dub recursively build subPackages?

2022-02-02 Thread Vijay Nayar via Digitalmars-d-learn
On Wednesday, 2 February 2022 at 14:07:08 UTC, Steven 
Schveighoffer wrote:

On 2/2/22 5:14 AM, Vijay Nayar wrote:
If you have them in the same repository, my recommendation is 
to use path dependencies instead of versions.


So, e.g.:

```sdl
dependency "funnel:proto" path="./proto" // in main dub.sdl
dependency "funnel:proto" path="../proto" // in sibling package
```

Because otherwise, dub is going to try and fetch the 
appropriate version from an online repository and not use your 
local files.


Honestly, for packages in the same repository, I'm not sure why 
you would version them separately from the main package. I 
don't even know if that works.


-Steve


I made this change and it did indeed work correctly, thank you 
for that! Truthfully, it was not entirely clear to me how dub was 
deciding where to go to build. I had assumed that this was being 
done via the `subPackage` lines.


The examples given in the offical documentation were also using 
versions, and I was following that: 
https://dub.pm/package-format-sdl.html#sub-packages





Re: How to make dub recursively build subPackages?

2022-02-02 Thread Vijay Nayar via Digitalmars-d-learn
On Wednesday, 2 February 2022 at 19:03:35 UTC, Steven 
Schveighoffer wrote:

On 2/2/22 1:42 PM, Vijay Nayar wrote:


Dub is kind of a hot mess in terms of the dependency resolution 
and ways to specify projects. I would love to see it cleaned 
up/reimplemented.


-Steve


For your larger more complex projects, what build system do you 
use? So far I've been having good luck with dub, but I haven't 
done any mixed-language projects lately either.




Approach to Integration Testing in D

2022-02-04 Thread Vijay Nayar via Digitalmars-d-learn

Greetings everyone,

## Question

What is your approach to integration testing in D? Do you use 
`unittest` blocks? Do you write stand-alone programs that 
interact with a running version of your program? Is there a 
library that makes certain kinds of testing easier?


For example, if I have a D project based on vibe.d, and I have 
custom converters to receive REST API request bodies in different 
formats based on the "Content-Type" HTTP header and other 
converter for the response based on the "Accepts" header, what is 
the best approach to test the entire program end-to-end?


## Context

Having done considerable work in Java using Spring and Spring 
Boot, it's very common to have [integration 
tests](https://softwaretestingfundamentals.com/integration-testing/), which the Spring Boot framework makes quite easy to set up with annotations like [@SpringBootTest](https://www.baeldung.com/spring-boot-testing#integration-testing-with-springboottest).


In a nutshell, Spring Boot is built on top of dependency 
injection, with a "Context" acting as a container for all the 
objects (called Beans) that are created and injected into that 
container. `@SpringBootTest` lets the user pick and choose which 
objects will be created for the test, and then when the program 
is run, only those objects are loaded. This allows one to do 
things like, start a complete web server environment, test by 
sending a request to some endpoint, and then validate that the 
response is what you would expect. This is especially helpful to 
validate that you are using the Spring Framework correctly, e.g. 
that custom converters you created that allow messages to be 
received in binary 
[protobuf](https://developers.google.com/protocol-buffers/) 
format instead of JSON work correctly.


Re: Approach to Integration Testing in D

2022-02-06 Thread Vijay Nayar via Digitalmars-d-learn

On Friday, 4 February 2022 at 17:39:00 UTC, H. S. Teoh wrote:
On Fri, Feb 04, 2022 at 12:38:08PM +, Vijay Nayar via 
Digitalmars-d-learn wrote: [...]


I am still in the process of experimenting, but the advice on 
this thread has all been very helpful. Right now I'm 
experimenting by creating a separate "integration" `dub` 
configuration which uses `std.process : spawnProcess` to run my 
vibe.d-based web server and try out requests on it.


However, in any kind of large organization using a build server, 
even when there are multiple services/builds running in the same 
environment, it can be very inconvenient use a fixed port on 
which to run this server. Another running service, another 
person's build, or a test that ran and died without closing its 
sockets can lead to conflicts during development.


In order to solve that problem of port conflicts during 
integration testing, I converted a utility class from the Java 
Spring Framework into D and wanted to share it here: 
https://gist.github.com/vnayar/04c6172d9f9991062974585bb3ccc8a4


The usage is very simple, and can be used by integration tests to 
pick random free ports on which to run their tests. Here is one 
of the available methods:


```d
/**
 * Find an available TCP port randomly selected from the range
 * \[ [PORT_RANGE_MIN], [PORT_RANGE_MAX] \].
 * Returns: an available TCP port number
 * Throws: Exception if no available port could be found
 */
ushort findAvailableTcpPort() {
  return findAvailableTcpPort(PORT_RANGE_MIN);
}

unittest {
  foreach (ushort i; 0..10) {
ushort port = findAvailableTcpPort();
assert(port >= PORT_RANGE_MIN && port <= PORT_RANGE_MAX);
  }
}
```


Re: Approach to Integration Testing in D

2022-02-06 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 6 February 2022 at 17:36:05 UTC, Vijay Nayar wrote:

On Friday, 4 February 2022 at 17:39:00 UTC, H. S. Teoh wrote:

On Fri, Feb 04, 2022 at 12:38:08PM +, Vijay Nayar via


When working on a dub configuration needed to separately run 
integration tests that operate on the fully built program from 
the outside, treating it like a black-box, I had run into a 
number of problems because `dub` implicitly created 
configurations called `application` or `library` only if you have 
no configurations of your own defined. But as soon as I added my 
own configuration, those default configurations were no longer 
being created and I suddenly found myself seeing strange errors 
when trying to run unit-tests or builds.


See [GitHub Dub Issue 
#1270](https://github.com/dlang/dub/issues/1270).


However, I did finally navigate the tricky waters and make a 
configuration that does actually work for `dub build`, `dub test` 
and `dub test --config=integration`.


I thought I would share what I found here:

```sdl
authors "Vijay Nayar"
copyright "Copyright © 2019, Vijay Nayar"
description "Receives data from sources, converts it to 
protobufs, and delivers it in batches to stem."

license "proprietary"
name "mouth"
targetPath "target"

# By default, 'dub' creates either an 'application' or 'library' 
config if no

# configuration exists.
# Because we need a configuration for integration tests, this 
forces us

# to create the 'application' config as well.
#
# The 'dub test' command searches for the first 'library' target 
type, and

# if none exists, the first 'executable'.

# Used by 'dub build' and 'dub test'.
configuration "application" {
  targetName "mouth"
  targetType "executable"
  dependency "funnel:common" path="../"
  dependency "funnel:proto" path="../"
  dependency "nanomsg-wrapper" version="~>0.5.3"
  dependency "poodinis" version="~>8.0.3"
  dependency "vibe-d" version="~>0.9.4"
  # This must be listed so that 'dub test' knows to ignore it.
  mainSourceFile "source/app.d"
}

# Used by 'dub test --config=integration'
configuration "integration" {
  targetName "mouth_integration"
  # This must not be 'library', or it will be used by 'dub test'.
  targetType "executable"
  # The "source/" directory is automatically included, it must be 
explicitly

  # excluded instead.
  excludedSourceFiles "source/*"
  # The integration tests' source is in './integration'.
  sourcePaths "integration"
  importPaths "integration"
  # Make sure the executable we are testing exists.
  preBuildCommands "echo IMPORT_PATHS=$$IMPORT_PATHS"
  preRunCommands "cd $PACKAGE_DIR ; dub build"
}
```


Re: vibe.d requestHTTP in static this causes infinite loop?

2022-05-20 Thread Vijay Nayar via Digitalmars-d-learn

On Friday, 20 May 2022 at 01:41:59 UTC, Ali Çehreli wrote:

On 5/19/22 16:44, Vijay Nayar wrote:

> If I remove the call from `static this()`, then the web call
works as
> normal. Any idea why calling vibe.d's `requestHTTP` function
inside of a
> module's static construction would cause an infinite loop?

I am not experienced with vibe.d.

'static this' is executed per thread. If requestHTTP starts a 
new thread, then I can see how you would be in an infinite 
loop. I wonder whether it should be 'shared static this' (which 
is executed once per program, not per thread).


Ali


Very clever, you were exactly right. I had not thought of that, 
but that is indeed what was happening.


vibe.d requestHTTP in static this causes infinite loop?

2022-05-19 Thread Vijay Nayar via Digitalmars-d-learn
I've encountered an unusual behavior that I have no good 
explanation for. Consider the following code example:


```d
import vibe.core.log : logInfo;
import vibe.http.client : requestHTTP, HTTPClientRequest, 
HTTPClientResponse;

import vibe.http.common : HTTPMethod;
import vibe.stream.operations : readAllUTF8;

void doThing() {
  requestHTTP("http://example.com/;,
  (scope HTTPClientRequest req) {
logInfo("Setting request method.");
req.method = HTTPMethod.GET;
  },
  (scope HTTPClientResponse res) {
logInfo("Log point 1");
string data = res.bodyReader.readAllUTF8();
logInfo("Log point 2: %s", data);
  });
}

static this() {
  logInfo("--- static this() ---");
  doThing();
}

void main(string[] args) {
  logInfo("--- main() ---");
  doThing();
}
```

The output of this program is actually an infinite loop with 
output of the form:

```
[Eventcore DNS Lookup() INF] --- static this() ---
[Eventcore DNS Lookup() INF] --- static this() ---
```

If I remove the call from `static this()`, then the web call 
works as normal. Any idea why calling vibe.d's `requestHTTP` 
function inside of a module's static construction would cause an 
infinite loop?


Re: Best practice for dub registry package and module names

2022-09-07 Thread Vijay Nayar via Digitalmars-d-learn

On Sunday, 4 September 2022 at 01:52:11 UTC, Ali Çehreli wrote:
Let's say I have three modules that work together, which I want 
to register on dub: A, B, and C.




Here I would take inspiration from the Java world, where a 
"domain" is used per project. Typically this domain is written 
from the most general part of the domain to the most specific, so 
"web.example.com" becomes "com.example.web".


For example:
```
import org.springframework.boot.SpringApplication;
```

So you could have: com.alicorp.a, com.alicorp.b, and com.alicorp.c

That being said, D is not Java, thus things like the company 
top-level domain could be left out and you end up with alicorp.a, 
alicorp.b, etc.


Thus the problem of name collision goes away until someone else 
tries to take the name "alicorp". I believe this is why Java uses 
the full domain, because unique domain ownership is already a 
solved problem, they just ride along.


Packages like `vibe` follow a similar mechanism, where all the 
useful modules and packages are nested under a single package.


Re: Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Vijay Nayar via Digitalmars-d-learn

On Thursday, 5 January 2023 at 16:41:32 UTC, Adam D Ruppe wrote:

On Thursday, 5 January 2023 at 16:38:49 UTC, Vijay Nayar wrote:
Does that class inherit the scope of the function it is 
inside, similar to how an inner class does with an outer class?


yup. They can see the local variables from the function.


Glad to learn that. Having worked many years in the Java world, 
where basically "class" and "scope" are nearly synonymous, I just 
assumed that classes could only get the scope of other classes, 
it never occurred to me that it could get a scope from a function.


Thanks for the explanation!


Re: Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Vijay Nayar via Digitalmars-d-learn

On Thursday, 5 January 2023 at 13:47:24 UTC, Adam D Ruppe wrote:

On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote:
Why is this error only found when declaring a class in the 
unittest?


A unittest is just a special function, it can run code and have 
local variables.


classes and structs declared inside it have access to those 
local contexts, which it calls the outer function context.


Make the outer class `static` too to lift it out of this and 
your error should go away.


That's very informative, I didn't realize that `unittest` is 
actually a function.


It raises another question one step deeper, what does it mean to 
define a non-static class within a function? Does that class 
inherit the scope of the function it is inside, similar to how an 
inner class does with an outer class?


Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Vijay Nayar via Digitalmars-d-learn
I've run into an unexpected problem that only seems to happen in 
unittests, but not outside of them. Consider the following 
example:


```
unittest {
  class Ab {
int a;
string b;

static class Builder {
  int _a;
  string _b;
  Builder a(int a) {
_a = a;
return this;
  }
  Builder b(string b) {
_b = b;
return this;
  }
  Ab build() {
Ab t = new Ab();
t.a = _a;
t.b = _b;
return t;
  }
}
  }

  Ab ab = new Ab.Builder()
  .a(1)
  .b("ham")
  .build();
  assert(ab.a == 1);
  assert(ab.b == "ham");
}
```

This fails to compile with the following error:
```
Generating test runner configuration 'builder-test-library' for 
'library' (library).
Starting Performing "unittest" build using /usr/bin/dmd for 
x86_64.
Building builder ~master: building configuration 
[builder-test-library]
source/builder.d(58,16): Error: outer function context of 
`builder.__unittest_L41_C1` is needed to `new` nested class 
`builder.__unittest_L41_C1.Ab`

Error /usr/bin/dmd failed with exit code 1.
```

However, if I move the class definition outside of the unittest 
block, then everything works fine:

```
class Ab {
  int a;
  string b;

  static class Builder {
int _a;
string _b;
Builder a(int a) {
  _a = a;
  return this;
}
Builder b(string b) {
  _b = b;
  return this;
}
Ab build() {
  Ab t = new Ab();
  t.a = _a;
  t.b = _b;
  return t;
}
  }
}

unittest {
  Ab ab = new Ab.Builder()
  .a(1)
  .b("ham")
  .build();
  assert(ab.a == 1);
  assert(ab.b == "ham");
}
```

```
 Generating test runner configuration 
'builder-test-library' for 'library' (library).
Starting Performing "unittest" build using /usr/bin/dmd for 
x86_64.
Building builder ~master: building configuration 
[builder-test-library]

 Linking builder-test-library
 Running builder-test-library
2 modules passed unittests
```

Why is this error only found when declaring a class in the 
unittest?


Re: class variable initialization

2023-04-15 Thread Vijay Nayar via Digitalmars-d-learn

On Saturday, 15 April 2023 at 14:05:17 UTC, NonNull wrote:
I want a way to default initialize a class variable to a 
default object (e.g. by wrapping it in a struct, because 
initialization to null cannot be changed directly). Such a 
default object is of course not available at compile time which 
seems to make this impossible. Can this be done in some way?


Assuming you want a default object that is unique per class 
instance rather than shared among all instances of the same 
class, then I think the constructor might be where you want to 
initialize such a member.


E.g.
```
class Var {
  int val;
  this(int val) {
this.val = val;
  }
}

class MyClass {
  Var var;

  this() {
var = new Var(3);
  }
}
```

I believe if you do initialization at the class declaration 
level, then every instance of the class shares the same instance, 
e.g.:


```
class Var {}

class MyClass {
  Var var = new Var();
}

void main() {
  MyClass c1 = new MyClass();
  MyClass c2 = new MyClass();
  assert(c1.var is c2.var);
}
```


Re: Syntax for Static Import of User Define Attributes

2023-07-28 Thread Vijay Nayar via Digitalmars-d-learn

On Thursday, 27 July 2023 at 21:24:44 UTC, Dennis wrote:

On Thursday, 27 July 2023 at 21:19:08 UTC, Vijay Nayar wrote:
Attempted Fix 2: Enclose the entire attribute name in 
parenthesis.

```
static import vibe.data.serialization;

class ChatCompletionFunctions {
  @(vibe.data.serialization.name)("name")
  ...
}
```


Try:

```D
@(vibe.data.serialization.name("name"))
```


This one causes a different error, because it invokes the 
template-argument syntax: 
https://dlang.org/spec/attribute.html#uda


Re: Syntax for Static Import of User Define Attributes

2023-07-28 Thread Vijay Nayar via Digitalmars-d-learn
On Friday, 28 July 2023 at 11:54:12 UTC, Steven Schveighoffer 
wrote:

On 7/28/23 4:15 AM, Vijay Nayar wrote:

I tried it and it worked for me. The template-argument syntax 
is normal. It's just a list of types or expressions (i.e. not a 
function argument list)


What is the error?

-Steve


You're right, I must have tried something slightly different 
without realizing it. The syntax that works seems to be to 
enclose the entire fully-qualified-name of the 
user-defined-attribute along with all its arguments within 
parentheses.


However, this makes me wonder. Is there any reason why the `@` 
shouldn't recognize the dots in a fully-qualified-name on its 
own, without the need for parentheses?