Template shenannigans with multiple datatypes

2022-05-12 Thread Chris Katko via Digitalmars-d-learn
I have an intrinsicGraph(T) class that is given a pointer to a T 
dataSource and automatically polls that variable every frame to 
add it to the graph, whether it's a float, double, integer, and 
maybe bool.


This all works fine if you have a single template type. But what 
if I want ... multiple graphs? I cannot do

D
class intrinsicGraph(T???)
{
(void*) dataSources[];
}

and have it become whatever datatype I want. Even if I'm always 
storing the values in a float buffer, the dataSources themselves 
cannot be multiple types.


Basically I'm wondering if there's a way to have
D
int FPS;
float frameTime;
//
graph myGraph;
myGraph.add(&frameTime);
myGraph.add(&fps);

and it enumerates through its dataSources array and adds to the 
relevant buffers.


There is a key that might help, they're all types that can 
resolve to integer or float. I'm not trying to add support for 
adding myRandomClass or networkPacket. Only things that can 
resolve down to float in some form.


Is there some kind of clue in having an array of Object (the 
fundamental superclass?)?


I don't think this is necessarily a "run time" reflection 
problem. Because I could make a graph at compile time, and know 
its of type, say, (T V U). Say, float, double, uint. Some sort of 
vardiac template.


But then how would you store that, unless you use some sort of 
mixins to write separate variables. (float\* dataSource0 and 
double\* dataSource1)


Or, wrap each pointer in some sort of fat pointer class that 
stores the type and a void*, and have an array of those fat 
pointers and and use some compile time voodoo to cast back  
cast(float)dataSource[0] (zero is always float), 
cast(uint)dataSource[2] (index 2 has cast(uint) put in).


Additional questions:

This may sound strange but is there a way to avoid having to 
specify the template type twice?

```D
instrinsicGraph!float testGraph;
instrinsicGraph!ulong testGraph2;
// later
testGraph = new intrinsic_graph!float(units[0].x, 100, 300, 
COLOR(1,0,0,1));
testGraph2 = new intrinsic_graph!ulong(g.stats.fps, 100, 500, 
COLOR(1,0,0,1));

```
It'd be nice if I only had to specify the type once.

It'd also be kinda nice if I could hide the fact I need to 
specify the type at all and have it automatically become whatever 
type the passed in value is:


D
instrinsicGraph testGraph(g.stats.fps) //automatically stores an 
integer buffer.







Re: Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread rikki cattermole via Digitalmars-d-learn



On 13/05/2022 6:23 PM, MichaelBi wrote:

     render!("index.dt", showData());


There ya go, template arguments are run at compile time.


Re: Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread MichaelBi via Digitalmars-d-learn

On Friday, 13 May 2022 at 06:12:01 UTC, rikki cattermole wrote:


Okay that is fine, now we need to see where showData is being 
called.


thanks, here's the code:

import vibe.vibe;
import std.process;
import std.conv : to;

