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?


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: 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: Builder: Tiny Utility Library to Add a Builder API to Classes

2023-01-06 Thread Vijay Nayar via Digitalmars-d-announce

On Friday, 6 January 2023 at 09:26:51 UTC, thebluepandabear wrote:

  .isActive(true)
  .build();
```


Good 

how would I extend the builder methods?


The builder methods are automatically generated and go up the 
inheritance chain to capture all the fields in your class. (I 
assume that you are referring to inheritance when you say 
"extend"?)


Here is one of the unit-tests demonstrating this:

```
class A2 {
  int a;
  string b;
}

class B2 : A2 {
  int c;

  mixin AddBuilder!(typeof(this));
}

/// All inherited fields should be available from the builder.
unittest {
  B2 b2 = B2.builder()
  .a(3)
  .b("ham")
  .c(4)
  .build();

  assert(b2.a == 3);
  assert(b2.b == "ham");
  assert(b2.c == 4);
}
```


Re: Builder: Tiny Utility Library to Add a Builder API to Classes

2023-01-06 Thread Vijay Nayar via Digitalmars-d-announce
On Thursday, 5 January 2023 at 23:31:36 UTC, Vladimir Marchevsky 
wrote:

On Thursday, 5 January 2023 at 21:48:40 UTC, Vijay Nayar wrote:


2. Using a constructor with many arguments.
```
A a = new A("Bob", 20, false, true);
```

This approach can construct arguments inline, such as during a 
function call, however, the arguments are not labeled, making 
it easy to get the order wrong or for the meaning to be 
unclear.


Hopefully we'll finally have named arguments. Considering they 
were accepted to language more than two years ago - maybe in 
the next century...


Named arguments would definitely obviate this tool, but in the 
meanwhile, this tool basically lets you achieve the same 
objectives in terms of single-expression construction and clearly 
labeled arguments. I guess one extra advantage of the `builder` 
library is that you also don't have to bother writing a 
constructor at all and can just use the default one.


Builder: Tiny Utility Library to Add a Builder API to Classes

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

https://code.dlang.org/packages/builder

Interacting with many projects that are related to Java, I could 
not help notice that a common "Builder API" is not easily 
available in D.


What is the problem? When constructing classes, especially those 
with lots of data, there are two broad ways of building the 
object.


1. Initializing each field in a different statement.
```
A a = new A();
a.setName("Bob");
a.setAge(20);
a.isProbation(false);
a.isActive(true);
...
```

This approach involves writing a lot of boiler plate, and it 
doesn't work well for quickly creating objects inline, such as 
during a function call.


2. Using a constructor with many arguments.
```
A a = new A("Bob", 20, false, true);
```

This approach can construct arguments inline, such as during a 
function call, however, the arguments are not labeled, making it 
easy to get the order wrong or for the meaning to be unclear.



This library allows one to get the best of both worlds. 
Construction within a single statement, but also without losing 
meaning of the parameters, e.g.


```
class A {
  string name;
  int age;
  bool isProbation;
  bool isActive;

  mixin AddBuilder!(typeof(this));
}

A a = A.builder()
  .name("Bob")
  .age(20)
  .isProbation(false)
  .isActive(true)
  .build();
```


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?


OpenAPI Client Generator

2023-01-02 Thread Vijay Nayar via Digitalmars-d-announce
I would like to put an announcement for two new projects added to 
https://code.dlang.org.


https://code.dlang.org/packages/openapi-client

This project is an executable that reads an [OpenAPI 
Specification](https://spec.openapis.org/oas/latest.html) in JSON 
format and writes a D client to interact with the described REST 
API.


https://code.dlang.org/packages/stripe-client

This project contains code produced by the `openapi-client` 
project to provide an interface to 
[Stripe](https://stripe.com/en-de), which is a service that 
allows one to make and receive online payments using a wide 
variety of methods, ranging from Credit Cards, to bank transfers, 
to even invoices.


Usage of the client libraries generated by `openapi-client` 
follows a similar pattern:
1. "Service" classes represent groups of related API Endpoints by 
URL.
2. Each method of a "Service" class corresponds to a single API 
Endpoint.

3. The methods generally take up to 3 arguments:
   - Parameters: These ultimately translate into path, header, 
cookie, or query-string parameters of the endpoint, depending on 
the OpenAPI Specification.
   - RequestBody: This corresponds to the uploaded HTTP request 
body for POST or PUT requests.
   - ResponseHandler: A object to set typed `delegates` to handle 
endpoint responses. The types may vary depending on the status 
code, e.g. a `200 OK` might process a `ChargeList` argument, but 
a `400 NOT FOUND` response might provide an `Error_` argument 
instead.


Example code:
```
import stripe.security : Security;
import stripe.service.v1_charges_service : V1ChargesService;
import vibe.data.json : serializeToJsonString;

// 1. Stripe's OpenAPI specification has two valid security 
schemes:

//   - HTTP Basic Auth (named "BasicAuth")
//   - HTTP Bearer Auth (named "BearerAuth")
Security.configureBasicAuth(
"sk_test_51MFbD...vri",  // Username / API key
""); // With Stripe, the password is 
always blank.


// 2. Service classes are created from valid URL paths + 
"Service", e.g. "/v1/charges" => "V1ChargesService".

auto service = new V1ChargesService();

// 3. Each endpoint has a "Params" object which covers any path, 
query-string, header, or cookie parameters.

auto params = new V1ChargesService.GetChargesParams();

// 4. Some requests have a request body, which will be an 
argument to the method,

// e.g. "postCharges(params, requestBody, handler)".

// 5. Different HTTP status codes can be associated with 
different data types.
// Create a handler object and add your own delegates that say 
what to do with each response.

auto handler = new V1ChargesService.GetChargesResponseHandler();

// 6. This handler is for a successful 200 response, there's also 
a default handler for errors.
handler.handleResponse200 = 
(V1ChargesService.GetChargesResponseHandler.ChargeList 
chargeList) {

  // Simply print out our response in JSON format.
  writeln(serializeToJsonString(chargeList));
};

// 7. Now call the desired endpoint and your handler will be 
invoked depending on the response.