void main()
{
auto settings = new HTTPServerSettings;
settings.port = 8080;
settings.bindAddresses = ["0.0.0.0"];
readOption("port|p", &settings.port, "Sets the port used 
for serving HTTP.");
readOption("bind-address|bind", 
&settings.bindAddresses[0], "Sets the address used for serving 
HTTP.");

auto router = new URLRouter;
router.get("*", serveStaticFiles("public/"));
router.registerWebInterface(new ContentController);
auto listener = listenHTTP(settings, router);

scope (exit)
{
listener.stopListening();
}

runApplication();
}

class ContentController
{
void index()
{
render!("index.dt", showData());
}
}

struct Camera{
	@name("_id") BsonObjectID id; // represented as "_id" in the 
database

string brand;
string model;
}

Camera[] showData(){
auto uri = environment.get("MONGODB_URI");
MongoClient conn = connectMongoDB(uri);
MongoDatabase eqpdb = conn.getDatabase("MbEqpHeroku");
MongoCollection cameras = eqpdb["cameras"];
Camera[] cs;
auto results = cameras.find();
foreach(rec;results) cs ~= deserializeBson!Camera(rec);
return cs;
}


Re: Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread rikki cattermole via Digitalmars-d-learn



Okay that is fine, now we need to see where showData is being called.


Re: Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread MichaelBi via Digitalmars-d-learn

On Friday, 13 May 2022 at 06:01:29 UTC, rikki cattermole wrote:


On 13/05/2022 5:52 PM, MichaelBi wrote:

struct Camera{
 @name("_id") BsonObjectID id; // represented as "_id" in 
the database

 string brand;
 string model;
}

the structure is mapping of database field structure. how to 
resolve?


That code isn't the cause of your issue (its fine, no CTFE 
needed).


We would need see more of your code surrounding:

auto uri = environment.get("MONGODB_URI");
MongoClient conn = connectMongoDB(uri);
MongoDatabase eqpdb = conn.getDatabase("MbEqpHeroku");


here is the code:

Camera[] showData(){
auto uri = environment.get("MONGODB_URI");
MongoClient conn = connectMongoDB(uri);
MongoDatabase eqpdb = conn.getDatabase("MbEqpHeroku");
MongoCollection cameras = eqpdb["cameras"];
Camera[] cs;
auto results = cameras.find();
foreach(rec;results) cs ~= deserializeBson!Camera(rec);
return cs;
}




Re: Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread rikki cattermole via Digitalmars-d-learn



On 13/05/2022 5:52 PM, MichaelBi wrote:

struct Camera{
 @name("_id") BsonObjectID id; // represented as "_id" in the database
 string brand;
 string model;
}

the structure is mapping of database field structure. how to resolve?


That code isn't the cause of your issue (its fine, no CTFE needed).

We would need see more of your code surrounding:

auto uri = environment.get("MONGODB_URI");
MongoClient conn = connectMongoDB(uri);
MongoDatabase eqpdb = conn.getDatabase("MbEqpHeroku");


Re: Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread MichaelBi via Digitalmars-d-learn

On Friday, 13 May 2022 at 05:41:33 UTC, rikki cattermole wrote:

On 13/05/2022 5:18 PM, MichaelBi wrote:

     i have code here:
     auto uri = environment.get("MONGODB_URI");
     MongoClient conn = connectMongoDB(uri);
     MongoDatabase eqpdb = conn.getDatabase("MbEqpHeroku");

the "MONGODB_URI" showed above already put into heroku's app 
config as the 'key' and there is a paired 'value'. so the uri 
is to extract the value which is to use for app to establish 
mongodb connection.


and above code with error msg here: Error: `getenv` cannot be 
interpreted at compile time, because it has no available 
source code


That part of the code is probably fine.

Basically you have to be careful that:

auto uri = environment.get("MONGODB_URI");

Isn't being executed during compilation.

Stuff that typically cause this is anything that initializes a 
variable.


Globals:

shared Foo foo = Foo(...);

Class fields:

class Foo {
Bar bar = Bar(...);
}


yes, then should be this?

struct Camera{
	@name("_id") BsonObjectID id; // represented as "_id" in the 
database

string brand;
string model;
}

the structure is mapping of database field structure. how to 
resolve?


Re: Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread rikki cattermole via Digitalmars-d-learn

On 13/05/2022 5:18 PM, MichaelBi wrote:

     i have code here:
     auto uri = environment.get("MONGODB_URI");
     MongoClient conn = connectMongoDB(uri);
     MongoDatabase eqpdb = conn.getDatabase("MbEqpHeroku");

the "MONGODB_URI" showed above already put into heroku's app config as 
the 'key' and there is a paired 'value'. so the uri is to extract the 
value which is to use for app to establish mongodb connection.


and above code with error msg here: Error: `getenv` cannot be 
interpreted at compile time, because it has no available source code


That part of the code is probably fine.

Basically you have to be careful that:

auto uri = environment.get("MONGODB_URI");

Isn't being executed during compilation.

Stuff that typically cause this is anything that initializes a variable.

Globals:

shared Foo foo = Foo(...);

Class fields:

class Foo {
Bar bar = Bar(...);
}



Help, in vibe.d, how to get configure var of mongodb in heroku?

2022-05-12 Thread MichaelBi via Digitalmars-d-learn
there are online documents of heroku on how to access config var 
value from code, and several code samples without D. link here: 
https://devcenter.heroku.com/articles/config-vars#accessing-config-var-values-from-code.


i have code here:
auto uri = environment.get("MONGODB_URI");
MongoClient conn = connectMongoDB(uri);
MongoDatabase eqpdb = conn.getDatabase("MbEqpHeroku");

the "MONGODB_URI" showed above already put into heroku's app 
config as the 'key' and there is a paired 'value'. so the uri is 
to extract the value which is to use for app to establish  
mongodb connection.


and above code with error msg here: Error: `getenv` cannot be 
interpreted at compile time, because it has no available source 
code


so don't know how to make change. thanks in advance!


Re: Back to Basics at DConf?

2022-05-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Friday, 13 May 2022 at 04:39:46 UTC, Tejas wrote:
On Friday, 13 May 2022 at 04:19:26 UTC, Ola Fosheim Grøstad 
wrote:

On Friday, 13 May 2022 at 03:31:53 UTC, Ali Çehreli wrote:

On 5/12/22 18:56, forkit wrote:

> So...you want to do a talk that challenges D's complexity, 
> by

getting
> back to basics?

I wasn't thinking about challenging complexity but it gives 
me ideas.


I am looking for concrete topics like templates, classes, 
ranges, rvalues, etc. Are those interesting?


I suggest: patterns for @nogc allocation and where D is going 
with move semantics and reference counting.


Basically, where is D heading with @nogc?

Take each pattern from c++ and Rust and show the D counter 
part, with an objective analysis that covers pitfalls and 
areas that need more work.


I feel that it'd be best if any video discussion/talk about 
move semantics happens _after_ [DIP 
1040](https://github.com/dlang/DIPs/blob/72f41cffe68ff1f2d4c033b5728ef37e282461dd/DIPs/DIP1040.md#initialization) is merged/rejected, so that the video doesn't become irrelevan after only a few years.


I think the purpose of conferences is to assess the current state 
and be forward looking. After 14 months I would expect Walter to 
know if it is going to be put to rest or not, so just email him I 
guess?




Re: Back to Basics at DConf?

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/12/22 21:41, Tejas wrote:

> Or a presentation on ranges can also be good, considering how the de
> facto best online article on it(by HS Teoh) is from 2013

I think the best person to give that presentation would be its awesome 
author. ;)


Ali



Re: Back to Basics at DConf?

2022-05-12 Thread Tejas via Digitalmars-d-learn

On Friday, 13 May 2022 at 03:31:53 UTC, Ali Çehreli wrote:

On 5/12/22 18:56, forkit wrote:

> So...you want to do a talk that challenges D's complexity, by
getting
> back to basics?

I wasn't thinking about challenging complexity but it gives me 
ideas.


I am looking for concrete topics like templates, classes, 
ranges, rvalues, etc. Are those interesting?


Ali


DIP 1000 would be a good start :P

Or a presentation on ranges can also be good, considering how the 
de facto best online article on it(by HS Teoh) is from 2013


Re: Back to Basics at DConf?

2022-05-12 Thread Tejas via Digitalmars-d-learn

On Friday, 13 May 2022 at 04:19:26 UTC, Ola Fosheim Grøstad wrote:

On Friday, 13 May 2022 at 03:31:53 UTC, Ali Çehreli wrote:

On 5/12/22 18:56, forkit wrote:

> So...you want to do a talk that challenges D's complexity, by
getting
> back to basics?

I wasn't thinking about challenging complexity but it gives me 
ideas.


I am looking for concrete topics like templates, classes, 
ranges, rvalues, etc. Are those interesting?


I suggest: patterns for @nogc allocation and where D is going 
with move semantics and reference counting.


Basically, where is D heading with @nogc?

Take each pattern from c++ and Rust and show the D counter 
part, with an objective analysis that covers pitfalls and areas 
that need more work.


I feel that it'd be best if any video discussion/talk about move 
semantics happens _after_ [DIP 
1040](https://github.com/dlang/DIPs/blob/72f41cffe68ff1f2d4c033b5728ef37e282461dd/DIPs/DIP1040.md#initialization) is merged/rejected, so that the video doesn't become irrelevan after only a few years.


Re: Back to Basics at DConf?

2022-05-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Friday, 13 May 2022 at 03:31:53 UTC, Ali Çehreli wrote:

On 5/12/22 18:56, forkit wrote:

> So...you want to do a talk that challenges D's complexity, by
getting
> back to basics?

I wasn't thinking about challenging complexity but it gives me 
ideas.


I am looking for concrete topics like templates, classes, 
ranges, rvalues, etc. Are those interesting?


I suggest: patterns for @nogc allocation and where D is going 
with move semantics and reference counting.


Basically, where is D heading with @nogc?

Take each pattern from c++ and Rust and show the D counter part, 
with an objective analysis that covers pitfalls and areas that 
need more work.





Re: What are (were) the most difficult parts of D?

2022-05-12 Thread zjh via Digitalmars-d-learn

On Thursday, 12 May 2022 at 20:49:08 UTC, Chris Katko wrote:

In D, I can do the module based method, but nothing short of 
renaming variables gives me a list of violations and, that also 
makes all the correct internal accesses wrong. Because private 
doesn't work.


Call it whatever keyword you want, I really want a 'private' 
specifier for classes. It's incredibly useful.


We can really add a keyword such as `secret`. `Good idea`.



Re: Back to Basics at DConf?

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/12/22 18:56, forkit wrote:

> So...you want to do a talk that challenges D's complexity, by getting
> back to basics?

I wasn't thinking about challenging complexity but it gives me ideas.

I am looking for concrete topics like templates, classes, ranges, 
rvalues, etc. Are those interesting?


Ali



Re: Back to Basics at DConf?

2022-05-12 Thread Salih Dincer via Digitalmars-d-learn

On Thursday, 12 May 2022 at 21:58:33 UTC, Ali Çehreli wrote:

I am considering proposing a presentation for DConf 2022.

Would a "Back to Basics" style presentation be interesting? If, 
so what exact topic would you like to see?




There was a book from my childhood. Its name is "Temel Basic", 
here it is 
https://www.nadirkitap.com/temel-basic-guzin-sagkan-tunc-gercek-kitap10256791.html


The interesting thing is that the meaning of the Turkish word 
(Temel) and the name of the language (Basic) are the same. In 
other words, one is Turkish, the other is English, but in the 
same place and in a different sense.


In summary, the basics are good. I don't like dependence at all. 
Simple things are beautiful...:)


SDB@79



Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Salih Dincer via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


The concept of traits (std.traits) confuses me enough. Actually 
the problem is that the interface is disorderly (disorganizedly). 
As if it was very difficult to establish a hierarchical system...


Also, multitasking is like that, it's disorganizedly: 
taskPool.parallel(std.parallelism), yield(std.concurrency), 
ThreadGroup(core.thread)...etc(pufff!)


SDB@79


Re: Back to Basics at DConf?

2022-05-12 Thread forkit via Digitalmars-d-learn

On Thursday, 12 May 2022 at 21:58:33 UTC, Ali Çehreli wrote:

I am considering proposing a presentation for DConf 2022.

Would a "Back to Basics" style presentation be interesting? If, 
so what exact topic would you like to see?


For ideas, here is what CppCon 2021 had on their track:

  https://cppcon2021.sched.com/?searchstring=Back+to+Basics

Ali


So...you want to do a talk that challenges D's complexity, by 
getting back to basics?


I'm afraid the ship has sailed :-(



Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Guillaume Piolat via Digitalmars-d-learn

On Thursday, 12 May 2022 at 17:34:30 UTC, H. S. Teoh wrote:


Why is TLS by default a problem?

It's not really for optimization, AIUI, it's more for thread 
safety: module-global state is TLS by default, so you don't 
accidentally introduce race conditions.


What you accidentally have instead is people expecting top-level 
to be global

and instead you get TLS, so it's a surprise.
I mean, a lot of things works like C and C++, but not that.

It's a problem because it goes from solving "no accidental race 
condition" and you get "people forget to add shared or __gshared 
and their shared library silently fail" situation. You could have 
none of that with explicit TLS.


- `shared static this()` vs `static this()` is another 
trap.


One is per-process, one is per-thread.  Why is this a trap?


Well because you can get that wrong.
You get to initialize "__gshared" variables in "shared static 
this".

It's not hard, but it's something more to explain.


I wouldn't sweat it if I couldn't easily add `pure` to an 
entire codebase -- it hardly makes any difference anyway.


If it doesn't make a difference to the bottom-line then why keep 
it?



you're on your own and you take responsibility for any problems 
that you may inadvertently introduce by using the escape hatch.


Well sizeable @afe code has heaps of @trusted code, so the escape 
hatch is very routine.




it's none of the users' business.


I'm not disagreeing about @trusted in API.
But I was remarking in practice that @safe would mean different 
invariants.

it's not a big issue, I was probably ranting.

IOW, public APIs should always be @safe or @system. @trusted 
should only appear on internal APIs.


Good rule to follow, TIL.


So I'm curious, what exactly is it about UFCS chains that make 
it less maintainable?


Probably personal preference, I mostly write the pedestrian way, 
so that debugging/optimization goes faster (maybe wrong, dunno).


In the dlang.org example:

void main()
{
stdin
.byLineCopy
.array
.sort!((a, b) => a > b) // descending order
.each!writeln;
}

This code has a number of prerequisites to be able to read: why 
is ".array" needed, why is it ".byLineCopy" vs ".byLine", is the 
sort stable, etc. It's just requires more time spent with the 
language.




Back to Basics at DConf?

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

I am considering proposing a presentation for DConf 2022.

Would a "Back to Basics" style presentation be interesting? If, so what 
exact topic would you like to see?


For ideas, here is what CppCon 2021 had on their track:

  https://cppcon2021.sched.com/?searchstring=Back+to+Basics

Ali


Re: Creating a custom iota()

2022-05-12 Thread realhet via Digitalmars-d-learn

On Thursday, 12 May 2022 at 20:12:19 UTC, Ali Çehreli wrote:
And I've been thinking 'iota' may not be as suitable as I 
thought at first. I like the following even more:


  auto r0 = st
.by(Duration(2))
.take(5);


So I wrote this by() for my DateTime and then:

import quantities.si;

auto by(in DateTime begin, in Frequency f){
  return begin.by(1/f);
}

//This let me do:

now.by(60*hertz)
   .until!"a>b"(now+1*second)
   .each!writeln;

My mind is blowing! :D



Re: Creating a custom iota()

2022-05-12 Thread realhet via Digitalmars-d-learn

On Thursday, 12 May 2022 at 17:06:39 UTC, Ali Çehreli wrote:
I don't care whether it is good practice or not. :) The 
following is what you meant anyway and seems to work.


I restricted the parameter types to the ones I wanted to use.
And for the standard iota behavior I used a public import.

public import std.range : iota;

auto iota(in DateTime begin, in DateTime end, in Time step){
  
//https://forum.dlang.org/post/ivskeghrhbuhpiyte...@forum.dlang.org -> Ali's solution


  static struct Result{
DateTime current, end;
Time step;

@property bool empty(){ return current >= end; }
@property auto front(){ return current; }
void popFront(){ assert(!empty); current += step; }
  }

  return Result(begin, end, step);
}

...

iota(st, en, day).each!writeln; //works
iota(1, 10, 0.5).each!writeln;  //also works

It works perfectly, Thank You very much!

Although that general implementation of iota is a bit complex for 
me, this specialized one is simple.


note(0): no cast() was needed here, worked with a const DateTime{ 
ulong ticks; ... }


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Chris Katko via Digitalmars-d-learn

On Thursday, 12 May 2022 at 16:04:09 UTC, Ali Çehreli wrote:
My view on private has changed over the years. I need to be 
convinced that there is usage that needs to be protected. :) I 
don't see people using types freely especially the ones that 
are in the same module. The only argument for private is to 
allow changing the implementation of published libraries in the 
future.


I use private as part of my rapid dev process. You write code, 
you get things working with no real worry for correctness or 
careful interfaces. You cannot make an interface until you 
actually know what you're making.


So you make things, with "bad" connections. Then you remove those 
connections.


1. Get system working with lots of direct access to class 
variables.

2. Make those variables forbidden (through private in C++).
3. The compiler now shows you every instance of your new 
interface encapsulation violations. No human decision to opt-in. 
No remembering to search. You have an automatically generated 
list of violations to fix.


I do the same thing with a module called "g" (for globals). I 
write new code into g, get it working. I can see how "dirty" a 
file is by simply searching for how many references to the module 
g there are. Then if I move the code into a proper new module, 
all references to g magically fail. It is impossible for me to 
leave dangling old code touching naughty internals, and I get a 
nice error view of all areas that need attention. If the uses are 
all over the place and not in only a few areas (instead of just 
in logic() and draw(), but all over the place) then I know I need 
to rewrite and introduce a system so everything is mostly in one 
place.


In D, I can do the module based method, but nothing short of 
renaming variables gives me a list of violations and, that also 
makes all the correct internal accesses wrong. Because private 
doesn't work.


Call it whatever keyword you want, I really want a 'private' 
specifier for classes. It's incredibly useful.


Re: Creating a custom iota()

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/12/22 12:51, ag0aep6g wrote:

>> auto iota(B, E, S)(B begin, E end, S step)
> [...]
>> {
>> static struct Result
>> {
>> B current;
> [...]
>> void popFront()
>> {
> [...]
>> current += step;
>> }
>> }
> [...]
>> }
>
> Mark iota's `begin` parameter as const. Then you don't need the cast,
> because `B` will be mutable.

Cool trick! Like this:

auto iota(B, E, S)(const(B) begin, E end, S step)
{
  // ...
}

It works with non-const values as well. So apparently it makes the 
function parameter const(B) and deduces B to be the non-const version of 
that, which always produces the non-const version.


And I've been thinking 'iota' may not be as suitable as I thought at 
first. I like the following even more:


  auto r0 = st
.by(Duration(2))
.take(5);

  auto r1 = st
.by(Duration(2))
.until(en);

A family of 'by' ovenloads can be defined or it can be templatized to be 
used as 'by!Duration(2)' etc.:


auto by(DateTime dt, Duration dur) {
  struct Result {
DateTime front;
Duration dur;

enum empty = false;
void popFront() { front += dur; }
  }

  return Result(dt, dur);
}

Just works. But one may want to provide an accessor for front().

Ali



Re: Creating a custom iota()

2022-05-12 Thread realhet via Digitalmars-d-learn

On Thursday, 12 May 2022 at 16:57:35 UTC, H. S. Teoh wrote:


Does your DateTime type support the `++` operator?


It can't because I only want to use the quantities.si.Time type 
to do arithmetic with my DateTime. In my previous DateTime, it 
was a lot of problem that I was doing math on it's raw internal 
variable (which was a double where 1.0 meant 1 day.)

In the new version adding int(1) does a compilation error.
I will use 1*second or 1*day or 1*micro(second) instead. I will 
always state the measurement unit to avoid confusions.




But I'm curious, why didn't you use std.datetime?


There are many weird reasons:
5 years ago I moved to DLang from Delphi. Since 20 years I always 
used the old  Borland date system whist stards in 1899, is an 
ieee double, 1 = 1 day. I only did stuff with local times, it was 
enough.
Recently I had to work with Python as well, and there I started 
to have problems with time synchronizations between the 2 
systems. I ended up sending the exact Borland time to the Python 
program and make my little routines to work with them exactly 
like I do 20 years ago in Delphi, 5 years ago in DLang. But I 
know it is not nice.
So a week ago I discovered the quantities package and I decided 
to rewrite my DateTime to use the Time type in that. It solves 
all my measurement unit madness in a very elegant way. So I also 
want those measurement units working in all my systems. (I have 
lengths, frequencies too)
For me std.datetime was not an option because that felt so big I 
scared of it at the first look. It's 1.5MB, the same size as my 
complete program I'm working on :D
I also hade a second based time measurement 'system', it used 
QueryPerformanceCounter. I want do discontinue that as well.