service.getCharges(params, handler);
```

Feedback is always welcome, or bugs can be reported on each 
project's GitHub Issues.


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: Vibe.d v0.9.5 released!

2022-07-18 Thread Vijay Nayar via Digitalmars-d-announce

On Monday, 18 July 2022 at 16:07:02 UTC, Mathias LANG wrote:

Hi everyone,
A new version of Vibe.d has been released today.
You can see the list of changes [on 
Github](https://github.com/vibe-d/vibe.d/releases/tag/v0.9.5).


Of particular interest to me is the bump of the deimos/OpenSSL 
dependency to v3.x.x.


Great news! I've definitely run into the SSL configuration issues 
before, and this should help make Vibe.d adoption easier for new 
users.


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




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


Re: Release: avro-d v0.1.0

2022-03-16 Thread Vijay Nayar via Digitalmars-d-announce

On Wednesday, 9 March 2022 at 14:26:10 UTC, Vijay Nayar wrote:
The initial v0.1.0 of the Avro library in D can be found here: 
https://code.dlang.org/packages/avro-d


Version 0.2.2 has been released, which includes the ability to 
read and write generic objects in JSON format in addition to the 
aforementioned binary format.


Release: avro-d v0.1.0

2022-03-09 Thread Vijay Nayar via Digitalmars-d-announce

Greetings D Community,

Do you have need for an efficient binary format for encoding and 
decoding data, but are hesitant to use things like [Google 
Protocol Buffers](https://developers.google.com/protocol-buffers) 
due to the need to re-compile code in order to change formats?


[Apache Avro](https://avro.apache.org/docs/current/) addresses 
many of these problems by pairing a binary (and other) format 
with a JSON formatted schema which is part of the protocol.


Sadly, this protocol is not available in the D Programming 
language... until now.


The initial v0.1.0 of the Avro library in D can be found here: 
https://code.dlang.org/packages/avro-d


## Features Implemented

### Schema representation

A set of data classes exist to represent schemas for generation 
in code or the processing of data.


For example:
```d
import avro.schema;
auto schema = new UnionSchema([
Schema.createPrimitive(Type.STRING),
Schema.createPrimitive(Type.INT)]);
```

### Schema parsing & validation

Schemas may be parsed from files, text, or JSON.

For example:
```d
import avro.parser;
auto parser = new Parser();
Schema schema =  parser.parseText(q"EOS
{"namespace": "example.avro",
 "type": "record",
 "name": "User",
 "fields": [
 {"name": "name", "type": "string"},
 {"name": "favorite_number", "type": ["int", "null"]},
 {"name": "favorite_color", "type": ["string", "null"]}
 ]
}
EOS");
```

Errors in the JSON format of a schema will lead to descriptive 
errors.


### Generic Data types

Generic data objects may be created according to schemas with 
their values set to schema-appropriate
defaults and validation logic when setting values. Most 
`GenericDatum` objects make use of
`.getValue!T()` and `.setValue(T)(T val)` methods, however, many 
convenience functions also exist.


For example:
```d
import avro.generic.genericdata;

// Initializes the GenericDatum according to the schema with 
default values.

GenericDatum datum = new GenericDatum(schema);
assert(datum.getType == Type.RECORD);

// Primitive values can be set and retrieved.
datum.getValue!(GenericRecord).getField("name").setValue("bob");

// Convenience shortcut using opIndex() and opAssign() for 
primitive types.

datum["name"] = "bob";

assert(datum["name"].getValue!string == "bob");

// Enums have convenience functions directly on GenericData.
datum["favorite_number"].setUnionIndex(0);
assert(datum["favorite_number"].getUnionIndex() == 0);

// Arrays also have convenience functions.
datum["scores"] ~= 1.23f;
datum["scores"] ~= 4.56f;
assert(datum["scores"].length == 2);
p
// Maps do as well.
datum["m"]["m1"] = 10L;
datum["m"]["m2"] = 20L;
assert(datum["m"]["m1"].getValue!long == 10L);
```

### Binary Serialization/Deserialization

`GenericData` objects can be written using an encoder.

For example:
```d
import avro.codec.binaryencoder;
import avro.generic.genericwriter;

ubyte[] data;
auto encoder = binaryEncoder(appender());
GenericWriter writer = new GenericWriter(schema, encoder);
writer.write(datum);

assert(data == [
// Field: name
// len=3 b o b
0x06, 0x62, 0x6F, 0x62,
// Field: favorite_number
// idx=0 8
0x00, 0x10,
// Field: favorite_color
// idx=0 len=4 b l u e
0x00, 0x08, 0x62, 0x6C, 0x75, 0x65
]);
```

They may also be read using a decoder.

For example:
```d
import avro.codec.binarydecoder;
import avro.generic.genericreader;

auto decoder = binaryDecoder(data);
GenericReader reader = new GenericReader(schema, decoder);
GenericDatum datum;
reader.read(datum);

assert(datum["name"].getValue!string() == "bob");
assert(datum["favorite_number"].getValue!int() == 8);
assert(datum["favorite_color"].getValue!string() == "blue");
```

## Features Not Yet Implemented

- Logical Type support
- Specific Data types generated for schemas
- JSON Serialization/Deserialization
- Codex compression support
- Object Container Files
- Protocol wire format
- Schema Resolution



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


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


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: 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: 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);
  }
}
```


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




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 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: The ABC's of Templates in D

2020-08-07 Thread Vijay Nayar via Digitalmars-d-announce

On Friday, 31 July 2020 at 13:46:43 UTC, Mike Parker wrote:

The blog:
https://dlang.org/blog/2020/07/31/the-abcs-of-templates-in-d/


This is very well written! I want to share it with my coworkers 
using Java to see if it piques their interest.






Re: Searching for Dgame Maintainer

2019-11-25 Thread Vijay Nayar via Digitalmars-d-announce

On Sunday, 24 November 2019 at 16:34:35 UTC, Dgame wrote:
Maybe some of you know Dgame (https://github.com/Dgame/Dgame), 
it was my biggest project using D and was a lot of fun at that 
time. But since I don't use D anymore, I have neither the time 
nor the desire and even less the knowledge to take care of it 
anymore. So, if anyone wants to keep it going, I am open for 
offers.


I have never used Dgame before, but what immediately stands out 
is that it's pretty well organized.  Your website also does a 
great job at explaining how to use the library and the tutorials 
are well done.  There is even a style guide for contributors.  It 
really seems that quite a bit of work and care went into making 
this.


I am curious to know why you are no longer using D?  Is it more 
that personal and professional life has taken up your free time, 
or have you found something else where you would prefer to invest 
your time and energy?  Or was it something about the D language 
or community that initiated the change?


Re: S2Geometry Library Release v0.2

2019-05-25 Thread Vijay Nayar via Digitalmars-d-announce

On Saturday, 25 May 2019 at 19:34:50 UTC, Sebastiaan Koppe wrote:

On Saturday, 25 May 2019 at 11:48:12 UTC, Vijay Nayar wrote:
D's philosophy of having a large tool-box makes this work 
doable by a single person while other languages have spent 
many years with many contributors.


Great work! Can you tell something about how you converted the 
code and how you plan to stay up-to-date?


I would say that this library is a bit of a special case in most 
regards. The code base is quite complicated not only in subject 
matter and mathematics, but also in the actual dependencies 
between modules as well. The code itself has numerous circular 
dependencies, but when you factor in the unit-tests as well, the 
case becomes much more severe. The original code also passes 
around references to stack objects frequently, and manual changes 
had to be made to replace that logic. This will give C++ a slight 
edge in performance, but I think the gain in safety is worth it.


The actual conversion was entirely by hand, making appropriate 
replacements for many parts of the algorithms. Where the original 
logic became nearly impossibly complex to understand, debugging 
was mostly done by following this procedure:


1. Find a failing test.
2. Instrument the D code with print statements leading up to the 
failing logic.

3. Instrument the C++ code with the equivalent print statements.
4. Run both tests and compare the output.
5. Add more print statements if there are no differences or if 
the code is not yet identified.

6. Cleanup.

If that approach sounds kinda silly, it's because it is. However, 
what it means is that the library is actually capable of being 
converted into D without me having to get a PhD in mathematics 
first :P


On the question of keeping the library up to date, this is also a 
bit of a special case. Previously I've used the Java version of 
this library which is already 8 years old, and it is extremely 
useful even today. The actual library itself is fairly complete, 
and even if it were to never get another update, it would 
continue to be very useful for a long time.


Re: S2Geometry Library Release v0.2

2019-05-25 Thread Vijay Nayar via Digitalmars-d-announce

On Saturday, 25 May 2019 at 11:48:12 UTC, Vijay Nayar wrote:
I wanted to announce here the v0.2 release of the S2 Geometry 
Library in the D language. The DUB page should be updated to 
show v0.2 shortly.


https://code.dlang.org/packages/s2geometry-d


Today I learned that released versions must be 3 digits in order 
to be picked up by DUB. The release is now v0.2.0.


S2Geometry Library Release v0.2

2019-05-25 Thread Vijay Nayar via Digitalmars-d-announce

Greetings everyone.

I wanted to announce here the v0.2 release of the S2 Geometry 
Library in the D language. The DUB page should be updated to show 
v0.2 shortly.


https://code.dlang.org/packages/s2geometry-d

What is it?
=
The S2 Geometry library is an extremely high precision and 
performant library for geometry on the surface of the Earth. It 
is useful for dealing with areas, boundaries, lines, polygons, 
etc. As a practical example, it can answer very quickly if 
thousands of driving paths would pass through the arbitrary 
boundaries of an airport and thus need to pay a toll.


It was originally created by Eric Veach and the library is used 
in Google. I have converted this library in the D programming 
language.


What's New?
=
This release is now nearly feature complete with the C++ library. 
Only encoding/decoding of geometric objects is missing.


What's in Store Next?

* More work is needed to improve performance further. The full D 
test suite runs in 139 seconds while the C++ full test suite only 
needs 112 seconds.
* Encoding/Decoding support for transmitting geometric objects in 
binary form.
* Work on this library will slow down, as I plan to start using 
it instead of writing it.


Why does this matter?

Currently only C++ and D have this level of feature support, 
which cannot be found in Java, Python, Go, Rust, or any other 
languages today.


Part of the reason for this is that it's a very very very large 
and complex project that makes use of a large set of C++ features.


---
Language   filesblank  comment code
---
C++  177 60821282037378
C/C++ Header 164 63851869121935
Python 1   35   24  188
CMake  100   16
---
SUM: 343125023153559517
---

D's philosophy of having a large tool-box makes this work doable 
by a single person while other languages have spent many years 
with many contributors.


Re: LDC 1.15.0

2019-04-10 Thread Vijay Nayar via Digitalmars-d-announce

On Saturday, 6 April 2019 at 17:40:39 UTC, kinke wrote:

Glad to announce LDC 1.15:

* Based on D 2.085.1.
* Support for LLVM 8.0. The prebuilt packages ship with LLVM 
8.0.0 and include the Khronos SPIRV-LLVM-Translator, so that 
dcompute can now emit OpenCL too.
* New -lowmem switch to enable the GC for the front-end, 
trading compile times for less required memory (in some cases, 
by more than 60%).
* New generic @llvmAttr("name") parameter UDAs, incl. @restrict 
with C-like semantics.
* Dropped support for 32-bit macOS. Min macOS version for 
prebuilt package raised to 10.9.
* Prebuilt packages don't depend on libtinfo/libedit and don't 
require SSSE3 anymore.
* Fix: functions annotated with `pragma(inline, true)` are 
implicitly cross-module-inlined again.


Full release log and downloads: 
https://github.com/ldc-developers/ldc/releases/tag/v1.15.0


Thanks to all contributors!


Pretty amazing work! I especially like the -lowmem option, which 
actually solves the problem of certain compile-time heavy 
algorithms failing to compile entirely due to running out of 
memory.


Re: DIP 1000--Scoped Pointers--Superseded

2019-03-07 Thread Vijay Nayar via Digitalmars-d-announce

On Thursday, 7 March 2019 at 11:30:01 UTC, Mike Parker wrote:
As most of you surely know, DIP 1000, "Scoped Pointers", has 
been sitting in the DIP queue with the Draft status for ages 
and was significantly out of sync with the implementation. When 
I first took over as DIP Manager, the initial plan was to 
rewrite the DIP to match the implementation once the 
implementation had stabilized.


I asked Walter about it recently and he agreed that, at this 
point, the "Superseded" status would be appropriate for this 
DIP. It was introduced when an implementation of DIP 1006 was 
implemented that differed from the proposal. The circumstances 
for DIP 1000 are similar, though perhaps more extreme.


So DIP 1000 is now branded "Superseded".

https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md


What is it superseded by?  Is there another DIP that supersedes 
the concept or implementation?


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


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.


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


Re: The New Fundraising Campaign

2019-01-02 Thread Vijay Nayar via Digitalmars-d-announce
On Wednesday, 2 January 2019 at 13:30:34 UTC, Martin Tschierschke 
wrote:
On Wednesday, 2 January 2019 at 13:07:23 UTC, Joakim Brännström 
wrote:
On Wednesday, 2 January 2019 at 10:16:11 UTC, Martin 
Tschierschke wrote:
This campaign will end in 43 day, so the question after app. 
50% is, what next?
Will we start collecting for something else or should we 
first try to extend the job of our pull request manager?


Thanks Martin for the reminder. From my observations of the 
activities on github it seems like Nicholas Wilson is doing an 
excellent job :-)


Regards, Joakim B.


Thank you! So here an update of the update:
$2,464 Raised of $3,000 Goal by 46 Supporters

=> We only need another 10 Supporters giving an average of $54. 
:-)


For me the credit card payment method fails without saying what's 
wrong. Is there another method to pay, like a IBAN that a 
transfer could be made to?


Re: DCD, D-Scanner and DFMT : new year edition

2018-12-31 Thread Vijay Nayar via Digitalmars-d-announce

On Monday, 31 December 2018 at 07:56:00 UTC, Basile B. wrote:
DCD [1] 0.10.2 comes with bugfixes and small API changes. DFMT 
[2] and D-Scanner [3] with bugfixes too and all of the three 
products are based on d-parse 0.10.z, making life easier and 
the libraries versions more consistent for the D IDE and D IDE 
plugins developers.


[1] https://github.com/dlang-community/DCD/releases/tag/v0.10.2
[2] https://github.com/dlang-community/dfmt/releases/tag/v0.9.0
[3] 
https://github.com/dlang-community/D-Scanner/releases/tag/v0.6.0


Really fantastic work! I typically use DCD integrated into Emacs 
via company-dcd-mode.


Re: DConf 2019: Shepherd's Pie Edition

2018-12-24 Thread Vijay Nayar via Digitalmars-d-announce

On Saturday, 22 December 2018 at 12:18:25 UTC, Mike Parker wrote:
Thanks to Symmetry Investments, DConf is heading to London! 
We're still ironing out the details, but I've been sitting on 
this for weeks and, now that we have a venue, I just can't keep 
quiet about it any longer.


Looking forward to it! The caliber of people at these conferences 
has been exceptional every year I've gone, and many of the ideas 
presented have been very valuable, whether they were directly 
related to DLang or not.


Just one small example was a 2017 talk by Bastiaan Veelo on D 
libraries implementing Parsing Expression Grammars, which I had 
never heard of at the time. But the idea ended up being very 
useful for greatly simplifying the interfaces of systems I was 
working on that year.



I've been doing quite a bit of work this year on the Google S2 
Geometric Library in D. If I can benchmark the library against 
the C++ version or show how it can be used to tackle some of the 
trickier real-time problems in large-scale web services, would it 
be a good candidate to try to make into a talk for the conference?


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: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();
}


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.


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: Blog post: What D got wrong

2018-12-19 Thread Vijay Nayar via Digitalmars-d-announce
On Wednesday, 12 December 2018 at 07:44:12 UTC, Walter Bright 
wrote:

On 12/11/2018 4:51 AM, Nicholas Wilson wrote:

> Returning a reference
Wow, thats f*ck'n stupid! https://run.dlang.io/is/SAplYw


It's quite deliberate.

ref in C++ is a type constructor, but it's so special-cased to 
behave like a storage class, it might as well be one. In D it 
is.


(For example, ref in C++ can only appear at the top level. 
There are no "pointers to refs".)


refs exist so the lifetime of them can be controlled for memory 
safety. Treating them as flexibly as pointers would make that 
pretty difficult. refs are the primary way a memory safe 
container can expose pointers to its contents.


Could you please elaborate a little bit more on this?  In the 
linked program, I had expected that "ref" would return a 
reference to "a" that would behave similar to a pointer. But when 
that reference is assigned to "b", and "b" is modified, "a" 
appears to retain its original value, implying that "b" is a copy.


When was the copy of "a" made?  Was it during the assignment to 
"b"?


I use ref regularly, especially when I have to port C++ code that 
does exactly that, exposing modifiable references to its members. 
And in my experience it works quite well, especially for array 
types and classes.


So what is the best way to understand this program and know why a 
copy of "a" is made?


S2 Geometric Library for D

2018-12-10 Thread Vijay Nayar via Digitalmars-d-announce
I would like to announce the release of the S2 Geometric Library 
in the D Programming Language.


Who: This is of interest to engineers who need to process very 
large amounts of geographic coordinate data very quickly.  E.g. 
ride-shares, bikes, maps, etc.


What: The S2 Geometric Library was originally developed by Eric 
Veach from Google to serve as a highly performance geo-spatial 
library with very high accuracy. It achieves this by keeping 
coordinates as 3D points which are projected onto the Earth's 
surface.  http://s2geometry.io/


Where: DUB Package - https://code.dlang.org/packages/s2geometry-d

When: Right now, the first version with most features is ready. 
The remaining features will be added in the following couple of 
months.