So these are the features of the new DateTime:
- small size: 64 uint is the internal format. (Half of 
std.systemtime, but it lacks timezone, it's only UTC internally).
- precise: 100.0/64 nanosecond is the smallest unit. It covers 
913 years.
- It was built around the new WinAPI 
GetSystemTimePreciseAsFileTime() It gives me 100ns resolution UTC 
time in less than 50ns. So that's why I don't need 
QueryPerformanceCounter anymore.
- The extra 6 bits under the 100ns ticks will be used for time 
based unique ID generation.  It's better for me than having 6 
years at my hand.
- The integration with quantities.si makes my work much easier. I 
can't wait to use it in my program, as I knows physics things 
better than me, haha.




std.range.recurrence.


Indeed, that's an option as well, I forgot about.

Thank You!





Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/12/22 12:00, Paul Backus wrote:

> Good news: starting from DMD 2.099, this error message has been
> reworded. Instead of "cannot deduce function...". it now says:
>
> Error: none of the overloads of template `std.algorithm.iteration.sum`
> are callable using argument types `!()(int[3])`

Much better.

An idea: The compiler should be able to detect static arrays and also 
suggest slicing with something like "slicing as in `arr[]` might work".


Ali



Re: Creating a custom iota()

2022-05-12 Thread ag0aep6g via Digitalmars-d-learn

On Thursday, 12 May 2022 at 17:06:39 UTC, Ali Çehreli wrote:

void main() {
  const st = DateTime(Duration(0));

[...]


  // (0) I think D should not insist on 'const'
  // when copying types that have no indirections.
  // We shouldn't need the cast() below in this case.

[...]

  iota(cast()st, en, step).each!writeln;
}


[...]

auto iota(B, E, S)(B begin, E end, S step)

[...]

{
static struct Result
{
B current;

[...]

void popFront()
{

[...]

current += step;
}
}

[...]

}


Mark iota's `begin` parameter as const. Then you don't need the 
cast, because `B` will be mutable.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Anonymouse via Digitalmars-d-learn

On Thursday, 12 May 2022 at 15:17:10 UTC, Adam D Ruppe wrote:
It is simpler than it looks, I wrote about it in my book and in 
a post here:


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


"Then commas separate the definitions of each placeholder 
variable, just as if they  were template argument definitions 
[...]"


That... makes sense, I didn't think of them like that.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Anonymouse via Digitalmars-d-learn

On Thursday, 12 May 2022 at 16:48:05 UTC, H. S. Teoh wrote:
static foreach isn't meant to handle large loops. Writing 
`static foreach (i; 0 .. 6)` is generally a bad idea; my 
suspicion is that the compiler ran out of stack space).  It's 
more for unfolding groups of statements or declarations like 
cases in a switch-statement.


I understand, but I don't think I had any static foreaches in my 
code at the time. My case was more comment #10.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 12 May 2022 at 18:07:05 UTC, H. S. Teoh wrote:
On Thu, May 12, 2022 at 09:04:09AM -0700, Ali Çehreli via 
Digitalmars-d-learn wrote:
Error: template `std.algorithm.iteration.sum` cannot deduce 
function from

argument types `!()(int[3])`
/usr/include/dlang/dmd/std/algorithm/iteration.d(7234): 
Candidates are:

`sum(R)(R r)`
  with `R = int[3]`
  must satisfy the following constraint:
`   isInputRange!R`

WHAT? :) But the clue is on the last line above.

[...]

Seriously though, that error message is horrendously ugly.  I 
mean I've seen it thousands of times by now, so I know what it 
means and where to look for the actual problem. But it's 
eminently unfriendly to someone who doesn't already know the 
language very well.


Good news: starting from DMD 2.099, this error message has been 
reworded. Instead of "cannot deduce function...". it now says:


Error: none of the overloads of template 
`std.algorithm.iteration.sum` are callable using argument types 
`!()(int[3])`


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, May 12, 2022 at 09:04:09AM -0700, Ali Çehreli via Digitalmars-d-learn 
wrote:
> On 5/11/22 18:06, Christopher Katko wrote:
> 
> > Cool useful library functions like sumElement that magically don't
> > work on static arrays.
> 
> Yeah, that sometimes gets me as well. Although it is trivial to deal
> with, the programmer may be surprised by the strange error messages:
> 
>   int[3] arr = [ 1, 2, 3 ];
>   assert(sum(arr) == 6);
> 
> Error: template `std.algorithm.iteration.sum` cannot deduce function from
> argument types `!()(int[3])`
> /usr/include/dlang/dmd/std/algorithm/iteration.d(7234): Candidates are:
> `sum(R)(R r)`
>   with `R = int[3]`
>   must satisfy the following constraint:
> `   isInputRange!R`
> 
> WHAT? :) But the clue is on the last line above.
[...]

Seriously though, that error message is horrendously ugly.  I mean I've
seen it thousands of times by now, so I know what it means and where to
look for the actual problem. But it's eminently unfriendly to someone
who doesn't already know the language very well.


T

-- 
A mathematician learns more and more about less and less, until he knows 
everything about nothing; whereas a philospher learns less and less about more 
and more, until he knows nothing about everything.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, May 12, 2022 at 01:06:02AM +, Christopher Katko via 
Digitalmars-d-learn wrote:
[...]
> Cool useful library functions like sumElement that magically don't
> work on static arrays.

Just slice it with []:

int[5] data = [ 1, 2, 3, 4, 5 ];
auto sum = data[].sumElement;

The main reason is that static arrays cannot shrink (their length is
constant), so they don't qualify as ranges. No problem, [] takes a slice
of them that *can* shrink.


> 'private' is per module, not per class, making it pretty much useless
> for preventing incorrect access and using .

This is a common complaint.  But IME, I haven't really run into problems
with it.  Accessing private members really only becomes a problem when
you have multiple separate modules interacting with each other. If a
module has grown large enough that this starts becoming a problem, it's
usually a sign that it's time to refactor the module into two (or more)
smaller ones.


> completely different semantics for a class vs a struct. Is it a
> reference?  Is it a value? Look up the entire declaration and have the
> entire Dlang manual open to find out.

class == by reference
struct == by value

Very straightforward.


> As far as I remember, no automatic RAII support, even though it's
> insanely useful. You have to manually write scope(end) stuff which
> means any person forgetting one is now leaking memory.

???  Structs with dtors have RAII. You only need scope(exit) if you're
manually managing resources.

What exactly are you referring to here?


> Writing output in a deconstuctor (for learning) works. But then you
> accidentally combine two strings inside it and the garbage collecter
> crashes without a stack trace.

Yeah, class dtors and GC don't mix, in general. There was a proposal to
remove class dtors from the language some years ago. But it didn't
happen, probably because more people complained about that than about
dtors not being allowed to allocate memory or access GC'd resources. :-D


> Documentation. Documentation. Documentation.
[...]

What exactly is wrong with the docs?  A concrete list of actionable
items would be nice. (I admit the docs could use some improvements,
btw.)


T

-- 
"I'm not childish; I'm just in touch with the child within!" - RL


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, May 11, 2022 at 06:43:39PM +, Guillaume Piolat via 
Digitalmars-d-learn wrote:
> On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
> > What are you stuck at? What was the most difficult features to
> > understand? etc.
> 
> - How to do deterministic destruction with programs that use
> everything (struct / class / dynamic dispatch / GC / manual /
> etc). This requires to understand what the runtime does, what the
> gc does.

I'm not sure I fully understand what you're trying to say here. How does
GC mix with deterministic destruction?  I thought by the very nature of
GC, destruction is non-deterministic.  If you want deterministic
destruction, don't use the GC...?


>   Interesting nonetheless.
> 
> - Some traps. Accidental TLS is a thing, top-level should probably
> not be silently TLS.
>   People will loose hours on this completely preventable thing.
>   What was the idea, optimize code without people knowing?

Why is TLS by default a problem?

It's not really for optimization, AIUI, it's more for thread safety:
module-global state is TLS by default, so you don't accidentally
introduce race conditions.


> - `shared static this()` vs `static this()` is another trap.

One is per-process, one is per-thread.  Why is this a trap?


[...]
> - Some features lack an escape hatch, notably `pure`. pure leaks
> into identifiers, like `pureMalloc`. Trying to add `pure` fails on
> a large codebase.

IMNSHO, pureMalloc is a code smell. It should not have been added in the
first place.

But more to the point: pure is of limited utility. Perhaps the most
useful application is the initialization of immutable data structures
constructed by a mutable factory method. But other than that, I don't
find very much use for it in practice.  I wouldn't sweat it if I
couldn't easily add `pure` to an entire codebase -- it hardly makes any
difference anyway.


> - `@safe`/`@trusted`/`@system` is good but the definition of what
> `@trusted` means has to be remembered from the programmer.

But isn't that the nature of all escape hatches?  An escape hatch by
definition means you're operating outside of the abstractions provided
by the compiler; IOW you're on your own and you take responsibility for
any problems that you may inadvertently introduce by using the escape
hatch.