Why: I have used the Java port of this library 
(https://github.com/google/s2-geometry-library-java) in systems 
handling thousands of inputs per second with great results.  The 
Java version, however, is 7 years old, and because performance 
was my interest, I decided to port this library from it's modern 
C++ version to D.


How: Lots and lots of work over a long time:  
https://github.com/vnayar/s2geometry-d/graphs/code-frequency


Re: Using D for AWS Beanstalk applications (German)

2018-11-28 Thread Vijay Nayar via Digitalmars-d-announce

On Tuesday, 27 November 2018 at 21:39:42 UTC, Andre Pany wrote:

Hi,

Find here a short tutorial how you can directly execute D 
applications on AWS Beanstalk.


http://d-land.sepany.de/tutorials/cloud/native-aws-beanstalk-applikation/

Kind regards
Andre


I would never have believed that it would be so easy to run a D 
application on AWS.  Your description is very clear.  Well done!


Ich würde nie glaubt haben, dass es so einfach eine D-Anwendung 
auf AWS ausführen könnte.  Ihren Beschreibung ist wirklich klar.  
Gut gemacht!




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: 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: Shared - Another Thread

2018-10-18 Thread Vijay Nayar via Digitalmars-d

On Wednesday, 17 October 2018 at 21:12:49 UTC, Stefan Koch wrote:

Hi,

reading the other shared thread  "shared - i need to be 
useful"(https://forum.dlang.org/thread/mailman.4299.1539629222.29801.digitalmar...@puremagic.com)


let me to an important realisation concerning the reason 
shareding data across threads is so unintuitve and hard to get 
right.
The reason is that sharing in the real world has nothing to do 
with using something and the same time.
For example: If I share my flat with another person, that 
person, while occupying the same flat as me, cannot actually 
occupy the same space. It is physically impossible.


In other words sharing does not mean for multiple entities to 
own something it's rather about diving and managing the 
(temporary) ownership of fragments.


Therefore if ownership is unclear sharing is impossible.
The safest default for something shared with unclear ownership 
is to view it as untouchable/unreadble/unwritable until 
ownership is established.


My understanding is that the "shared" keyword can be useful 
especially with array types that are operated on by multiple 
threads.  Some algorithms put together data following specific 
rules on how that data can be fragmented.


Imagine a simple algorithm that does logic on very long numbers, 
split into bytes.  One multi-threaded implementation may use 4 
threads.  The first operating on bytes 0, 4, 8, etc.  The second 
operating on bytes 1, 5, 9, etc.


In this case, a mutex or lock isn't actually needed, because the 
algorithm itself assures that threads don't collide.


It's an over-simplification, but I think this is basically what 
the prime-number finding algorithm by Jabari Zakiya is doing.


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: A Friendly Challenge for D

2018-10-16 Thread Vijay Nayar via Digitalmars-d

On Monday, 15 October 2018 at 22:17:57 UTC, Jabari Zakiya wrote:
$ dub build --compiler=ldc2 -b=release && echo "30" | 
./twinprimes

Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 1 ms, 864 μs, and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 196 ms, 566 μs, and 5 hnsecs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/- 1
total time = 198 ms, 431 μs, and 2 hnsecs

My understanding is that the difference in performance is 
largely due to slightly better optimization from the LLVM 
based ldc2 compiler, where I believe Nim is using gcc.


Here's what I get on my system.

$ echo 3_000_000_000 | ./twinprimes_test7yc.0180.gcc821
Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 0.000 secs
perform twinprimes ssoz sieve
sieve time = 0.144 secs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/-1
total time = 0.144 secs

Could you list your hardware, D ver, compiler specs.

I will run your code on my system with your D version and 
compiler, if I can.


Excellent work!


D has multiple compilers, but for the speed of the finished 
binary, LDC2 is generally recommended.  I used version 1.11.0.  
https://github.com/ldc-developers/ldc/releases/tag/v1.11.0


I was using DUB to manage the project, but to build the 
stand-alone file from the gist link, use this command:  $ ldc2 
-release -O3 twinprimes_ssoz.d

And to run it:  $ echo "30" | ./twinprimes_ssoz

Running the program a bunch of times, I get variable results, 
mostly between 195ms and 250ms.  Running the Nim version, I also 
get variable results, mostly between 230ms and 280ms.


My system is an Alienware 14x R2 from 2012.  Specs can be found 
here: 
https://www.cnet.com/products/alienware-m14xr2-14-core-i7-3630qm-8-gb-ram-750-gb-hdd/specs/


Re: A Friendly Challenge for D

2018-10-15 Thread Vijay Nayar via Digitalmars-d

On Sunday, 14 October 2018 at 10:51:11 UTC, Vijay Nayar wrote:
Once I get the bugs out, I'm curious to see if any performance 
differences crop up.  There's the theory that says they should 
be the same, and then there's the practice.


I don't actually understand the underlying algorithm, but I at 
least understand the flow of the program and the structure.  The 
algorithm utilized depends heavily on using shared memory access, 
which can be done in D, but I definitely wouldn't call it 
idiomatic.  In D, message passing is preferred, but it really 
can't be well demonstrated on your algorithm without a deeper 
understanding of the algorithm itself.


A complete working version can be found at: 
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


I modified both versions of the program to utilize the 
pgParameters13 for more of an apples-to-apples comparison.


The final results are as follows:
$ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim && 
echo "30" | ./twinprimes_ssoz

Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 0.000 secs
perform twinprimes ssoz sieve
sieve time = 0.222 secs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/-1
total time = 0.223 secs

$ dub build --compiler=ldc2 -b=release && echo "30" | 
./twinprimes

Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 1 ms, 864 μs, and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 196 ms, 566 μs, and 5 hnsecs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/- 1
total time = 198 ms, 431 μs, and 2 hnsecs

My understanding is that the difference in performance is largely 
due to slightly better optimization from the LLVM based ldc2 
compiler, where I believe Nim is using gcc.




Re: A Friendly Challenge for D

2018-10-14 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 19:04:48 UTC, Jabari Zakiya wrote:

On Saturday, 13 October 2018 at 18:31:57 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 18:14:20 UTC, Vijay Nayar 
wrote:
On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya 
wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants 
as the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code 
is working correctly, and that the compiler is choking 
either/and because of a hard time limit and/or memory limit. 
That's why I put in a compiler output statement in 
'genPGparameters' to see the progression of the PG 
parameters being built by the compiler to initially find 
when the compiler started choking. You may also need to 
patch whatever facility in the D compiler chain that 
controls this too.


It's P17, the biggest one that takes the longest to build in 
the Nim version. I actually don't know what memory limits 
exist for the D compiler at compile-time, so I may need to do 
some homework.


It's not just DMD either.

$ ldc2 twinprimes_ssoz.d
...
generating parameters for P17
Killed

$ gdc twinprimes_ssoz.d
...
generating parameters for P17
gdc: internal compiler error: Killed (program cc1d)
Please submit a full bug report,
with preprocessed source if appropriate.
See  for instructions.

$ dmd twinprimes_ssoz.d
...
generating parameters for P17
Killed


In the Nim code, starting line 91 is when the PG constants are 
being generate at compile time.


-
# Generate at compile time the parameters for PGs P5-P17.
const parametersp5  = genPGparameters(5)
const parametersp7  = genPGparameters(7)
const parametersp11 = genPGparameters(11)
const parametersp13 = genPGparameters(13)
const parametersp17 = genPGparameters(17)
-

Can it compile just using P5 (the first line, others commented 
out), and then P7, etc?


I'm not understanding your comments now.

If you can get a working version up and running (with correct 
output) we can solve the P17 compiler issues later (or in a 
parallel forum thread), especially if you have to delve into 
the weeds of the compiler chain.


In my mind (same with Nim process) getting working code using 
any PG is first order priority (because you'll need getting 
multi-threading working too). Once you can do that, by default, 
you can then use any generator you want if you create the 
correct parameters for it. That's one of the advantages of the 
algorithm, it's PG agnostic (as long as your hardware will 
accommodate it).


So don't prioritize getting P17 to compile right now (in this 
thread). Create the working generic structure that can work 
with any PG first.


Updated:  
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


I still get a few runtime errors likely from mistakes in my 
conversion for certain primes.  I'll resolve those after I get 
back from the gym.


But as previous posters have said, the code is not really very 
different between Nim and D.  Most of it is array manipulation 
and arithmetic operations, and not many of the features of either 
D or Nim are very different.  Both turn into fast code, both have 
garbage collection, and both have generally similar operators and 
libraries for this kind of problem.


The biggest differences I observed revolved not around the 
languages themselves, but around code style.  For example, can 
you put a loop and 3 additional statements on a single line in D? 
 Yes.  But it is considered to be not very readable code from a 
style perspective.


Once I get the bugs out, I'm curious to see if any performance 
differences crop up.  There's the theory that says they should be 
the same, and then there's the practice.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 18:14:20 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya 
wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants 
as the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code is 
working correctly, and that the compiler is choking either/and 
because of a hard time limit and/or memory limit. That's why I 
put in a compiler output statement in 'genPGparameters' to see 
the progression of the PG parameters being built by the 
compiler to initially find when the compiler started choking. 
You may also need to patch whatever facility in the D compiler 
chain that controls this too.


It's P17, the biggest one that takes the longest to build in 
the Nim version. I actually don't know what memory limits exist 
for the D compiler at compile-time, so I may need to do some 
homework.


It's not just DMD either.

$ ldc2 twinprimes_ssoz.d
...
generating parameters for P17
Killed

$ gdc twinprimes_ssoz.d
...
generating parameters for P17
gdc: internal compiler error: Killed (program cc1d)
Please submit a full bug report,
with preprocessed source if appropriate.
See  for instructions.

$ dmd twinprimes_ssoz.d
...
generating parameters for P17
Killed



Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants as 
the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code is 
working correctly, and that the compiler is choking either/and 
because of a hard time limit and/or memory limit. That's why I 
put in a compiler output statement in 'genPGparameters' to see 
the progression of the PG parameters being built by the 
compiler to initially find when the compiler started choking. 
You may also need to patch whatever facility in the D compiler 
chain that controls this too.


It's P17, the biggest one that takes the longest to build in the 
Nim version. I actually don't know what memory limits exist for 
the D compiler at compile-time, so I may need to do some homework.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 15:50:06 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 15:19:07 UTC, Jabari Zakiya 
wrote:

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:
On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar 
wrote:

[...]


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


My mistake. I updated the file and forgot to include the 
'import algorithm' directive. The file is now fixed to include 
it. Download the corrected version or patch your file 
accordingly.


As stated in the file intro **YOU MUST DO THIS** to get it to 
compile with current Nim (they were supposed to fix this in 
this version 0.19.0 but didn't).


 To compile for nim versions <= 0.19.0 do following:
 1) in file: ~/nim-0.19.0/compiler/vmdef.nim
 2) set variable: MaxLoopIterations* = 1_000_000_000 (1 
Billion or >)

 3) then rebuild sysem: ./koch boot -d:release

If you are using 'choosenim' to install Nim (highly advisable) 
the full path is:


 ~/.choosenim/toolchains/nim-0.19.0/compiler/vmdef.nim

I'll post performance results from my laptop to give reference 
times to compare against.


Ok, now it builds.  I was previously following the build 
instructions from the Nim website and am not super clear what 
the "koch" tool does, but following your instructions, the 
program does build and run.  I'll take a stab at making a D 
version.


Interesting results so far.  I have a partially converted program 
here:  
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


The interesting part is that during compilation (with the command 
"dmd twinprimes_ssoz.d"), the compilation will abort with the 
message "Killed" and no further information. That's a new one for 
me, so I'm looking into the cause.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 15:19:07 UTC, Jabari Zakiya wrote:

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:
On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar 
wrote:

[...]


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


My mistake. I updated the file and forgot to include the 
'import algorithm' directive. The file is now fixed to include 
it. Download the corrected version or patch your file 
accordingly.


As stated in the file intro **YOU MUST DO THIS** to get it to 
compile with current Nim (they were supposed to fix this in 
this version 0.19.0 but didn't).


 To compile for nim versions <= 0.19.0 do following:
 1) in file: ~/nim-0.19.0/compiler/vmdef.nim
 2) set variable: MaxLoopIterations* = 1_000_000_000 (1 Billion 
or >)

 3) then rebuild sysem: ./koch boot -d:release

If you are using 'choosenim' to install Nim (highly advisable) 
the full path is:


 ~/.choosenim/toolchains/nim-0.19.0/compiler/vmdef.nim

I'll post performance results from my laptop to give reference 
times to compare against.


Ok, now it builds.  I was previously following the build 
instructions from the Nim website and am not super clear what the 
"koch" tool does, but following your instructions, the program 
does build and run.  I'll take a stab at making a D version.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:

On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar wrote:


I downloaded the reference NIM implementation and got the 
latest nim compiler, but I received the following error:

  $ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim
  twinprimes_ssoz.nim(74, 11) Error: attempting to call 
undeclared routine: 'sort'


For a person not familiar with nim, what's the fastest way to 
fix that?


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


I ran into the same problem as you did, and then followed the 
instructions from the error.  I modified the compiler source and 
increased the number of maximum iterations from 3_000_000 to 
1_000_000_000, rebuilt and installed it, but still ran into the 
exact same problem.  There may be something up with the algorithm 
itself.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Friday, 12 October 2018 at 21:08:03 UTC, Jabari Zakiya wrote:

On Friday, 12 October 2018 at 20:05:29 UTC, welkam wrote:
On Friday, 12 October 2018 at 16:19:59 UTC, Jabari Zakiya 
wrote:
The real point of the challenge is too see what idiomatic 
code...


There is no idiomatic D code. There is only better 
implementations.