>   For example `Mutex.lock()` is `@trusted`, it could have been
>   `@system` to let user review their usage of locks. You have to
>   wonder "can a lock()/unlock() corrupt memory?". People can use
>   that to mean "@reviewed" instead. Because it is up to us, the
>   exact meaning will float in the D subcultures. A function which
>   has been marked `@trusted` does not receive any review whan
>   changed later. It will not mean the same as `@trusted` in
>   another codebase.

IMNSHO, @trusted should never be used in public-facing APIs. It's really
an implementation detail -- "this code does something using potentially
dangerous operations, but we reviewed it carefully to make sure it's
safe to call from @safe code".  The caller does NOT need to know this;
as far as the caller is concerned, it's calling a @safe function. That's
all it knows and all that it should care about. How this @safe function
is implemented -- using completely @safe operations or potentially
dangerous operations (@trusted) isn't something the user should care
about.  That's something the author of the module needs to care about,
but it's none of the users' business.

IOW, public APIs should always be @safe or @system. @trusted should only
appear on internal APIs.


> - Generic code typically has bad names (domain-less) and worse
> usability. It's often not pretty to look at. Mostly cultural,
> since D has powerful templates so they had to be everywhere. UFCS
> chains are not that convincing when you are worried about
> maintenance.

I'm puzzled by this. I use (and write!) generic code all the time and
they have been great. UFCS chains are awesome; they allow me to express
a series of data transformations in a very concise way, so that I can
keep the high-level logic of the function readable, without having to
break it into separate functions.  This, plus `auto` type inference,
makes the code *more* maintainable, IME, because I can shuffle
components of the UFCS chain around without needing to rewrite the types
of a bunch of helper functions.

So I'm curious, what exactly is it about UFCS chains that make it less
maintainable?


>   Phobos take short names for itself, this leads to pretty
>   complicated operations having a small screen estate.

I'm also puzzled by this. Why is this a problem?


> - `assert(false)` being different and not removed by `-release`.
> Keyword reuse seems entrenched but honestly a "crash here" keyword
> would be more readable.

noreturn crashHere() { assert(false); }

void main() {
  

Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Guillaume Piolat via Digitalmars-d-learn

On Thursday, 12 May 2022 at 16:24:26 UTC, Ali Çehreli wrote:


Cool trick but "parent" confused me there. I think you mean 
"base". :)


https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming

mentions "base class" as much as "parent class"


Re: Creating a custom iota()

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/12/22 04:57, realhet wrote:

> //this would be nicer, but not works
> iota(st, en, day).each!writeln;

For others, the problem is, iota does have a version that works with 
user types but not one that parameterizes 'step'. An oversight?


> My question is, is there a way to 'extend' the functionality of the
> std.iota() function or it is better to come up with a unique name for
> this special 'iota' functionality?

I think ioat can be improved to work with user 'step' types as I did below.

> Is this a good practice

I don't care whether it is good practice or not. :) The following is 
what you meant anyway and seems to work. I added 6 comments:


import std.stdio;
import std.range;
import std.algorithm;

struct Duration {
  ulong value;
}

struct DateTime {
  Duration sinceEpoch;  // Quickest implementation for this post

  auto opOpAssign(string op)(Duration dur)
  if (op == "+") {
return DateTime(Duration(sinceEpoch.value += dur.value));
  }
}

void main() {
  const st = DateTime(Duration(0));
  const en = DateTime(Duration(10));

  const step = Duration(1);

  // (0) I think D should not insist on 'const'
  // when copying types that have no indirections.
  // We shouldn't need the cast() below in this case.
  //
  // Alternatively, the implementation of iota()
  // could use Unqual after detecting B has no
  // indirections. That would be better for the
  // user but again, the language should copy
  // to non-const by-default. But then, I am
  // sure there would be cases where an unexpected
  // function overload might be selected in some
  // cases.
  iota(cast()st, en, step).each!writeln;
}

// I adapted the following template from my
// /usr/include/dlang/dmd/std/range/package.d
// and then:
//  (1) Added 'S step'
auto iota(B, E, S)(B begin, E end, S step)
// (2) Removed for now
// if (!isIntegral!(CommonType!(B, E)) &&
// !isFloatingPoint!(CommonType!(B, E)) &&
// !isPointer!(CommonType!(B, E)) &&
// is(typeof((ref B b) { ++b; })) &&
// (is(typeof(B.init < E.init)) || is(typeof(B.init == E.init))) )
{
static struct Result
{
B current;
E end;
S step;  // (3) Added

@property bool empty()
{
static if (is(typeof(B.init < E.init)))
return !(current < end);
else static if (is(typeof(B.init != E.init)))
return current == end;
else
static assert(0);
}
@property auto front() { return current; }
void popFront()
{
assert(!empty);
// (4) Used += instead of ++current
// This can be improved to use the other
// method a.l.a. "design by introspection".
current += step;
}
}
// (5) Added step
return Result(begin, end, step);
}

Ali



Re: Creating a custom iota()

2022-05-12 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, May 12, 2022 at 11:57:54AM +, realhet via Digitalmars-d-learn wrote:
[...]
> I have my own DateTime struct.
> It has opCmp() and opBinary(), I can do arithmetic with this custom
> DateTime and the amazing time units of the **quantities** package.
> 
> Now I'm about mo make iterations in a DateTime range:
> 
> const
>   st = DateTime(UTC, "22.1.1 8:30").utcDayStart,
>   en = DateTime(UTC, "22.3.5 19:56").max(now).utcDayStart +
> (100.0/64)*nano(second);
> 
> //this works
> for(auto d = cast()st; d < en; d += day) writeln(d);
> 
> //this would be nicer, but not works
> iota(st, en, day).each!writeln;
> 
> My question is, is there a way to 'extend' the functionality of the
> std.iota() function or it is better to come up with a unique name for
> this special 'iota' functionality?

Custom user types should already be supported by iota; see:

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

Does your DateTime type support the `++` operator?  If not, that's the
most likely reason iota failed to instantiate on it.  Just add
`opUnary(string op : "++")` to your type, and it should work.


[...]
> Or maybe put it inside a DateTimeRange struct, and implement the std
> range functionality?
[...]

That would work too.

But I'm curious, why didn't you use std.datetime?  The DateTime type
there supports inter-date arithmetic (as far as it makes sense), and can
be easily made into a range using std.range.recurrence.


T

-- 
When solving a problem, take care that you do not become part of the problem.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, May 12, 2022 at 02:42:43PM +, Anonymouse via Digitalmars-d-learn 
wrote:
[...]
> The one thing that has caused me most anguish and woe is hands-down
> https://issues.dlang.org/show_bug.cgi?id=18026 though. It hasn't bit
> me for a while now, but the feeling of uncertainty, that the compiler
> might just suddenly after an innocent change no longer compile your
> project, seemingly outside of your control, is just... disheartening
> when it happens.

static foreach isn't meant to handle large loops. Writing `static
foreach (i; 0 .. 6)` is generally a bad idea; my suspicion is that
the compiler ran out of stack space).  It's more for unfolding groups of
statements or declarations like cases in a switch-statement.

For complex loops, what you really want is to use CTFE, which has a
proper interpreter that can execute real code, instead of static
foreach. What I'd do in the case described in comment 20 is to use CTFE
to generate an array of indices that satisfy the predicate (it can
create this array however it wants), then static foreach over this
array, instead of iterating from 0 to 6 directly.

Or, in certain cases, you might want to just try straight foreach
instead of static foreach, just make a tuple of your indices first and
it will auto-unroll.


T

-- 
Не дорог подарок, дорога любовь.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, May 12, 2022 at 12:13:32PM +, Basile B. via Digitalmars-d-learn 
wrote:
[...]
> Problem is more (from https://dlang.org/spec/expression.html#is_expression)
> 
> ```
> is ( Type : TypeSpecialization , TemplateParameterList )
> is ( Type == TypeSpecialization , TemplateParameterList )
> is ( Type Identifier : TypeSpecialization , TemplateParameterList )
> is ( Type Identifier == TypeSpecialization , TemplateParameterList )
> ```
> 
> I never remember those variants, because basically you never need
> them...  They were required for std.traits and that's it.

Not true. I use these all the time in generic code. Basically, they
allow you to do IFTI-like template pattern-matching using static-if's.
This is eminently useful for inspecting incoming types in template
functions. For example, in serialization code, I would do something
like:

auto serialize(T)(T data) {
static if (is(T == string))
{
... // straightforward string encoding
}
else static if (is(T : U[], U))
// this means: "T matches the pattern `U[]`,
// where U is some arbitrary type"
{
... // non-string array encoding
// note that in this block, `U` is defined to be
// the array element; very convenient for
// further type dissection
}
else static if (is(T : U[V], U, V))
// this means: "T matches the pattern `U[V]`,
// where U and V are arbitrary types"
{
... // AA encoding
// similarly, in this block U is the value type
// and V is the key type, very convenient for
// further type dissection
}
else static if (is(T : MyType!(U), string U))
// this means: "T matches the pattern
// `MyType!(U)` where U is some string"
{
... // special handling for instantiations of
// MyType with string argument
// in this block, U == string
}
... // and so on
}

I concede that the documentation isn't exactly easy to understand on a
first read; it took me many tries before it "clicked".  But once you
understand the general pattern, most of the cases make sense and is
pretty predictable.

There *are* one or two special cases, granted, but those are exceptional
and there are already std.traits wrappers that expose a friendlier API.
The worst offender in this category is __parameters, about which I wrote
years ago here:

https://forum.dlang.org/thread/vpjpqfiqxkmeavtxh...@forum.dlang.org

Still, putting this ugly special case aside, the rest of is(...) syntax
mostly conforms to the above pattern, and is readily understandable once
you learn the pattern.


T

-- 
Written on the window of a clothing store: No shirt, no shoes, no service.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/12/22 07:28, Guillaume Piolat wrote:
> On Thursday, 12 May 2022 at 11:05:08 UTC, Basile B. wrote:
>> - Certain variant forms of the `is` Expression are not obvious (not
>> intuitive), I'm pretty sure I still cant use them without a quick look
>> to the specs.
>
> That one was a trouble to hear about =>
> 
http://p0nce.github.io/d-idioms/#Get-parent-class-of-a-class-at-compile-time


Cool trick but "parent" confused me there. I think you mean "base". :)

It looks like there is an alternative now:

  https://dlang.org/phobos/std_traits.html#BaseTypeTuple

Ali



Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/11/22 19:35, zjh wrote:
> On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
>> What are you stuck at? What was the most difficult features to
>> understand? etc.
>>
>
> I don't know the progress of `interface to C++`.
> I want to use my C++ functions in `d`.

That direction is easier:


https://dlang.org/spec/cpp_interface.html#calling_global_d_functions_from_cpp

(Also see "Using D Classes From C++" on the same page.)

The problem is calling into C++ where C++ templates are involved. As D 
does not include a C++ compiler, it cannot instantiate C++ templates 
automatically. (The programmer must instantiate explicitly as needed on 
the C++ side.)


Ali



Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Ali Çehreli via Digitalmars-d-learn

On 5/11/22 18:06, Christopher Katko wrote:

> Cool useful library functions like sumElement that magically don't work
> on static arrays.

Yeah, that sometimes gets me as well. Although it is trivial to deal 
with, the programmer may be surprised by the strange error messages:


  int[3] arr = [ 1, 2, 3 ];
  assert(sum(arr) == 6);

Error: template `std.algorithm.iteration.sum` cannot deduce function 
from argument types `!()(int[3])`
/usr/include/dlang/dmd/std/algorithm/iteration.d(7234): 
Candidates are: `sum(R)(R r)`

  with `R = int[3]`
  must satisfy the following constraint:
`   isInputRange!R`

WHAT? :) But the clue is on the last line above.

For completeness and for people who may not know the reason, D's static 
arrays and dynamic arrays are different in a number of ways but what 
matters here is that static arrays are not ranges because they cannot 
shrink. (Arguably, static arrays could be RandomAccessRanges but D's 
range hierarchy does not allow RandomAccessRanges that are not also 
InputRanges and ForwardRanges.)


So, the commented-out assert below cannot be compiled but the two 
following lines do compile by simply adding the two characters [] to get 
a range to all elements:


import std.algorithm;

void main() {
  int[3] arr = [ 1, 2, 3 ];
  // assert(sum(arr) == 6);
  assert(sum(arr[]) == 6);
  assert(arr[].sum == 6);
}

> 'private' is per module, not per class, making it pretty much useless
> for preventing incorrect access and using .

My view on private has changed over the years. I need to be convinced 
that there is usage that needs to be protected. :) I don't see people 
using types freely especially the ones that are in the same module. The 
only argument for private is to allow changing the implementation of 
published libraries in the future.


Still, private could have been a convention like naming variables with 
an underscore (which Go chose) and it could have been as effective. 
People who went around the convention and accessed the private members 
would either be happy or deserved what they got. I really don't see any 
problem on this matter for a programming language to go out of their way 
to protect people from themselves.


I started wondering as I wrote those: Perhaps IDEs make this a bigger 
issue? If they do respect private/public, perhaps they include member 
names in menus to pick from and the programmer does not want to see the 
private members there?


> I just realized foreach copies by value by default. Maybe. Sometimes.
> When?

It is always by-value when passing parameters and in foreach (which can 
be defined by opApply) and everywhere else. As Steve said, the confusion 
is when the copied thing is a reference itself. You end up getting 
another reference to data.


Ali



Re: What are (were) the most difficult parts of D?

2022-05-12 Thread jmh530 via Digitalmars-d-learn

On Thursday, 12 May 2022 at 15:32:24 UTC, Adam D Ruppe wrote:

On Thursday, 12 May 2022 at 15:18:34 UTC, jmh530 wrote:

What's the difference between a Type and Type Identifier?


The is expression roughly follows variable declaration style.

You write

int a;

to declare a new symbol named `a` of type `int`.

Similarly,

static if(is(T a))

declares a new symbol of type `a` if `T` is a valid type. (Of 
course, in this case, a and T are aliases of each other, so it 
isn't super useful, but in the more complex matches using the 
== and : operators, it might be different.)


The Identifier is optional.


Ah, yeah I know about that.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Basile B. via Digitalmars-d-learn
On Thursday, 12 May 2022 at 15:31:03 UTC, Steven Schveighoffer 
wrote:

On 5/12/22 11:18 AM, jmh530 wrote:

On Thursday, 12 May 2022 at 12:13:32 UTC, Basile B. wrote:

[snip]
```
is ( Type : TypeSpecialization , TemplateParameterList )
is ( Type == TypeSpecialization , TemplateParameterList )
is ( Type Identifier : TypeSpecialization , 
TemplateParameterList )
is ( Type Identifier == TypeSpecialization , 
TemplateParameterList )

```

I never remember those variants, because basically you never 
need them...

They were required for std.traits and that's it.


What's the difference between a Type and Type Identifier?


Type is a type, Identifier is an identifier.

In general, after such expressions, Identifier is now declared 
as an alias to the type, if the is expression was true. But in 
special forms, it might be a portion of the type.


So e.g.:

```d
static if(is(Foo Bar == struct))
{
  // inside here, it was determined that `Foo` was a type, and 
it is a

  // struct, and now, `Bar` is aliased to `Foo`
}
```

It's very confusing syntax though.

-Steve


yess that kind of stuff


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 12 May 2022 at 15:18:34 UTC, jmh530 wrote:

What's the difference between a Type and Type Identifier?


The is expression roughly follows variable declaration style.

You write

int a;

to declare a new symbol named `a` of type `int`.

Similarly,

static if(is(T a))

declares a new symbol of type `a` if `T` is a valid type. (Of 
course, in this case, a and T are aliases of each other, so it 
isn't super useful, but in the more complex matches using the == 
and : operators, it might be different.)


The Identifier is optional.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/12/22 11:18 AM, jmh530 wrote:

On Thursday, 12 May 2022 at 12:13:32 UTC, Basile B. wrote:

[snip]
```
is ( Type : TypeSpecialization , TemplateParameterList )
is ( Type == TypeSpecialization , TemplateParameterList )
is ( Type Identifier : TypeSpecialization , TemplateParameterList )
is ( Type Identifier == TypeSpecialization , TemplateParameterList )
```

I never remember those variants, because basically you never need them...
They were required for std.traits and that's it.


What's the difference between a Type and Type Identifier?


Type is a type, Identifier is an identifier.

In general, after such expressions, Identifier is now declared as an 
alias to the type, if the is expression was true. But in special forms, 
it might be a portion of the type.


So e.g.:

```d
static if(is(Foo Bar == struct))
{
  // inside here, it was determined that `Foo` was a type, and it is a
  // struct, and now, `Bar` is aliased to `Foo`
}
```

It's very confusing syntax though.

-Steve


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Tejas via Digitalmars-d-learn

On Thursday, 12 May 2022 at 15:18:34 UTC, jmh530 wrote:

On Thursday, 12 May 2022 at 12:13:32 UTC, Basile B. wrote:

[snip]
```
is ( Type : TypeSpecialization , TemplateParameterList )
is ( Type == TypeSpecialization , TemplateParameterList )
is ( Type Identifier : TypeSpecialization , 
TemplateParameterList )
is ( Type Identifier == TypeSpecialization , 
TemplateParameterList )