D doesnt tell you how to write your code. It gives you many 
tools and you choose which tools to use. That`s what people 
like about D.


I await your implementation(s)! :-)


I downloaded the reference NIM implementation and got the latest 
nim compiler, but I received the following error:

  $ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim
  twinprimes_ssoz.nim(74, 11) Error: attempting to call 
undeclared routine: 'sort'


For a person not familiar with nim, what's the fastest way to fix 
that?


Re: Interesting Observation from JAXLondon

2018-10-12 Thread Vijay Nayar via Digitalmars-d

On Friday, 12 October 2018 at 07:13:33 UTC, Russel Winder wrote:
On Thu, 2018-10-11 at 13:00 +, bachmeier via Digitalmars-d 
wrote: […]

Suggestions?

My guess is that the reason they've heard of those languages 
is because their developers were writing small projects using 
Go and Rust, but not D.


I fear it may already be too late. Go, and now Rust, got 
marketing hype from an organisation putting considerable 
resources into the projects. This turned into effort from the 
community that increased rapidly, turning the hype into 
frameworks and libraries, and word of mouth marketing. It is 
the libraries and frameworks that make for traction. Now the 
hype is gone, Go and Rust, and their libraries and frameworks, 
are well positioned and with significant penetration into the 
minds of developers.


Talk to Java developers and they have heard of Go and Rust, but 
not D. Go is
more likely to them because of Docker and the context of The 
Web, for which Go
has a strong pitch. They have heard of Rust but usually see it 
as not relevant

to them, despite Firefox.

Talk to Python developers and they know of Go, many of them of 
Rust, but
almost never D. C and C++ are seen as the languages of 
performance extensions,

though Rust increasingly has a play there.

D has vibe.d, PyD, GtkD, and lots of other bits, but they've 
never quite had the resources of the equivalents in Go and Rust.


Also the D community as a whole is effectively introvert, 
whereas Go and Rust communities have been quite extrovert. 
"Build it and they will come" just doesn't work, you have to be 
pushy and market stuff, often using guerilla marketing, to get 
mindshare.


D has an excellent position against Python (for speed of 
development but without the performance hit) but no chance of 
penetrating the places where Python is strong due to lack of 
libraries and frameworks that people use – cf. Pandas, 
SciKit.Learn, etc.


D has an excellent position against Go as a language except 
that Go has goroutines and channels. The single threaded event 
loop and callback approach is losing favour. Kotlin is 
introducing Kotlin Coroutines which is a step on from the 
observables system of Rx. Structured concurrency abstracting 
away from fibres and threadpools. Java may well get this via 
Project Loom which is Quasar being inserted into the JVM 
directly. Whatever D has it doesn't seem to be going to compete 
in this space.


D without the GC has a sort of position against Rust, but I 
think that battle has been lost. Rust has won in the "the new C 
that isn't Go and doesn't have a garbage collector, and isn't 
C++, but does have all the nice monads stuff, oh and memory 
safety mostly".


When it comes down to it D will carry on as a niche language 
loved by a few unknown to most.


In my opinion, I don't think the game is over just yet.  One of 
D's biggest strengths has been its ability to adapt and innovate. 
 Despite being around since 2001, it is still forging ahead and 
many of the new features coming out in programming languages are 
coming to fruition in D before being back-ported to other 
languages.


The D crowd is certainly very introverted and very technically 
minded, it really seems to be an amazing hub for innovators and 
compiler designers.  But the D community has also been very 
receptive of changes to the language which allows it to evolve at 
a pace few other languages can match.


My personal opinion is that languages that grow up too fast get 
stuck because they have too much legacy code and certain options 
that they may have originally wanted become unavailable.


Go and Rust are gaining traction, especially among developers 
getting tired of very hard to work with languages.  Java is very 
very slow to evolve and there's a huge amount of effort invested 
in learning other JVM languages like Scala, I think largely 
because people are looking for alternatives.


Rust, while intriguing, is very alien in syntax and concept for 
many developers.  Go gets wider adoption than other languages 
I've seen, but the race is still on in my book.



One thing that does concern me, is the avenues in which people 
can discover D.  For me personally, after a particularly nasty 
C++ project, I just googled for "alternatives to C++" and that's 
how I found D back in 2009 or so.  But the same search today 
turns up nothing about D.  I'm not sure sure how people are 
supposed to find D.


Re: Interesting Observation from JAXLondon

2018-10-11 Thread Vijay Nayar via Digitalmars-d

On Thursday, 11 October 2018 at 11:50:39 UTC, Joakim wrote:
On Thursday, 11 October 2018 at 07:58:39 UTC, Russel Winder 
wrote:

This was supposed to come to this list not the learn list.

On Thu, 2018-10-11 at 07:57 +0100, Russel Winder wrote:
It seems that in the modern world of Cloud and Kubernetes, 
and the charging
model of the Cloud vendors, that the startup times of JVMs is 
becoming a
financial problem. A number of high profile companies are 
switching from

Java
to Go to solve this financial difficulty.

It's a pity D is not in there with a pitch.

I suspect it is because the companies have heard of Go (and 
Rust), but not

D.


I doubt D could make a pitch that would be heard, no google 
behind it and all that jazz. D is better aimed at startups like 
Weka who're trying to disrupt the status quo than Java shops 
trying to sustain it, while shaving off some up-front time.


Personally I think this is going to change soon depending on what 
options are available.  The amount of time and money that 
companies, especially companies using Java and AWS, are putting 
in to saving money with Nomad or Kubernetics on the promise of 
having more services per server is quite high.  However, these 
JVM based services run in maybe 1-2GB of RAM at the minimum, so 
they get maybe 4 services per box.


A microservice built using D and vibe.d could easily perform the 
same work using less CPU and maybe only 500MB of RAM.  The scale 
of improvement is roughly the same as what you would get by 
moving to containerization.


If D has the proper libraries and integrations available with the 
tools that are commonly used, it could easily break through and 
become the serious language to use for the competitive business 
of the future.


But libraries and integrations will make or break that.  It's not 
just Java you're up against, it's all the libraries like 
SpringBoot and all the integrations with AWS systems like SQS, 
SNS, Kinesis, MySQL, PostGREs, Redis, etc.


My hope is that D will be part of that future and I'm trying to 
add libraries as time permits.


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".


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: 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();
}


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?


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?


Associative Array that Supports upper/lower Ranges

2018-06-25 Thread Vijay Nayar via Digitalmars-d
I was in need of an associative array / dictionary object that 
could also support getting ranges of entries with keys below or 
above a given value.  I couldn't find anything that would do 
this, and ended up using the RedBlackTree to store key/value 
pairs, and then wrap the relevant functions with key lookups.


I feel that there was probably an easier way to do this, but I 
didn't find one.  Regardless, if anyone else has this kind of 
problem, you can get around it like this:


```
module rbtree_map;

import std.container.rbtree;
import std.algorithm : map;
import std.functional : binaryFun;
import std.meta : allSatisfy;
import std.range : ElementType, isInputRange;
import std.traits : isDynamicArray, isImplicitlyConvertible;

/**
 * A dictionary or associative array backed by a Red-Black tree.
 */

unittest {
  auto rbTreeMap = new RBTreeMap!(string, int)();
  rbTreeMap["a"] = 4;
  rbTreeMap["b"] = 2;
  rbTreeMap["c"] = 3;
  rbTreeMap["d"] = 1;
  rbTreeMap["e"] = 5;
  assert(rbTreeMap.length() == 5);
  assert("c" in rbTreeMap);
  rbTreeMap.removeKey("c");
  assert("c" !in rbTreeMap);
  rbTreeMap.lowerBound("c");  // Range of ("a", 4), ("b", 2)
  rbTreeMap.upperBound("c");  // Range of ("d", 1), ("e", 5)
}