```

I never remember those variants, because basically you never 
need them...

They were required for std.traits and that's it.


What's the difference between a Type and Type Identifier?


`int`, `char` and friends are `Type`

In `int a`, `string c`, `a` and `c` are `Identifier`s


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread jmh530 via Digitalmars-d-learn

On Thursday, 12 May 2022 at 12:13:32 UTC, Basile B. wrote:

[snip]
```
is ( Type : TypeSpecialization , TemplateParameterList )
is ( Type == TypeSpecialization , TemplateParameterList )
is ( Type Identifier : TypeSpecialization , 
TemplateParameterList )
is ( Type Identifier == TypeSpecialization , 
TemplateParameterList )

```

I never remember those variants, because basically you never 
need them...

They were required for std.traits and that's it.


What's the difference between a Type and Type Identifier?


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 12 May 2022 at 14:42:43 UTC, Anonymouse wrote:
That said, one thing I cannot seem to firmly wrap my head 
around is `is` expressions. `is` does so many things.


It is simpler than it looks, I wrote about it in my book and in a 
post here:


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


```
alias AA = long*[string];
static if (is(AA whatEvenGoesHere : VP[K], VP, K))


You don't have to put anything there. The is expression kinda 
parallels declarations, so that thing would be the name for the 
newly declared symbol. But you don't need to declare a new symbol 
there so you can leave it blank; most the pieces are optional.


The one thing that has caused me most anguish and woe is 
hands-down https://issues.dlang.org/show_bug.cgi?id=18026 
though.


yeah bugs happen.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Basile B. via Digitalmars-d-learn

On Thursday, 12 May 2022 at 14:06:13 UTC, Arjan wrote:

On Thursday, 12 May 2022 at 11:05:08 UTC, Basile B. wrote:

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:

- Operator overloading in certain cases was confusing, I 
remember that for one particular form once I had to use your 
book instead of the official specs (when opSlice and opIndex 
are combined)




I still have the thing :

```d
/**
 * CharMap is an helper struct that allows to test
 * if a char is within a set of characters.
 */
struct CharMap
{
private bool[] _map;
private dchar _min, _max;

private void setMinMax(dchar value) pure nothrow @safe
{
if (value <= _min) _min = value;
else if (value >= _max) _max = value;
_map.length = _max + 1 - _min;
}

/**
 * Used in the construction process.
 *
 * Params:
 *  lo = The dchar that defines the range lower bound.
 *  hi = The dchar that defines the range upper bound 
(inclusive).

 *
 * Examples:
 * ---
 * CharMap cm = CharMap['0'..'9'];
 * ---
 */
static CharRange opSlice(int index)(dchar lo, dchar hi) pure 
nothrow @safe @nogc

{
return CharRange(lo, hi);
}

/**
 * Used in the construction process.
 *
 * Params:
 *  a = A list made of character slices, of single 
characters or

 *
 * any other values whose type is implicitly convertible to 
dchar.

 *
 * Examples:
 * ---
 * CharMap cm = CharMap['0'..'9', '.', 'f', 'd', 38, 39];
 * ---
 */
static CharMap opIndex(A...)(A a) pure nothrow @safe
{
CharMap result;

// bounds
foreach(elem; a)
{
alias T = typeof(elem);
static if (isSomeChar!T || 
isImplicitlyConvertible!(T, dchar))

{
result.setMinMax(elem);
}
else static if (is(T == CharRange))
{
result.setMinMax(elem._min);
result.setMinMax(elem._max);
}
else static assert(0, "unsupported opIndex argument 
type: " ~ T.stringof);

}

result._map[] = false;
foreach(elem; a)
{
alias T = typeof(elem);
static if (isSomeChar!T || 
isImplicitlyConvertible!(T, dchar))

result._map[elem - result._min] = true;
else static if (is(T == CharRange))
{
foreach(size_t i; elem._min - result._min .. 
elem._max - result._min + 1)

result._map[i] = true;
}
}
return result;
}

/**
 * Returns true if a character is within the map.
 *
 * Params:
 *  c = A character or any value convertible to a dchar.
 */
bool opBinaryRight(string op = "in", C)(C c) const pure 
nothrow @safe @nogc

if (op == "in")
{
static if (isSomeChar!C || isImplicitlyConvertible!(C, 
dchar))

{
if (_min > c || c > _max) return false;
else return _map[c - _min];
}
else static assert(0, `invalid argument type for 
CharMap.opBinaryRight!"in"(): ` ~ C.stringof);

}
}
///
pure @safe unittest
{
CharMap cm = CharMap['a'..'f', '0'..'9' , 'A'..'F', '_', 9];
assert('a' in cm);
assert('b' in cm);
assert('c' in cm);
assert('d' in cm);
assert('e' in cm);
assert('f' in cm);
assert('g' !in cm);
assert('A' in cm);
assert('B' in cm);
assert('C' in cm);
assert('D' in cm);
assert('E' in cm);
assert('F' in cm);
assert('G' !in cm);
assert('0' in cm);
assert('4' in cm);
assert('9' in cm);
assert('_' in cm);
assert('%' !in cm);
assert('\t' in cm);
}
```





Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Anonymouse via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


I came from shell scripts. They grew too large and overly complex 
when I wanted to do non-trivial things in a neat way, so I looked 
to proper programming languages and arbitrarily settled on D over 
python and similar. So for me the norm is D, and everything else 
is "other languages".


That said, one thing I cannot seem to firmly wrap my head around 
is `is` expressions. `is` does so many things. There's probably 
more intricate examples of how it's confusing, but I don't know 
it well enough to construe one:


```
alias AA = long*[string];
static if (is(AA whatEvenGoesHere : VP[K], VP, K))
{
static if(is(VP : V*, V))
{
assert(is(V));
}
}
```

The one thing that has caused me most anguish and woe is 
hands-down https://issues.dlang.org/show_bug.cgi?id=18026 though. 
It hasn't bit me for a while now, but the feeling of uncertainty, 
that the compiler might just suddenly after an innocent change no 
longer compile your project, seemingly outside of your control, 
is just... disheartening when it happens.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Guillaume Piolat via Digitalmars-d-learn

On Thursday, 12 May 2022 at 11:05:08 UTC, Basile B. wrote:
- Certain variant forms of the `is` Expression are not obvious 
(not intuitive), I'm pretty sure I still cant use them without 
a quick look to the specs.


That one was a trouble to hear about => 
http://p0nce.github.io/d-idioms/#Get-parent-class-of-a-class-at-compile-time






Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Arjan via Digitalmars-d-learn

On Thursday, 12 May 2022 at 11:05:08 UTC, Basile B. wrote:

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


To make it more meaningful, what is your experience with other 
languages?


Ali


Overhall I think that D was not hard to learn because well 
designed (i.e intuitive).


 I concur..


A few specific points however that I remember

- Certain variant forms of the `is` Expression are not obvious 
(not intuitive), I'm pretty sure I still cant use them without 
a quick look to the specs.


Yes indeed, had to read through the then excellent 
pdf()https://github.com/PhilippeSigaud/D-templates-tutorial by 
Philippe Sigaud (of PEG) to grasp the whole idea first, and still 
have to look it up when the need to use it arises...




- Operator overloading in certain cases was confusing, I 
remember that for one particular form once I had to use your 
book instead of the official specs (when opSlice and opIndex 
are combined)


Indeed same experience. Also opCmp and opEquals caused some 
confusion.


D's [][] !== C's [][],

Range peculiarities w.r.t some algo's (algo want's fwdRange but 
got inputRange but did not have the constraint ea)


lazy vs eager algorithms (the need to call .array)


The main difficulty I had is actually not specific to D. It was 
to accept that a GC is OK.


Nice one.

I recon I have to think much harder sometimes to know where the 
data is and 'who' has access: stack heap tls mutexed or not 
whatever, but find myself almost never asking this question 
anymore in D, which I use(d) to do almost all the time in c++ 
land. The need for it is almost removed by D.





Re: Exercises

2022-05-12 Thread Anonymouse via Digitalmars-d-learn

On Thursday, 12 May 2022 at 13:04:51 UTC, Alain De Vos wrote:
Is there a link to a webpage with some dlang exercises in order 
to see if i master the language, from simple to diffucult ?


[Rosetta Code](https://www.rosettacode.org) has a bunch, with 
[many](https://www.rosettacode.org/wiki/Category:D) 
examples/answers in D.


Re: Exercises

2022-05-12 Thread zjh via Digitalmars-d-learn

On Thursday, 12 May 2022 at 13:04:51 UTC, Alain De Vos wrote:
Is there a link to a webpage with some dlang exercises in order 
to see if i master the language, from simple to diffucult ?



[dtour](https://tour.dlang.org/).




Re: While loop on global variable optimised away?

2022-05-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 10:01:18 UTC, Johan wrote:
Any function call (inside the loop) for which it cannot be 
proven that it never modifies your memory variable will work. 
That's why I'm pretty sure that mutex lock/unlock will work.


 I think the common semantics ought to be that everything written 
by thread A  before it releases the mutex will be visible to 
thread B when it aquires the same mutex, and any assumptions 
beyond this are nonportable?




Exercises

2022-05-12 Thread Alain De Vos via Digitalmars-d-learn
Is there a link to a webpage with some dlang exercises in order 
to see if i master the language, from simple to diffucult ?


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Basile B. via Digitalmars-d-learn

On Thursday, 12 May 2022 at 12:13:32 UTC, Basile B. wrote:

On Thursday, 12 May 2022 at 11:50:59 UTC, Alain De Vos wrote:
Some keywords are overloaded and have different meaning when 
used in a different place.
Also some syntactic-sugar is way to much meaning too many 
different ways to do the same thing. I would prefer one way 
which is advised.


`ptr1 is ptr2` VS `is(T==U)` is ok even if the keyword is 
reused for two different things.


Problem is more (from 
https://dlang.org/spec/expression.html#is_expression)


```
is ( Type : TypeSpecialization , TemplateParameterList )
is ( Type == TypeSpecialization , TemplateParameterList )
is ( Type Identifier : TypeSpecialization , 
TemplateParameterList )
is ( Type Identifier == TypeSpecialization , 
TemplateParameterList )

```

I never remember those variants, because basically you never 
need them...

They were required for std.traits and that's it.


Perfect example of reuse that is never a problem : `final`.

what statically does `is` should have been several `__traits` I 
think.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Basile B. via Digitalmars-d-learn

On Thursday, 12 May 2022 at 11:50:59 UTC, Alain De Vos wrote:
Some keywords are overloaded and have different meaning when 
used in a different place.
Also some syntactic-sugar is way to much meaning too many 
different ways to do the same thing. I would prefer one way 
which is advised.


`ptr1 is ptr2` VS `is(T==U)` is ok even if the keyword is reused 
for two different things.


Problem is more (from 
https://dlang.org/spec/expression.html#is_expression)


```
is ( Type : TypeSpecialization , TemplateParameterList )
is ( Type == TypeSpecialization , TemplateParameterList )
is ( Type Identifier : TypeSpecialization , TemplateParameterList 
)
is ( Type Identifier == TypeSpecialization , 
TemplateParameterList )

```

I never remember those variants, because basically you never need 
them...

They were required for std.traits and that's it.


Creating a custom iota()

2022-05-12 Thread realhet via Digitalmars-d-learn

Hello,

I have my own DateTime struct.
It has opCmp() and opBinary(), I can do arithmetic with this 
custom DateTime and the amazing time units of the **quantities** 
package.


Now I'm about mo make iterations in a DateTime range:

const
  st = DateTime(UTC, "22.1.1 8:30").utcDayStart,
  en = DateTime(UTC, "22.3.5 19:56").max(now).utcDayStart + 
(100.0/64)*nano(second);


//this works
for(auto d = cast()st; d < en; d += day) writeln(d);

//this would be nicer, but not works
iota(st, en, day).each!writeln;

My question is, is there a way to 'extend' the functionality of 
the std.iota() function or it is better to come up with a unique 
name for this special 'iota' functionality?


I know that if I'm going to patch iota in my module, I have to 
make ALL the iota() variants plus my special iota variant visible 
in that module scope. Is this a good practice, or is there a 
better way?


Or maybe put it inside a DateTimeRange struct, and implement the 
std range functionality?






Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Alain De Vos via Digitalmars-d-learn
Some keywords are overloaded and have different meaning when used 
in a different place.
Also some syntactic-sugar is way to much meaning too many 
different ways to do the same thing. I would prefer one way which 
is advised.


Re: What are (were) the most difficult parts of D?

2022-05-12 Thread Basile B. via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


To make it more meaningful, what is your experience with other 
languages?


Ali


Overhall I think that D was not hard to learn because well 
designed (i.e intuitive).


A few specific points however that I remember

- Certain variant forms of the `is` Expression are not obvious 
(not intuitive), I'm pretty sure I still cant use them without a 
quick look to the specs.


- Operator overloading in certain cases was confusing, I remember 
that for one particular form once I had to use your book instead 
of the official specs (when opSlice and opIndex are combined)


The main difficulty I had is actually not specific to D. It was 
to accept that a GC is OK.


Re: Virtual methods on stack objects

2022-05-12 Thread vit via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 20:53:21 UTC, Marvin Hannott wrote:

On Wednesday, 11 May 2022 at 20:23:07 UTC, Ali Çehreli wrote:

On 5/11/22 13:06, Marvin Hannott wrote:

> I appreciate the answer, don't much like the "solutions".

Me neither. :)

> It's not so much about copying

Great!

> scoped class objects should have value semantics.

std.typecons.scoped does exactly that:

  https://dlang.org/phobos/std_typecons.html#scoped

import std.stdio;
import std.typecons;

interface Animal {
  string sing();
}

class Cat : Animal {
  this() {
writeln("Hi!");
  }

  ~this() {
writeln("Bye!");
  }

  string sing() {
return "mew";
  }
}

void foo(Animal animal) {
  writeln(animal.sing());
}

void bar() {
  auto cat = scoped!Cat();
  foo(cat);
}

void main() {
  bar();
}

The output:

Hi!
mew
Bye!

Ali


Yeah, but you can't return `Cat` 😉. And the documentation for 
`scoped` says:
It's illegal to move a class instance even if you are sure 
there are no pointers to it. As such, it is illegal to move a 
scoped object.


That's kinda very limiting.

Anyway, I cooked up another idea based on your first 
suggestions.

```D
struct S
{
static private interface I
{
int f(int i);
}

static private final class A : I
{
int f(int i) {return i;}
}

static private final class B : I
{
int f(int i) {return i+ 1;}
}

private I i;
private int d;

this(int d)
{
this.d = d;
if(d < 10)
{
i = scoped!A();
}else {
i = scoped!B();
}
}

int f() { return i.f(d);}
}
```
I mean, this is a super dumb example, but it kinda works. And I 
think it could be made a lot less tedious with some mixin magic.


`scoped` is not necesary, try this:

```d
import std.typecons;

struct S{
static private interface I{
int f(int i)const;
}

static private final class A : I{
static immutable typeof(this) instance = new 
immutable typeof(this)();


int f(int i)const {return i;}
}

static private final class B : I{
static immutable typeof(this) instance = new 
immutable typeof(this)();


int f(int i)const {return i+ 1;}
}

private immutable I i;
private int d;

this(int d){
this.d = d;

if(d < 10) i = A.instance;
else i = B.instance;

}

int f() { return i.f(d);}
}

void main(){
import std.stdio;
S(1).f().writeln();  /// 1
S(100).f().writeln(); /// 101

}
```