final class RBTreeMap(KeyT, ValueT, alias KeyLessF = "a < b", 
bool allowDuplicates = false) {

public:
  static struct Pair {
KeyT key;
ValueT value;
  }

  alias keyLess = binaryFun!KeyLessF;

  alias RedBlackTreeT =
  RedBlackTree!(Pair, (pair1, pair2) => keyLess(pair1.key, 
pair2.key), allowDuplicates);


  RedBlackTreeT rbTree;

  // Forward compatible methods like: empty(), length(), 
opSlice(), etc.

  alias rbTree this;

  this() {
rbTree = new RedBlackTreeT();
  }

  this(Pair[] elems...) {
rbTree = new RedBlackTreeT(elems);
  }

  this(PairRange)(PairRange pairRange)
  if (isInputRange!PairRange && 
isImplicitlyConvertible!(ElementType!PairRange, Pair)) {

rbTree = new RedBlackTreeT(pairRange);
  }

  override
  bool opEquals(Object rhs) {
RBTreeMap that = cast(RBTreeMap) rhs;
if (that is null) return false;

return rbTree == that.rbTree;
  }

  /// Insertion
  size_t stableInsert(K, V)(K key, V value)
  if (isImplicitlyConvertible!(K, KeyT) && 
isImplicitlyConvertible!(V, ValueT)) {

return rbTree.stableInsert(Pair(key, value));
  }
  alias insert = stableInsert;

  ValueT opIndexAssign(ValueT value, KeyT key) {
rbTree.stableInsert(Pair(key, value));
return value;
  }

  /// Membership
  bool opBinaryRight(string op)(KeyT key) const
  if (op == "in") {
return Pair(key) in rbTree;
  }

  /// Removal
  size_t removeKey(K...)(K keys)
  if (allSatisfy!(isImplicitlyConvertibleToKey, K)) {
KeyT[K.length] toRemove = [keys];
return removeKey(toRemove[]);
  }

  //Helper for removeKey.
  private template isImplicitlyConvertibleToKey(K)
  {
enum isImplicitlyConvertibleToKey = 
isImplicitlyConvertible!(K, KeyT);

  }

  size_t removeKey(K)(K[] keys)
  if (isImplicitlyConvertible!(K, KeyT)) {
auto keyPairs = keys.map!(key => Pair(key));
return rbTree.removeKey(keyPairs);
  }

  size_t removeKey(KeyRange)(KeyRange keyRange)
  if (isInputRange!KeyRange
  && isImplicitlyConvertible!(ElementType!KeyRange, KeyT)
  && !isDynamicArray!KeyRange) {
auto keyPairs = keys.map(key => Pair(key));
return rbTree.removeKey(keyPairs);
  }

  /// Ranges
  RedBlackTreeT.Range upperBound(KeyT key) {
return rbTree.upperBound(Pair(key));
  }

  RedBlackTreeT.ConstRange upperBound(KeyT key) const {
return rbTree.upperBound(Pair(key));
  }

  RedBlackTreeT.ImmutableRange upperBound(KeyT key) immutable {
return rbTree.upperBound(Pair(key));
  }

  RedBlackTreeT.Range lowerBound(KeyT key) {
return rbTree.lowerBound(Pair(key));
  }

  RedBlackTreeT.ConstRange lowerBound(KeyT key) const {
return rbTree.lowerBound(Pair(key));
  }

  RedBlackTreeT.ImmutableRange lowerBound(KeyT key) immutable {
return rbTree.lowerBound(Pair(key));
  }

  auto equalRange(KeyT key) {
return rbTree.equalRange(Pair(key));
  }

}
```


Re: Expanding tool (written in D) use, want advice

2018-06-25 Thread Vijay Nayar via Digitalmars-d

On Friday, 22 June 2018 at 14:45:46 UTC, Jesse Phillips wrote:
Should I be looking more at the benefits of having D as a tool? 
It was a good choice for me since I know D so well (and other 
reasons at the time), but C# is a reasonable language in this 
space. I'm thinking, like should I go into how learning D 
wouldn't be too hard for new hire since it has similar syntax 
to C# and so on.


One strong argument to make is based on performance. Give them 
numbers about how fast your tool runs and make it efficient. The 
idea is that because the linting tool will be run for every 
incremental build a developer makes, slower running times are a 
barrier to productivity.


But once performance targets are defined, and if the company 
thinks that C# can also meet those targets, then really it's 
their call. Ultimately it is their company and their assets.


In such a case, I would generalize your tool for use outside of 
the specific context of your company, and make it the basis of an 
open source project.


Re: detectcycles: A source code dependency cycle checker

2018-06-18 Thread Vijay Nayar via Digitalmars-d-announce

On Sunday, 17 June 2018 at 20:20:48 UTC, Mario Kröplin wrote:
I did not mention it in the README, but the tred filter used in 
https://code.dlang.org/packages/depend complains about cyclic 
dependencies.


I am currently working on a branch, where the transitive 
reduction and the corresponding warnings are built in.


While this tool is for D only, it also allows to visualize and 
to check dependencies.


Very nice project.  The PlantUML output is a brilliant idea.

In my case, I am mostly analyzing projects that are NOT in D, so 
I need a general purpose tool. I'm putting it through practical 
runs this morning and discovering areas of improvement.


For example, in Java, one need not import dependencies within the 
same package, so I need to take a list of "uses" regex patterns 
instead of just having a single one, so that things like 
"@Autowired" from Spring can be detected as well.


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?




detectcycles: A source code dependency cycle checker

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

https://github.com/vnayar/detectcycles

I made a small configurable tool to detect software source 
dependency cycles that is configurable to use for most languages. 
By default, C++, Java, and D are supported, but add new languages 
is as simple as adding a few lines to JSON configuation file.


I often work on very large software projects in various different 
languages, and sometimes you walk onto projects that were large 
long before you got there. Part of my work involves 
re-architecting and breaking apart monolithic code bases, and 
knowing which components have been tied together as a block is 
useful for a quick analysis and helps show me where I need to 
focus my attention.


Hopefully other people find it useful as well.


Re: What's happening with the `in` storage class

2018-06-12 Thread Vijay Nayar via Digitalmars-d

On Saturday, 9 June 2018 at 02:38:14 UTC, SonicFreak94 wrote:

On Saturday, 9 June 2018 at 02:17:18 UTC, Adam D. Ruppe wrote:

On Saturday, 9 June 2018 at 02:13:00 UTC, Walter Bright wrote:
But it was never enforced, meaning that suddenly enforcing it 
is just going to break code left and right.



It isn't going to break anything. It is going to *correctly 
diagnose already broken code*.


That's a significant difference. Real world D users don't like 
broken code, but they DO like the compiler catching new bugs 
that slipped by before.


I agree. I would rather my potentially broken code be pointed 
out to me rather than removing the much more concise `in` from 
my code. In any case, I feel as though the concept of both `in` 
and `out` should be fairly intuitive. `in` would be a read-only 
reference (C# has received this recently), and `out` is a 
reference with the intention to write.


100% agreed.

I always found "in" to be consistent with what I view as one of 
D's core philosophies, that the simple thing should be the right 
thing.  For example, when you have a class parameter, it is 
automatically passed by reference without any other special 
considerations by the programmer.


To me, "in" has been a shorthand to communicate my desire to make 
sure that the parameter is treated strictly as an input, and not 
modified in any way or having ways to pass its reference to 
others who may then modify it.


Where I may be doing something wrong, a helpful message from the 
compiler is welcome.


Re: Clash When Using Function as Template Value-Parameters?

2018-05-30 Thread Vijay Nayar via Digitalmars-d

On Tuesday, 29 May 2018 at 19:17:37 UTC, Vijay Nayar wrote:

On Tuesday, 29 May 2018 at 12:58:20 UTC, Yuxuan Shui wrote:


[...]


I tried this again, this time completely ignoring lambdas and 
completely specifying the desired type like so:


[...]


Issue created:  https://issues.dlang.org/show_bug.cgi?id=18917


Re: Clash When Using Function as Template Value-Parameters?

2018-05-29 Thread Vijay Nayar via Digitalmars-d

On Tuesday, 29 May 2018 at 12:58:20 UTC, Yuxuan Shui wrote:

I believe that is the case. Normally that will be fine, because 
you can't modify them. Type-deduced lambda is a very special 
case, as in their parameter types are deduced on first use, so 
in a sense, they are "modified" by the first instantiation.


BTW, I can't find the documentation about defining lambda with 
their parameter types omitted anywhere.


I tried this again, this time completely ignoring lambdas and 
completely specifying the desired type like so:


final class BTree(
ValueT,
KeyT = ValueT,
const(KeyT) function(ValueT) nothrow pure @nogc KeyF =
function KeyT(ValueT a) { return a; }) {

  KeyT getKey(ValueT val) {
return KeyF(val);
  }
}

But unfortunately, the following code still produces an error:

void main()
{
auto btree1 = new BTree!(char);
auto btree2 = new BTree!(int);  // The error is on this line.
}

onlineapp.d(17): Error: template instance `BTree!int` does not 
match template declaration `BTree(ValueT, KeyT = ValueT, 
const(char) function(char) pure nothrow @nogc KeyF = function 
KeyT(ValueT a)

{
return a;
}
)`

I think at this point this may be a bug in the compiler.  What do 
you think?




Re: Clash When Using Function as Template Value-Parameters?

2018-05-29 Thread Vijay Nayar via Digitalmars-d

On Tuesday, 29 May 2018 at 11:36:11 UTC, Yuxuan Shui wrote:


No, wait a second. (a)=>a is in default argument list, so it is 
in the global scope. And it was instantiated when you 
instantiate BTree with char.


Could you explain that part a bit for me?  Yes, (a) => a is a 
default value, but when you say it is in the global scope, are 
you saying that a single object "(a) => a" is created in the 
global scope and not created for each template argument list, 
e.g. "BTree!int" and "BTree!char"?


I actually do not know in what scope such objects would be 
created, I had assumed it was per template-parameter list, but 
are you saying this is not the case?


Re: Clash When Using Function as Template Value-Parameters?

2018-05-28 Thread Vijay Nayar via Digitalmars-d

On Sunday, 27 May 2018 at 20:38:25 UTC, Daniel Kozak wrote:

I would rewrite it to something like this:

template BTree(ValueT, KeyT = ValueT,alias KeyF = 
unaryFun!"cast(const)a")

{
class BTree
{


This is roughly what I originally had, but it creates a number of 
problems that I wanted to get around.  Changing KeyF back to an 
alias means that any function that uses it can no longer be 
const, pure, @nogc, or nothrow.  Essentially the parameter is 
just anything the user provides.


If I use a template value-parameter, then it forces any lambda 
the user passes in to either match the type I enter in (with 
const, pure, etc.) or the program to fail to compile.  That is, I 
don't want the user to pass in any function, but only functions 
with the desired attributes.  I.e., I wouldn't want them to pass 
in for KeyF something like "a.data--".


Listing out the full type does indeed work correctly with various 
examples, and letting the user pass in something like `a => 
a._id` does compile, but the only problem is that when there are 
two such template instances in the same program.


Logically `BTree!(MyStruct, int, a => a.id)`, 
`BTree!(AnotherStruct, char, a => a.name[0])`, `BTree!int` and 
`BTree!char` should all be totally independent.  But for reasons 
unknown, the individual parameters seems to be swapped and and 
confused during compilation.


In the error above I listed.  The function parameter from 
`BTree!char` is being used to create a compile error against 
`BTree!int`, which is very odd.  Each of these classes compile 
and run just fine individually, the compilation only breaks when 
both exist.





Re: Friends in D, a new idiom?

2018-05-27 Thread Vijay Nayar via Digitalmars-d
On Sunday, 27 May 2018 at 06:37:56 UTC, IntegratedDimensions 
wrote:


I'm looking for something lightweight and direct. It is not for 
total encapsulation control but to simply provide an extra 
level of indirection for write access to make the object look 
read only to those that directly use it.


I think const is something that may be helpful then. If applied 
consistently, especially with methods, it can also protect you 
from accidentally making mutations in functions where were 
originally intended to be read-only.  Having an object "look" 
read-only is more of a stylistic thing based on conventions about 
method naming, etc. Personally I lean towards having the compiler 
enforce it.


Re: Clash When Using Function as Template Value-Parameters?

2018-05-27 Thread Vijay Nayar via Digitalmars-d

On Saturday, 26 May 2018 at 11:56:30 UTC, Vijay Nayar wrote:

The error is:
```
onlineapp.d(8): Error: function literal `__lambda6(char a)` is 
not callable using argument types `(int)`
onlineapp.d(8):cannot pass argument `val` of type `int` 
to parameter `char a`
onlineapp.d(15): Error: template instance 
`onlineapp.BTree!(int, int, function (char a) => a)` error 
instantiating

```


Just to clarify.  In the example above, if I create a 'BTree!int' 
by itself, it's fine.  If I create a 'BTree!char' by itself, it's 
fine also.  But if I create both, even if they are created in 
different modules, the compiler seems to mix up the types of the 
function template-parameter, and tries to fit a 'char' to the 
'int' function or an 'int' to the 'char' function, depending on 
which was declared first.


Re: General problem I'm having in D with the type system

2018-05-27 Thread Vijay Nayar via Digitalmars-d
On Sunday, 27 May 2018 at 06:00:30 UTC, IntegratedDimensions 
wrote:



The problem description is not very clear, but the catfood 
example gives a bit more to work with.



animal  ->   food
  ||
  vv
cat ->   catfood


Of course, I'm not sure how to avoid the problem in D of


animal a = new cat();

a.f = new food()
auto c = cast(cat)a;


Cast operations are generally not guaranteed to preserve type 
safety and should be avoided when possible.  But if I understand 
your description, you have the following relations and 
transitions:


  animal owns food
  catowns catfood
  animal may be treated as a cat (hence the casting)
  food may be treated as a catfood (hence the casting)

It may be that the inheritance relationship is backwards in your 
use case.  If "animal" may be treated as a "cat", then the 
inheritance should be other other way around, and "animal" would 
inherit from "cat".


What specific kinds of relationships are you trying to model 
among what kinds of entities?




Re: Friends in D, a new idiom?

2018-05-27 Thread Vijay Nayar via Digitalmars-d
On Sunday, 27 May 2018 at 05:25:53 UTC, IntegratedDimensions 
wrote:



Re: Friends in D, a new idiom?


In D, there's no exact equivalent to friend, but there are a few 
more specialized tools at your disposal. Normally all code in the 
same module is essentially a friend, so if the classes you are 
dealing with are tightly coupled, they can simply be in the same 
module.


For example:

module m;

class C {
  // This is still visible in the same module.
  // See https://dlang.org/spec/attribute.html#VisibilityAttribute
  private int data;
  ...
}

class CAccessor {
  C _this;
  this(C c) {
_this = c;
  }
  @property void data(int v) {
_this.data = v;
  }
  ...
}

Initially I thought nested classes contained an inherent super 
but I guess that is not the case?


Super is for inheritance rather than inner classes. So another 
way to tackle your problem using super would be this:


class C {
  protected int _data;
  @property int data() {
return _data;
  }
}

class CAccessor : C {
  @property void data(int v) {
_data = v;
  }
  C toC() {
return this;
  }
}

I also imagine that one could enhance this so that write access 
could also be allowed by certain types.


The 'package' visibility attribute can also be given a parameter 
if you need to limit access only to certain module.


Any ideas about this type of pattern, how to make it better, 
already exists etc?


You might be looking for the "Builder Pattern" which uses a 
separate object to construct and modify objects, and then it 
creates a read-only object with those values upon request.


Also, I would recommend using "const" to control access as well.  
Setter methods will not be const, but getters will be.  Those 
that have a `const(C)` reference will only be able to read, and 
those with a `C` will be able to call all methods.


For example:

class C {
  private int _data;
  @property int data() const { return _data; }
  @property void data(int v) { _data = v; }
}

void main() {
  C a = new C();
  const(C) b = a;

  a.data(3);
  a.data();
  b.data();
  // b.data(4);  Compile error.
}


Clash When Using Function as Template Value-Parameters?

2018-05-26 Thread Vijay Nayar via Digitalmars-d
I've been experimenting with code that uses std.functional : 
binaryFun and unaryFun, but I have found that using these methods 
makes it impossible to add function attributes like @safe, @nogc, 
pure, and nothrow, because no guarantee can be made about the 
functions created via a stream.  For example, if you expect a 
comparator function like "a == b", someone can pass in "a.data--" 
instead.


That being said, I started trying out using strongly typed and 
attributed template parameters instead, relying on lambdas to 
keep the syntax for the user short. But when I tried this, I 
found that the very existence of templates with different 
parameter values causes a collision during compilation.


The following code snippet demonstrates the error:

```
import std.stdio;

final class BTree(
ValueT, KeyT = ValueT,
	const(KeyT) function(ValueT) @safe @nogc nothrow pure KeyF = (a) 
=> a) {


KeyT getKey(ValueT val) {
return KeyF(val);
}
}

void main()
{
auto btree1 = new BTree!(char);  // Removing this line 
eliminates the error.

auto btree2 = new BTree!(int);
}
```

The error is:
```
onlineapp.d(8): Error: function literal `__lambda6(char a)` is 
not callable using argument types `(int)`
onlineapp.d(8):cannot pass argument `val` of type `int` 
to parameter `char a`
onlineapp.d(15): Error: template instance `onlineapp.BTree!(int, 
int, function (char a) => a)` error instantiating

```

Is this an error in the compiler or in my own understanding of 
the D language?


Bug?: Presence of "init()" Method Causes std.array.appender to Fail to Compile

2018-05-13 Thread Vijay Nayar via Digitalmars-d
I encountered a very unexpected error when working on a project.  
It seems that the Appender and RefAppender structs created from 
the std.array.appender() method are sensitive to the mere 
presence of a method called "init()" on the element type of the 
array.


Here is a minimal example:

```
import std.array;

struct S1 {
  // The mere presence of this method causes the error, deleting 
it fixes the error.

  void init(string p1, int p2, int p3) { }
}

struct S2 {
  S1[] a;
  RefAppender!(int[]) getAppender() {
return appender();
  }
}

void main() { }
```

The compiler produces the following output:
```
/dlang/dmd/linux/bin64/../../src/phobos/std/array.d(2907): Error: 
cannot have array of `void(string, int, int)`
/dlang/dmd/linux/bin64/../../src/phobos/std/array.d(2976): Error: 
cannot have array of `inout void(string, int, int)`
/dlang/dmd/linux/bin64/../../src/phobos/std/array.d(3369): Error: 
template instance `std.array.Appender!(S1[])` error instantiating
/dlang/dmd/linux/bin64/../../src/phobos/std/array.d(3879):
instantiated from here: `RefAppender!(S1[])`
onlineapp.d(12):instantiated from here: `appender!(S1[]*, 
S1)`
/dlang/dmd/linux/bin64/../../src/phobos/std/array.d(3429): Error: 
cannot have array of `inout void(string, int, int)`

```

Is this a bug or a misunderstanding on my part?


Should 'in' Imply 'ref' as Well for Value Types?

2018-05-04 Thread Vijay Nayar via Digitalmars-d
While working on a library built for high efficiency, avoiding 
unnecessary copies of structs became an issue.  I had assumed 
that `in` was doing this, but a bit of experimentation revealed 
that it does not.  However, `ref in` works great.


My question is, should `in` by default also imply `ref` for value 
types like structs?  Is there a reason not to do this?


This is the test program I used for reference:

```
import std.stdio;

struct Bob {
int a;
this(this) {
  writeln("");
}
}

void main()
{
Bob b = Bob(3);
writeln(" = ", );
void showAddrIn(in Bob b) {
writeln("(showAddrIn) = ", );
}
showAddrIn(b);
void showAddrRefIn(ref in Bob b) {
writeln("(showAddrRefIn)  = ", );
}
showAddrRefIn(b);
}
```

The output is as follows:

```
 = 7FFD9F526AD0

(showAddrIn) = 7FFD9F526AB0
(showAddrRefIn)  = 7FFD9F526AD0
```


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?


  1   2   >