Re: Dynamic length string array at compile time?

2023-06-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/6/23 4:38 PM, Dany12L wrote:

On Tuesday, 6 June 2023 at 14:26:01 UTC, Steven Schveighoffer wrote:

On 6/5/23 11:45 AM, Dany12L wrote:
Hi, I'd be interested to know if it's possible to have a dynamic 
length array containing strings generated at compile time.





Sure. Just do it. Probably the reason nobody answered the question yet 
is that it trivially works if you try it :) Unless you did try it and 
it didn't work? In that case, post your code, I'm sure we can fix it.




My concern would be to create an immutable array (or other "equivalent") 
of strings by adding elements to the array at compile time from 
different modules.


OK, so you want to affect the same static variable from multiple places? 
No, that can't happen that way. You can do it in a functional 
programming fashion, but there can only be one initialization, you can't 
edit the thing afterwards.


So for instance, you can do:

```d
immutable string[] strs = mod1.makeStrings() ~ mod2.makeStrings() ~ ...;
```

In a centralized place.

-Steve


Re: What's dxml DOMEntity(R) type ?

2023-06-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/6/23 12:15 PM, Ferhat Kurtulmuş wrote:

On Tuesday, 6 June 2023 at 14:16:37 UTC, Steven Schveighoffer wrote:


In general, the easiset thing to do is use typeof, though it's not 
always pretty (and not always obvious how to write it). However, it's 
required for voldemort types.


```d
typeof(parseDom("")) DomEntity;
```



İt is one of the nicest features of d. I believe it should not be used 
too often because it may cause longer compilation times, worse code 
reading, less comfort with d code scanners, editors etcetera.


It should not affect compile times at all. If you are going to 
instantiate it that way, it will need to be compiled regardless. 
`typeof` is very low cost, as it's a direct call on the compiler internals.


Something like `ReturnType!Foo` is different.

-Steve


Re: Dynamic length string array at compile time?

2023-06-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/5/23 11:45 AM, Dany12L wrote:
Hi, I'd be interested to know if it's possible to have a dynamic length 
array containing strings generated at compile time.





Sure. Just do it. Probably the reason nobody answered the question yet 
is that it trivially works if you try it :) Unless you did try it and it 
didn't work? In that case, post your code, I'm sure we can fix it.


-Steve


Re: How do I generate `setX` methods for all private mutable variables in a class?

2023-06-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/5/23 11:33 AM, Basile B. wrote:

On Monday, 5 June 2023 at 15:13:43 UTC, Basile B. wrote:

On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote:

How do I generate `setX` methods for all private mutable


although I did not spent time on the setter body... I suppose the 
question was more about the metprogramming technic, and that you don't 
want a pre-mashed solution ;)


By the way...an other solution is to use 
[opDispatch](https://dlang.org/spec/operatoroverloading.html#dispatch):


```d
class Color {}

class Rectangle {
     private Color fillColor;
     private Color strokeColor;
     private uint strokeWidth;

     auto opDispatch(string member, T)(auto ref T t)
     {
  static if (member == "setStrokeWidth") {}
     else static if (member == "setStrokeColor") {}
     else static if (member == "setFillColor") {}
     else static assert(0, "cannot set " ~ member);
     return this;
     }
}

void main()
{
     (new Rectangle)
     .setStrokeWidth(0)
     .setStrokeColor(null)
     .setFillColor(null);
}
```


Ugh, don't do it that way. Always give opDispatch a template constraint 
or it will suck to use.


Also, given the problem constraints, you can build the method 
automatically using the string.


```d
auto opDispatch(string member, T)(auto ref T t) if(member.startsWith("set"))
{
   mixin(toLower(m[3]), m[4 .. $], " = t;");
}
```

-Steve


Re: how to skip empty field in csvReader?

2023-06-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/6/23 1:09 AM, mw wrote:


Is there a way to tell csvReader to skip such empty fields?


What I have done is specify that it's a string, and then handle the 
conversion myself.


Possibly it can use Nullable, but I'm not sure.


Or, is there another CSV reader library with this functionality I can use?


I don't know how much of this is supported in tsv-utils but you might 
give it a look.


-Steve



Re: What's dxml DOMEntity(R) type ?

2023-06-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/5/23 6:43 AM, Ferhat Kurtulmuş wrote:

On Monday, 5 June 2023 at 10:01:01 UTC, John Xu wrote:
The parseDOM returns a DOMEntity(R) type, how do I write a xmlRoot as 
global variable?

I need its detailed type (auto / Variant doesn't work).


    import dxml.dom;
    ?? xmlRoot;
    int main() {
    string xml = readText("a.xml");
    auto dom = parseDOM(xml);
    xmlRoot = dom.children[0];
    }

```d
import dxml.dom;
import std.stdio;

     DOMEntity!string xmlRoot;
     int main()
     {
     string xml = "";
     auto dom = parseDOM(xml);
     writeln(typeof(dom.children[0]).stringof); // yields 
"DOMEntity!string"

     xmlRoot = dom.children[0];
     return 0;
     }
     ```



In general, the easiset thing to do is use typeof, though it's not 
always pretty (and not always obvious how to write it). However, it's 
required for voldemort types.


```d
typeof(parseDom("")) DomEntity;
```

-Steve


Re: How get struct value by member name string ?

2023-06-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/1/23 10:58 PM, John Xu wrote:


Ok, thanks for all you gentlemen's help. I tried following function,
now it works like C/C++/Python way:

     string getTMember(T t, string columnName) {
     foreach(member; __traits(allMembers, T)){
     if (member == columnName) {
     return __traits(getMember, mcu, member).to!string;
     }
     }
     return "";
     }



You can use a switch, and the search for the right member name should be 
more optimized, though it's possible the compiler might recognize your 
pattern and do this anyway:


```d
string getTMember(T t, string columnName) {
   switch(columnName)
   {
static foreach(member; __traits(allMembers, T)) {
case member:
 return __traits(getMember, t, member).to!string;
}
default:
return "";
   }
}
```

This is a very common pattern in e.g. serialization libs in D.

-Steve


Re: How get struct value by member name string ?

2023-06-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/31/23 12:08 AM, John Xu wrote:



When render vibe.d diet template,

     string[] allMembers = __traits(allMembers, t);


enum allMembers = __traits(allMembers, t);


     res.render!("index.dt", t, allMembers)

if I don't want write memberName one by one in diet template:

     table
     - foreach(memberName; allMembers)
     tr
     td #{memberName}
     td #{getTMember!memberName(t)}

Problem: memberName is not known at compile time.


The problem is that you stored the member name list as a runtime 
variable, and that is not known at compile time. Try the enum.


Or really, just `foreach(memberName; __traits(allMembers, t))` right in 
the diet template.


-Steve


Re: How get struct value by member name string ?

2023-05-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/30/23 4:46 AM, John Xu wrote:
How to put above enum as a function parameter? Following code wouldn't 
work:


     string getTMember(T t, enum string memberName) {
     return __traits(getMember, t, memberName);
     }


compile time parameters come before runtime parameters:

```d
string getTMember(string memberName)(T t) {
   return __traits(getMember, t, memberName);
}

// used like
auto v = getTMember!"name"(t);
```

-Steve


Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/29/23 10:57 PM, Cecil Ward wrote:
I have often come into difficulties where I wish to have one routine 
that can be called with either immutable or (possibly) mutable argument 
values. The argument(s) in question are in, readonly, passed by value or 
passed by const reference. Anyway, no one is trying to write to the 
items passed in as args, no badness attempted.


In cases where const doesn't suffice, inout might. inout has a feature 
that it can be used in cases where a const nested behind multiple 
references would not work.


-Steve


Re: Concepts like c++20 with specialized overload resolution.

2023-05-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/27/23 9:50 AM, vushu wrote:

On Saturday, 27 May 2023 at 13:42:29 UTC, Basile B. wrote:

On Saturday, 27 May 2023 at 13:23:38 UTC, vushu wrote:

[...]
Is there something equivalent in dlang, doesn't seem like d support 
specialized overload?


D solution is called [template 
constraints](https://dlang.org/spec/template.html#template_constraints).


Yes I know there is template constraint, but not with specialized 
overloading right?


so you need to use static if for checking if it hasmagma.


What is missing is an "else" thing.

So you have to repeat the constraint (as a negation) unfortunately.

e.g.:

```d
struct LavaMan {
  void magma() { writeln(" LavaMan is throwing LAVA"); }
}

struct FakeVulcano {
  void try_making_lava() { writeln(" Making fake lava"); }
};

void make_lava(T)(ref T lava) if (hasMagma!T) {
lava.magma();
}

void make_lava(T)(ref T lava_thing) if (!hasMagma!T){
lava_thing.try_making_lava();
}
```

-Steve


Re: string to char[4] FourCC conversion

2023-05-26 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/26/23 8:19 AM, realhet wrote:

Hello,

Is there a way to do it nicer/better/faster/simpler?

```
char[4] fourC(string s)
{
 uint res;//Zero initialized, not 0xff initialized.
 auto cnt = min(s.length, 4),
     p = cast(char[4]*)();
 (*p)[0..cnt] = s[0..cnt];
 return *p;
}
```


This worked for me:

```d
char[4] fourC(string s)
{
if(s.length >= 4)
return s[0 .. 4];
char[4] res = 0;
res[0 .. s.length] = s;
return res;
}
```

Supporting returning as a 4-char array even when the input has less than 
4 makes it tricky. But not so bad.


-Steve


Re: As of 2023, we still cannot declaring a constant string[char] AA?

2023-05-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/16/23 7:17 PM, mw wrote:

Hi,

I just run into this problem again:

https://stackoverflow.com/questions/26861708/what-is-the-syntax-for-declaring-a-constant-stringchar-aa

So, the solution still is to use:
```
static this () {
   ...
}
```

What happened to this comments:
"""
It should be noted that this restriction will eventually go away, once 
there is a solid library implementation of associative arrays. There is 
currently work in progress to this effect, which seems to be nearing 
completion. –

Meta  Nov 14, 2014 at 17:41
"""

Still not there yet, after ~10 years?


Yep.

I have a library solution: https://code.dlang.org/packages/newaa

You can declare a `Hash!(char, string)` in module space, and then use it 
as an AA later.


However, it needs to not be const. The Hash type does not set itself up 
as an AA doppelganger until you call `asAA` on it, which means it needs 
to set up some internal things, and therefore needs to be mutable. I 
think I can make a method that does this, so you can use `const 
Hash!(char, string) = [ ... ]`, but it still can't change the type to an 
actual AA (the compiler won't let that work).


Wow, over a year since I did anything on it. Probably should tinker a 
bit more.


-Steve


Re: Given an object, how to call an alias to a member function on it?

2023-05-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/2/23 8:52 AM, Quirin Schroll wrote:
How do I invoke the member function in a reliable way? Given `obj` of 
the type of the object, I used `mixin("obj.", __traits(identifier, 
memberFunc), "(params)")`, but that has issues, among probably others, 
definitely with visibility. (The member function alias is a template 
parameter.)


Isn't that what `__traits(child)` is for?

https://dlang.org/spec/traits.html#child

-Steve


Re: Making a D library for a C executable

2023-04-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/27/23 5:29 PM, Jan Allersma wrote:

On Thursday, 27 April 2023 at 21:05:00 UTC, Mike Parker wrote:
That's a compilation error, not a linker problem. You need to tell the 
compiler about the function with a prototype:


Declaring the function does fix the compiler problem. However, I do get 
a linker error once I compile that:


```bash
$ g++ ../build/libshared-api.so main.cpp
/usr/bin/ld: /tmp/ccNMKxEE.o: in function `main':
main.cpp:(.text+0x2a): undefined reference to `foo()'
collect2: error: ld returned 1 exit status
```




You may have to link the library second. Sometimes linkers are 
particular about object order.


Also, please include your commands for building the D library so 
reproduction is possible.


-Steve


Re: Getting a total from a user defined variable

2023-04-20 Thread Steven Schveighoffer via Digitalmars-d-learn

```d
writeln("Total: ", p.fold!((a,b) => a+b.age)(0UL));
// or
writeln("Total: ", reduce!((a,b) => a+b.age)(0UL, p));
```

Note that `reduce` is the old version of `fold`, which happened when 
UFCS became a thing.


-Steve


Re: Variable length arrays under -betterC?

2023-04-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/17/23 11:34 AM, DLearner wrote:
Requirement is to write some D code (which avoids the GC), that will be 
called from C.
So simple approach seemed to be to write D code under -betterC 
restrictions.


However, also need variable length arrays - but D Dynamic Arrays not 
allowed under -betterC.



Any ideas how to implement variable length arrays under -betterC?


variable-length arrays (i.e. slices) are valid in betterC. What isn't 
allowed is *GC-allocating* them and *appending* to them in betterC.


```d
int[] arr; // fine
// arr ~= 5; // nope, uses GC
arr = (cast(int *)malloc(int.sizeof * 5))[0 .. 5]; // fine
arr = arr[0 .. 3]; // also fine, no allocations needed
arr = (cast(int*)realloc(arr.ptr, int.sizeof * 10))[0 .. 10]; // fine, 
but leaks the original pointer

free(arr.ptr); // fine
```
What you *likely* want is an array type that handles some of the 
lifetime issues, or at least some UFCS/factory functions to make life 
easier (the above code is as bad as C code (except for the slicing)). 
But variable-length arrays work just fine as-is.


As with any manual memory management system, you need to handle the 
lifetime more carefully and explicitly. There's a reason why reference 
counting is hard to implement.


-Steve


Re: class variable initialization

2023-04-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/15/23 7:05 AM, 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?


You can construct objects at compile time.

If I understand your question properly:

```d
struct Wrapper
{
   Object x = new Object();
   alias x this;
}

void foo(Object o)
{
   assert(o !is null);
}

void main()
{
   Wrapper w;
   foo(w);
}
```

-Steve


Re: How come a count of a range becomes 0 before a foreach?

2023-04-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/10/23 6:43 PM, ikelaiah wrote:

On Monday, 10 April 2023 at 01:01:59 UTC, Steven Schveighoffer wrote:

On 4/9/23 9:16 AM, Ali Çehreli wrote:



   auto entries = dirEntries(/* ... */).array;


I'd be cautious of that. I don't know what the underlying code uses, 
it may reuse buffers for e.g. filenames to avoid allocation.


If you are confident the directory contents won't change in that 
split-second, then I think iterating twice is fine.




Steve,

The Rmd files are not on a network drive, but saved locally.
So, I'm confident, the files won't change in a split-second.


That is not what I meant.

What I mean is that `array` is going to copy whatever values the range 
gives it, which might be later *overwritten* depending on how 
`dirEntries` is implemented.


e.g. the following code is broken:

```d
auto lines = File("foo.txt").byLine.array;
```

But the following is correct:

```
auto lines = File("foo.txt").byLineCopy.array;
```

Why? Because `byLine` reuses the line buffer eventually to save on 
allocations. The array of lines might contain garbage in the earlier 
elements as they got overwritten.


I'm not saying it's wrong for `dirEntries`, I haven't looked. But you 
may want to be cautious about just using `array` to get you out of 
trouble, especially for lazy input ranges.


-Steve


Re: mutable pointers as associative array keys

2023-04-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/10/23 4:25 PM, Steven Schveighoffer wrote:
It's also completely useless. Having const keys does nothing to 
guarantee unchanging keys. Another half-assed attempt to be encode 
correct semantics but fails completely in its goal.


In case you wonder how old this is:

https://issues.dlang.org/show_bug.cgi?id=11477
https://issues.dlang.org/show_bug.cgi?id=12491#c2

-Steve


Re: mutable pointers as associative array keys

2023-04-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/10/23 2:14 PM, John Colvin wrote:

It seems that it isn't possible, am I missing something?

alias Q = int[int*];
pragma(msg, Q); // int[const(int)*]


Yep, it's been that way forever. Only with pointers and arrays. It's 
fine with mutable classes and structs (even if they contain pointers).



Also, is this documented somewhere?


No.

It's also completely useless. Having const keys does nothing to 
guarantee unchanging keys. Another half-assed attempt to be encode 
correct semantics but fails completely in its goal.


-Steve


Re: How come a count of a range becomes 0 before a foreach?

2023-04-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/9/23 9:16 AM, Ali Çehreli wrote:

On 4/8/23 21:38, ikelaiah wrote:

 > I will modify the code to construct it twice.

Multiple iterations of dirEntries can produce different results, which 
may or may not be what your program will be happy with.


Sticking an .array at the end will iterate a single time and maintain 
the list forever because .array returns an array. :)


   auto entries = dirEntries(/* ... */).array;


I'd be cautious of that. I don't know what the underlying code uses, it 
may reuse buffers for e.g. filenames to avoid allocation.


If you are confident the directory contents won't change in that 
split-second, then I think iterating twice is fine.


-Steve


Re: How come a count of a range becomes 0 before a foreach?

2023-04-08 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/8/23 9:38 PM, ikelaiah wrote:

// Get files in specified inputPath variable with a specific extension
     auto rmdFiles = file.dirEntries(inputPath, file.SpanMode.shallow)
     .filter!(f => f.isFile)
     .filter!(f => f.name.endsWith(fileEndsWith));

     // LINE 72 -- WARNING -- If we count the range here, later it will 
become 0 in line 82
     writeln(programName ~ ": number of files found " ~ 
to!string(rmdFiles.walkLength));


dirEntries returns an *input range*, not a *forward range*. This means 
that once it's iterated, it's done.


If you want to iterate it twice, you'll have to construct it twice.

-Steve


Re: Prevent console line advancing on user input

2023-04-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/6/23 4:01 AM, anonymouse wrote:

Wondering if this is possible? Ask a user at input and wait for response:

write("Is the sky blue? ");
readf!" %s\n"(response);

If the user's response is correct, I'd like to change the color of 
provided response to indicate it was correct then advance to the next 
line and ask a different question.


If the user's response is incorrect, I'd like to clear the line and 
repeat the question without advancing down the screen vertically.


I'm assuming it can be done by intercepting all input before the console 
processes them and outputting a '\r', a blank line the length of the 
screen, and another '\r' to get back to the beginning before reprinting 
the question. But I have no idea how to intercept the raw input.


You can't intercept raw input. It's the terminal that decides when to 
send you the line of text, you cannot control it via `stdin`.


You need to use a terminal-control library, such as `arsd.terminal`

https://github.com/adamdruppe/arsd/blob/master/terminal.d

-Steve


Re: constant pointer failing to compile

2023-04-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/5/23 8:59 PM, Mathias LANG wrote:

immutable ubyte[4] data = [1, 2, 3, 4];


Using a static array instead of a slice will do the trick. You can leave 
the `__gshared` if you want, but it is redundant on a global, 
initialized `immutable` variable.


I found out the same thing. But I don't really understand why.

the error message gives a slight clue:

```
cannot use non-constant CTFE pointer in an initializer ‘&[cast(ubyte)1u, 
cast(ubyte)2u, cast(ubyte)3u, cast(ubyte)4u][0]’

```

That *isn't* a CTFE pointer, it's a pointer to a static immutable. Yes, 
the initialization value is a CTFE array, but the variable itself has an 
address. Notice how the expression has turned into an address of the 
initializer.


I think this is a compiler bug.

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/5/23 6:34 PM, Paul wrote:

On Tuesday, 4 April 2023 at 22:20:52 UTC, H. S. Teoh wrote:


Best practices for arrays in hot loops:
- Avoid appending if possible; instead, pre-allocate outside the loop.
- Where possible, reuse existing arrays instead of discarding old ones
  and allocating new ones.
- Use slices where possible instead of making copies of subarrays (this
  esp. applies to strings).
- Where possible, prefer sequential access over random access (take
  advantage of the CPU cache hierarchy).


Thanks for sharing Teoh!  Very helpful.

would this be random access? for(size_t i; iindices?

...and this be sequential foreach(a;arr) ?


No, random access is access out of sequence. Those two lines are pretty 
much equivalent, and even a naive compiler is going to produce exactly 
the same generated code from both of them.


A classic example is processing a 2d array:

```d
for(int i = 0; i < arr[0].length; ++i)
   for(int j = 0; j < arr.length; ++j)
 arr[j][i]++;

// vs
for(int j = 0; j < arr.length; ++j)
   for(int i = 0; i < arr[0].length; ++i)
 arr[j][i]++;
```

The first accesses elements *by column*, which means that the array data 
is accessed non-linearly in memory.


To be fair, both are "linear" in terms of algorithm, but one is going to 
be faster because of cache coherency (you are accessing sequential 
*hardware addresses*).


-Steve


Re: Virtual method call from constructor

2023-04-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/4/23 3:08 AM, Chris Katko wrote:
Second, could you give me some case examples where this problem occurs? 
Is the issue if I override refresh in a derived class, and the base 
class will accidentally use child.refresh()?




An example of a problem:

```d
class Base
{
   this() { virtualCall(); }
   void virtualCall() {}
}

class Derived : Base
{
   int *data;
   this() { data = new int; }
   override void virtualCall() { *data = 5; }
}
```

A derived class constructor without an explicit `super()` call, is 
injected with a `super()` call at the beginning of the constructor.


So in this case, the `Base` constructor runs before the `Derived` 
constructor. The `Base` ctor calls `virtualCall` before `Derived` is 
ready for it.


To fix this, you can explicitly call `super()` after initializing the data:

```d
this() {data = new int; super(); }
```

So there are ways to do this in a reasonable way, but that is why the 
warning exists.


-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/4/23 11:34 AM, Salih Dincer wrote:

On Tuesday, 4 April 2023 at 14:20:20 UTC, Steven Schveighoffer wrote:
parallel is a shortcut to `TaskPool.parallel`, which is indeed a 
foreach-only construct, it does not return a range.


I think what you want is `TaskPool.map`:

```d
// untested, just looking at the
taskPool.map!(/* your map function here */)
   (s.iota(len)).writeln;
```



I tried, thanks but it goes into infinite loop. For example, the first 
50 of the sequence should have been printed to the screen immediately 
without waiting.


```d
long[50] arr;
RowlandSequence_v2 range;

auto next(long a)
{
   range.popFront();
   return arr[a] = range.front();
}

void main()
{
     range = RowlandSequence_v2(7, 2);
     taskPool.map!next(iota(50))/*
     s.iota(50)
  .map!next
  .parallel//*/
  .writeln;
}
```


Keep in mind that `arr` and `range` are thread-local, and so will be 
different states for different tasks.


Though I don't really know what you are doing there.

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/4/23 5:24 AM, Salih Dincer wrote:

Is it necessary to enclose the code in `foreach()`? I invite Ali to tell 
me! Please explain why parallel isn't running.


parallel is a shortcut to `TaskPool.parallel`, which is indeed a 
foreach-only construct, it does not return a range.


I think what you want is `TaskPool.map`:

```d
// untested, just looking at the
taskPool.map!(/* your map function here */)
   (s.iota(len)).writeln;
```

Can't use pipelining with it, because it is a member function.

https://dlang.org/phobos/std_parallelism.html#.TaskPool.map

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/3/23 7:22 PM, Paul wrote:

```d
// Timed main() 
vvv

void main(string[] args) {
auto progStartTime = MonoTime.currTime;
//-
 string filename = args.length > 1 ? args[1] : "aoc2215a.data";
 CommPair[] commPair;
 ulong x,y;

 // read file that has data sets in the form of x,y coordinate pairs
 // for each sensor-beacon pair.  Create on array of structs to hold
 // this information.
 loadFileDataIntoArrayOfStructs(commPair, filename);

 foreach(int lineOfInterest;parallel(iota(0,4_000_001))) {
     Span[] span; // A section of line-of-interest coordinates where 
no other beacons are present.

     const spanReserve = span.reserve(50);
     createSpansOfNoBeacons(lineOfInterest,commPair,span);

     // if spans overlap, combine them into a single span and mark
     // the other spans !inUse.
     combineOverlappingSpans(span);

     // look for a line that doesn't have 4,000,001 locations 
accounted for

     if(beaconFreeLocations(span) < 4_000_001) {

     // find the location that is not accounted for
     foreach(ulong i;0..4_000_000) {
     bool found = false;
     foreach(sp;span) {
     if(i >= sp.xLow && i <= sp.xHigh) {
     found = true;
     break;
     }
     }
     if(!found) {
     x = i; y = lineOfInterest;
     break;
     }
     }
     }
 }
writeln(x," ",y);

```


So I just quoted your main loop.

I am assuming that this O(n^2) algorithm doesn't actually run for all 
iterations, because that wouldn't be feasible (16 trillion iterations is 
a lot).


This means that I'm assuming a lot of cases do not run the second loop. 
Everything you do besides prune the second loop is mostly allocating an 
array of `Span` types. This means most of the parallel loops are 
allocating, and doing nothing else. As I said earlier, allocations need 
a global lock of the GC.


What you need to do probably, is to avoid these allocations per loop.

The easiest thing I can think of is to store the Span array as a static 
array of the largest array you need (i.e. the length of `commPair`), and 
then slice it instead of appending.


So what you need is inside `createSpansOfNoBeacons`, take as a reference 
a `ref Span[MAX_SPANS]`, and have it return a `Span[]` that is a slice 
of that which was "alocated".


See if this helps.

FWIW, I did the AoC 2022 as well, and I never needed parallel execution. 
Looking at my solution comment in reddit, this one I sort of punted by 
knowing I could exit as soon as the answer is found (my solution runs in 
2.5s on my input). But I recommend (once you are done), reading this 
post, it is a really cool way to look at it:


https://www.reddit.com/r/adventofcode/comments/zmcn64/2022_day_15_solutions/j0hl19a/?context=8=9

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/3/23 6:56 PM, Paul wrote:

On Monday, 3 April 2023 at 22:24:18 UTC, Steven Schveighoffer wrote:



If your `foreach` body takes a global lock (like `writeln(i);`), 
then it's not going to run any faster (probably slower actually).

**Ok I did have some debug writelns I commented out.**


And did it help?

**No**

My program is about 140 lines Steven.  Its just one of the Advent of 
Code challenges.  Could I past the whole program here and see what you 
think?


Yeah, please post.

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/3/23 6:02 PM, Paul wrote:

On Sunday, 2 April 2023 at 15:32:05 UTC, Steven Schveighoffer wrote:



It's important to note that parallel doesn't iterate the range in 
parallel, it just runs the body in parallel limited by your CPU count.

**?!?**


So for example, if you have:

```d
foreach(i; iota(0, 2_000_000).parallel)
{
   runExpensiveTask(i);
}
```

The foreach is run on the main thread, gets a `0`, then hands off to a 
task thread `runExpensiveTask(0)`. Then it gets a `1`, and hands off to 
a task thread `runExpensiveTask(1)`, etc. The iteration is not 
expensive, and is not done in parallel.


On the other hand, what you *shouldn't* do is:

```d
foreach(i; iota(0, 2_000_000).map!(x => runExpensiveTask(x)).parallel)
{
}
```

as this will run the expensive task *before* running any tasks.



If your `foreach` body takes a global lock (like `writeln(i);`), then 
it's not going to run any faster (probably slower actually).

**Ok I did have some debug writelns I commented out.**


And did it help? Another thing that takes a global lock is memory 
allocation.



Also make sure you have more than one logical CPU.

**I have 8.**


It's dependent on the work being done, but you should see a roughly 8x 
speedup as long as the overhead of distributing tasks is not significant 
compared to the work being done.


-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/1/23 6:32 PM, Paul wrote:

On Saturday, 1 April 2023 at 18:30:32 UTC, Steven Schveighoffer wrote:

On 4/1/23 2:25 PM, Paul wrote:

```d
import std.range;

foreach(i; iota(0, 2_000_000).parallel)
```



Is there a way to tell if the parallelism actually divided up the work?  
Both versions of my program run in the same time ~6 secs.


It's important to note that parallel doesn't iterate the range in 
parallel, it just runs the body in parallel limited by your CPU count.


If your `foreach` body takes a global lock (like `writeln(i);`), then 
it's not going to run any faster (probably slower actually).


If you can disclose more about what you are trying to do, it would be 
helpful.


Also make sure you have more than one logical CPU.

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/1/23 2:25 PM, Paul wrote:

Thanks in advance for any assistance.

As the subject line suggests can I do something like? :
```d
foreach (i; taskPool.parallel(0..2_000_000))
```
Obviously this exact syntax doesn't work but I think it expresses the 
gist of my challenge.



```d
import std.range;

foreach(; iota(0, 2_000_000).parallel)
```

-Steve


Re: The Phobos Put

2023-03-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/30/23 11:44 AM, Paul Backus wrote:

It should be fine to have both a `ref` and non-`ref` overload for `put`, 
though, right? If the non-`ref` overload is only called with rvalues, 
then it's fine to leave them in an undetermined state, because nothing 
can access them afterward anyway.


There's a certain attempt in phobos in some places to try and ensure 
code that is going to confuse will not compile. I think this is one of 
those attempts.


Consider that if you pass a slice into `put`, then it returns nothing. 
There is no indication of what actually was written. It's essentially an 
inconclusive call, because the "result" is the output range itself. How 
many elements were written? You can't tell.


I'd argue that the way input ranges are used as output ranges today is 
extremely confusing. It makes sort of a logical sense, but the fact that 
you need to store your "original" range, and then do some length math to 
figure out what was written makes such code very awkward all around. The 
output is decipherable, but not obvious.


I stand by my assertion that probably lvalue input ranges should never 
have been treated as output ranges implicitly. They should have had to 
go through some sort of wrapper.


-Steve


Re: The Phobos Put

2023-03-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/29/23 11:01 PM, Salih Dincer wrote:


```d
import std.algorithm.mutation : copy;
void main()
{
   int[8] buf;
   auto dig = [1, 2, 3, 4];
   auto rem = dig.copy(buf);
   assert(rem.length == 4);
}

```

Looks like 'copy' has the same overload issue.


A static array is not a range of any kind. What would `popFront` do on a 
static array, since the length is part of the type?


But you can do `dig.copy(buf[])` since a dynamic array is.

-Steve


Re: The Phobos Put

2023-03-29 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/29/23 4:29 PM, ag0aep6g wrote:

But regardless of Salih's exact intent, the broader point is: a non-ref 
overload could be added to Phobos. And that would enable 
`a[1..$-1].phobos_put([2, 3])`. Which is what he asked about originally.


I think the idea of requiring ref output ranges is that you can then let 
the range keep track of its output state.


An input range with lvalue elements is therefore an output range, but 
only if it's accepted via ref, since it has to be iterated as it goes. 
If you iterate it only internally, then it's either in an undetermined 
state when you exit `put`, or it is a forward range that was copied 
without using `save`.


It's not the greatest situation. I feel like we probably shouldn't have 
made lvalue input ranges be output ranges automatically.


-Steve


Re: How to debug and watch globals in windows debugger?

2023-03-29 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/28/23 6:42 PM, ryuukk_ wrote:



Am i the only want who want to improve things, is it a lost cause?


I'm not one to use a debugger often, but it is very helpful for many 
people. I lament that the Windows debugging situation out of the box is 
dreadful. The students I teach D to I don't show the debugger because 
I'm worried it would confuse them more than help.


I both don't use Windows and mostly do debugging via writeln, so for 
something that doesn't affect me much, I tend not to put effort in. I'm 
hoping someone who is motivated enough will do it.


If I recall correctly, visual studio debugging is better than the other 
solutions. But I don't know having never got debugging to work. I've 
heard that mago is supposed to work better, and was written for D, but 
is Visual Studio dependent: https://github.com/rainers/mago


I wonder if there isn't some way to make this work well for other IDEs? 
I couldn't get it to work on VSCode.



Should i move on?


In any case, the debugging experience isn't perfect, but seems like a 
drastic measure to leave D altogether if you can't debug globals.


-Steve


Re: Convert binary to UUID from LDAP

2023-03-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/28/23 6:36 AM, WebFreak001 wrote:


the formatting messed up here. Try this code:

```d
auto uuid = UUID(
     (cast(const(ubyte)[]) value.attributes["objectGUID"][0])
     [0 .. 16]
);
```


Nice, I didn't think this would work actually!

-Steve


Re: Convert binary to UUID from LDAP

2023-03-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/28/23 1:05 AM, Alexander Zhirov wrote:

On Tuesday, 28 March 2023 at 00:51:43 UTC, Steven Schveighoffer wrote:

`auto uuid = UUID(*cast(ubyte[16]*)youruuiddata.ptr);` (added quotes here)


```d
ubyte[] arr = cast(ubyte[])value.attributes["objectGUID"][0].dup;
writeln(UUID(cast(ubyte[16])arr.ptr));
```

`Error: cannot cast expression 'cast(ubyte*)arr' of type 'ubyte*' to 
'ubyte[16]'`


No, it's not possible to transform. The array is initially 
`immutable(char[])`.




Apologies, I quoted my original above to suppress the markdown 
formatting. Here it is again with syntax highlighting.


```d
auto uuid = UUID(*cast(ubyte[16]*)youruuiddata.ptr);
```

That should work. I sometimes forget that my newsreader adds the 
markdown tag, even though it looks good on my end.


-Steve


Re: como eliminar los caracteres nulos de las respuestas en socket?

2023-03-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/27/23 1:13 PM, Espartan Jhon wrote:
hola a todos quisiera saber como es que puedo eliminar los caracteres 
nulos de las respuestas de mi socket


In English (via google translate):

Hello everyone, I would like to know how I can remove null characters 
from my socket responses


My response in English:

You should not be getting null characters from that code, it's sending 
the string, but the string has no null characters in it.


However, I see you are reading into a static buffer. That static 
character buffer has already-defined characters in it. If you use the 
whole buffer, it will include those characters (they are not null, but 
`0xff`). The return value from `receive` is the number of characters 
written.


Try instead:

```d
auto nchars = c.receive(cadena);
if(nchars < 0) { /* error */ }
auto mensaje = cadena[0 .. nchars]; // real message
```

Traducido al español (con traductor de google):

No debería obtener caracteres nulos de ese código, está enviando la 
cadena, pero la cadena no tiene caracteres nulos.


Sin embargo, veo que está leyendo en un búfer estático. Ese búfer de 
caracteres estáticos tiene caracteres ya definidos. Si usa todo el 
búfer, incluirá esos caracteres (no son nulos, sino `0xff`). El valor de 
retorno de `receive` es el número de caracteres escritos.


Prueba en su lugar:

```d
auto nchars = c.receive(cadena);
if(nchars < 0) { /* error */ }
auto mensaje = cadena[0 .. nchars]; // mensaje real
```

-Steve


Re: Convert binary to UUID from LDAP

2023-03-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/27/23 1:56 PM, Alexander Zhirov wrote:
I get `objectGUID` data from LDAP as binary data. I need to convert 
`ubyte[]` data into a readable `UUID`. As far as I understand, it is 
possible to do this via `toHexString()`, but I have reached a dead end. 
Is there a way to make it more elegant, like [this 
technique](https://dlang.org/phobos/std_uuid.html#.UUID)?


```
ubyte[] => [159, 199, 22, 163, 13, 74, 145, 73, 158, 112, 7, 192, 12, 
193, 7, 194]

hex => 9FC716A30D4A91499E7007C00CC107C2
```


auto uuid = UUID(*cast(ubyte[16]*)youruuiddata.ptr);

-Steve


Re: Why are globals set to tls by default? and why is fast code ugly by default?

2023-03-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/26/23 4:41 PM, ryuukk_ wrote:

On Sunday, 26 March 2023 at 19:08:32 UTC, Steven Schveighoffer wrote:

On 3/26/23 2:07 PM, ryuukk_ wrote:

Hi,

It's common knowledge that accessing tls global is slow 
http://david-grs.github.io/tls_performance_overhead_cost_linux/


What i do not understand is the reasoning behind choosing tls global 
by default in D


If you know a variable is not `shared`, then you know it can only be 
accessed from the current thread. This has huge implications for 
thread access.


However, one problem that D has no good solution is passing 
thread-local data to another thread (to be owned by the new thread, 
and no access in the current thread). That's typically the most common 
use case for "shared data".




I haven't explored this use case, that must explain why i find it 
surprising, however, i read about other languages too, and they seem to 
be explicit whenever they make use of TLS


C, C++, Rust, Zig, Go doesn't do TLS by default for example


If you want to have the type system tell you when a variable is readable 
from other threads or not, you need to have *something* to distinguish 
them. 99% of all variables are not readable from other threads, so 
making that the default seems the right call to me.


I don't know if you have thought through the implications. Start with 
the requirement that I need to know by examining the type whether the 
value is viewable from multiple threads. Is there a better mechanism 
with better defaults? C/C++ is precisely the wrong answer -- just let 
the programmer fend for himself. I haven't used the others to know what 
their story is.


One possibility is to REQUIRE you to mark module-level and static 
variables as one of `__gshared`, `shared`, `immutable`, or `@tls`. I 
would be OK with such a change.


I've run into a situation where I want to make a thread local pointer to 
shared data, and it's not easy. The only solution I could come up with 
is to put it inside a dummy struct with a shared member. Having a `@tls` 
storage class would help solve that.


-Steve


Re: Why are globals set to tls by default? and why is fast code ugly by default?

2023-03-26 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/26/23 2:07 PM, ryuukk_ wrote:

Hi,

It's common knowledge that accessing tls global is slow 
http://david-grs.github.io/tls_performance_overhead_cost_linux/


What i do not understand is the reasoning behind choosing tls global by 
default in D


If you know a variable is not `shared`, then you know it can only be 
accessed from the current thread. This has huge implications for thread 
access.


However, one problem that D has no good solution is passing thread-local 
data to another thread (to be owned by the new thread, and no access in 
the current thread). That's typically the most common use case for 
"shared data".


-Steve


Re: Calling assumeSorted on const(std.container.Array)

2023-03-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/25/23 9:45 AM, Olivier Prat wrote:

Would someone explain the exact nature of this error as I fail to 
understand as how just telling that an Array ConstRange is assumed to be 
sorted actually modifies anything??


It's because a Range keeps a copy of the array (Array is a reference 
counted type). Since that is labeled `const`, then editing the Range is 
forbidden.


Inside SortedRange, it has this, which is causing the issue:

```d
static if (isForwardRange!Range)
@property auto save()
{
// Avoid the constructor
typeof(this) result = this;
result._input = _input.save;
return result;
}
```

Overwriting the input isn't possible here, because it contains a const 
member.


Now, this possibly could be fixed with something like:

`return typeof(this)(_input.save);`

But it might just push the error to another place.

The whole thing is kind of ugly.

There is a note inside the Array Range which says it's trying to work 
around some old bug that is now marked as "works for me", so maybe that 
can be reexamined.


https://github.com/dlang/phobos/blob/17b1a11afd74f9f8a69af93d77d4548a557e1b89/std/container/array.d#L137

-Steve


Re: Including parts of a diet template in another

2023-03-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/25/23 4:56 PM, seany wrote:

Hello

If we are creating a multipage Vibe.d application, we need to use diet 
templates. I can't find any info on how to include parts or whole of a 
diet template in another.


You can include an entire other diet template like:

```pug
include commondiv
```

Note that it gets copy-pasted as code, so it can use local 
symbols/functions you define in code islands.


I would also note that you can template the entire page (a common 
model), and allow other pages to inherit that common layout.


So something like:

layout.dt:
```pug
html
  head
// stuff in head (always the same)
  body
commondiv
  // always the same stuff here
block content
```

page1.dt:
```pug
extends layout
block content
  // all the page1 specific content
```

Which is what I use. I also define `extraCss` and `extraJs` blocks to 
allow for more customization in those sections.


-Steve


Re: Formatted date

2023-03-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/22/23 10:02 AM, Alexander Zhirov wrote:
Tell me, how can I use such a date conversion mechanism? I didn't find 
[something](https://www.php.net/manual/en/datetime.format.php) similar 
on the forum.


Convert date from received time

```
Clock.currTime().toSimpleString()
```

So that i can get a more readable look:

`2023-Mar-22 16:53:42.2507395` => `2023.03.22 16:53:42`


D's datetime intentionally does not tackle formatting -- it's a huge 
undertaking.


There is an option on code.dlang.org: 
https://code.dlang.org/packages/datefmt


-Steve


Re: What makes vibe.d Incredibly Slow on a VPS?

2023-03-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/18/23 9:36 AM, seany wrote:

But on a VPS server, the program outputs the first writeln line (not 
even the consequent req.form printouts), then apparently stops for 
several seconds ( 10 to 16) , and then suddenly starts working again. I 
see this in the log outputs.


Why does this happen? How can I start debugging?


Before getting into it any further, try flushing output after every writeln.

This is true in D and C too -- if your `stdout` stream is connected to a 
log file, it will *not* flush upon every newline. However, if it's 
connected to a terminal, it *will* flush upon every newline.


It's possible it is running just as fast as you expect, but the buffered 
output has not yet been flushed.


So just add `stdout.flush()` after every `writeln` call and see if it 
helps. If not, then it needs more investigation.


-Steve


Re: Best way to read/write Chinese (GBK/GB18030) files?

2023-03-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/12/23 8:32 PM, zjh wrote:

On Sunday, 12 March 2023 at 20:03:23 UTC, 0xEAB wrote:

...


Thank you for your reply, but is there any way to output `gbk` code to 
the console?




What is required is an addition to the `std.encoding` module, to allow 
such an encoding.


Encodings are simply translating some encoding (e.g. utf) to another 
(e.g. gbk). If you look at `std.encoding` you can get an idea of what it 
might require.


It will take some effort and especially some help from a knowledgeable 
user (such as yourself).


-Steve


Re: @nogc and Phobos

2023-03-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/11/23 7:04 AM, bomat wrote:

Hi all,

I am a C++ programmer in my "day job" and was playing around with D to 
maybe use it in a personal project.


I'm using Dear ImGui for the graphical user interface, for which I use 
this port:

https://github.com/KytoDragon/imgui/

It works fairly well so far, just one problem: Dear ImGui is obviously 
`@nogc`, and I noticed that it doesn't mix with standard library functions.
I tried `std.process.executeShell()` (which I'd kinda need for my 
project unless I want do do OS specific API calls), and 
`std.stdio.writeln()` (which I won't exactly be needing, just as a very 
basic test).


So my question is:
Is Phobos essentially incompatible to `@nogc`?
Or is there a trick for mixing GC code with non-GC code that I don't know?


Most of Phobos uses exceptions, which require the gc.



I'm assuming the second, for if the first was true I'd say that D would 
be pretty much useless when combined with non-D libs...


I think it is an error to mark a library which centers on callbacks with 
always being @nogc. You can work around nothrow and @safe, but not @nogc.


This also brings up a point that there just isn't a way to do a 
callback-centered library that can be simultaneously used with nogc or 
gc, unless you template based on that. It's not a good situation, and I 
don't know of a good solution.


-Steve


Re: vibe.d

2023-03-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/11/23 5:12 AM, seany wrote:

email.headers["Sender"] = "<"; // valid mail


Looks like an extra `<`, is that correct?

Exception while handling request POST /createNewOwner: 
object.Exception@/home/monsoon/.dub/packages/vibe-d-0.9.6-alpha.1/vibe-d/tls/vibe/stream/openssl.d(668): Connecting TLS tunnel: error:0A86:SSL routines::certificate verify failed (167772294)

```


Note that dub is running on localhost.

How can I resolve this? Please help. Thank you


Looks like an issue with the certificate, either on your vibe app or on 
the email server.


-Steve


Re: help: Unresolvable dependencies to package openssl

2023-03-08 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/8/23 7:52 PM, mw wrote:

Hi,

In my dub.json, I have:

```
     "dependencies": {
     "apache-thrift": "==0.16.0",
     ...
     }

     "subConfigurations": {
     "apache-thrift": "use_openssl_1_1",
     "pyd": "python39"
     },

```

But:

     $ dub build
     Unresolvable dependencies to package openssl:
   apache-thrift 0.16.0 depends on openssl ~>2.0.3
   apache-thrift 0.16.0 depends on openssl ~>1.1.6
   app ~master depends on openssl ~>2.0.3


Why the subConfigurations: "use_openssl_1_1":

https://github.com/apache/thrift/blob/master/dub.json#L26

     {
   "name": "use_openssl_1_1",
   "versions": ["use_openssl_1_1_x"],
   "dependencies": {
     "openssl": {
   "version": "~>2.0.3"
     }
   }
     }

did not pick up the 2.0.3? but report conflict instead?

Thanks.


This is a known limitation -- dub builds the selections file based on 
*all* configurations in the file. If you have conflicting ones, it will 
not know what to pick.


However, if you manually construct the selections file, then it will work.

See https://github.com/dlang/dub/issues/1217

-Steve


Re: dub.sdl bindbc-glfw is returning a deprecation warming. So what do I do now?

2023-03-08 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/8/23 7:21 PM, WhatMeWorry wrote:

my small dub.sdl project uses:

dependency "bindbc-glfw"  version="~>1.0.1"
versions "GLFW_33"

and returns

Building bindbc-glfw 1.0.1: building configuration [dynamic]
C:\Users\Admin\AppData\Local\dub\packages\bindbc-glfw-1.0.1\bindbc-glfw\source\bindbc\glfw\binddynamic.d(557,11):
 Deprecation: variable `bindbc.loader.system.bindWindows` is deprecated


So now what?  I'm pretty sure deprecation means to replace with 
something better
but what would that be?   I looked on github code in binddynamic.d at 
line 557 and

the package info at the DUB web site and I'm still clueless.


It's newly deprecated, without much explanation:

https://github.com/BindBC/bindbc-loader/commit/d13d7f246f325472b26282cfac8d2b02b26eccac

Last commit to bindbc-glfw is from last year, so it makes sense why it 
is triggering this.


I feel it was in error to deprecate symbols without bumping the major 
revision.


-Steve


Re: Best way to read/write Chinese (GBK/GB18030) files?

2023-03-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/6/23 8:45 PM, John Xu wrote:
I'm new to dlang. I didn't find much tutorials on internet about how to 
read/write Chinese easily. std.encoding doesn't seem to support GBK or 
GB18030:


"Encodings currently supported are UTF-8, UTF-16, UTF-32, ASCII, 
ISO-8859-1 (also known as LATIN-1), ISO-8859-2 (LATIN-2), WINDOWS-1250, 
WINDOWS-1251 and WINDOWS-1252."


It appears that encoding is not supported.

There is a scant mention of it, in the BOM detection. But I don't think 
there's any mechanism to encode/decode it.




Then what is best way to read GBK/GB18030 contents ? Even GBK/GB18030 
file names ?





D has direct bindings to C, so possibly using a C library. I don't see 
anything jumping out at me from code.dlang.org


-Steve


Re: How to build a static lib properly?

2023-03-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/5/23 9:09 PM, ryuukk_ wrote:

On Monday, 6 March 2023 at 02:00:16 UTC, Mike Parker wrote:


This is not dub's fault. When building a shared library, there's a 
link step, so any external dependencies are linked into the shared 
library just as they are with an executable. There is no link step 
with a static library. That means when you build your executable, you 
need to also link the static library's dependencies along with it.


Most of the symbols in your list appear to come from the packages 
listed in the dependencies section of DCD's dub.json:


https://github.com/dlang-community/DCD/blob/master/dub.json

So if you want to do this manually, with DCD as a static library, then 
you also need to build all of those dependencies and link them with 
your executable.




Well, you can create a library that contains all the static libraries, 
you just can't use dub to do it for you automatically, or even manually 
(dub ignores `.a` files when specified as source files).


dub should build a static library for the project i build, that includes 
each library it uses that are referenced as "library" since the default 
is "staticLibrary" according to rikki




Dub expects to have dub-built artifacts available to link. This problem 
only occurs if you are building outside of dub, without proper 
dependency management.


Dub indeed does not play nice with exporting artifacts for other build 
systems. It's something that should be addressed.


Keep in mind though, that you still need to specify any shared library 
dependencies, since static libs cannot contain shared libraries or 
automatic references to them.


-Steve


Re: Use dub to create source lib and executables

2023-03-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/4/23 1:33 PM, Chris Piker wrote:

Hi D

I normally work in a *nix environment, typically on server-side code.  
For many projects I have gnu makefiles that build a small lib along with 
command line utilities.


Up to now I've been creating a dub.json file for just the sourceLibrary, 
and then putting embedded dub comments at the top of each of the utility 
programs.  The utilities are built via `dub build --single` and a thin 
makefile triggers all the dub commands.


This method is inefficient, and it won't work in a typical Windows dev 
environment, so today I'm trying to remove gnu make from the picture.  
Going back to basics, does anyone know of a clear example of how to 
convert this simplified makefile into 1-N dub files?:


```makefile
# Build library + utility programs.
# Lib sources are in "libsrc", 1-file programs in "utils"

# Implicit rule to make a utility program
outdir/%:utils/%.d outdir/mylib.a
     dmd -I libsrc -od=outdir -of=$@ $^

# Top level build rule for everything
build:outdir/mylib.a outdir/prog1 outdir/prog2 | outdir

# Explicit rule to make output directory if not present
outdir:
     @if [ ! -e outdir ]; then mkdir outdir; fi

# Explicit build rule for the library
outdir/mylib.a:libsrc/mod1.d libsrc/mod2.d
     dmd -lib -od=outdir -of=$@ $^
```
This is a paired down example since `make test` and `make install` 
aren't present, but I hope the main ideas are apparent.


I've been at it now for about four hours, with lots of web-searches 
(btw, thanks to schveiguy for getting me this far) but I haven't figured 
out what hierarchy of dub constructs I need to create to order to get 
the effect of the small make file above.


Thanks for considering the question,




If you mean that you have multiple subprojects inside your main dub 
project, my advice is to follow what other such projects do. I always 
look at vibe for my example.


dub isn't great when it comes to the "one true way" to specify this. You 
can actually create a dub subproject inside your dub file, or create dub 
files inside all your other subproject folders, and tag them as 
subprojects of the main project.


I've tried both ways, and I find the latter to be easier to deal with. 
This is what vibe does.


-Steve


Re: dub.selections.json & optional dependencies: How's it work?

2023-02-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/24/23 2:01 PM, jmh530 wrote:
I'm looking at the dub package format [1] about optional dependencies 
and it says:


"With this set to true, the dependency will only be used if explicitly 
selected in dub.selections.json. If omitted, this attribute defaults to 
false."


And it occurs to me that I don't know anything about how 
dub.selections.json works.


Let's say you have dependency A, which has an *optional* dependency on B.

In your project, if you depend on A, but don't explicitly depend on B, 
then A will be built without B as a dependency.


If you have a dependency on A *and* B, then B's optional dependency will 
kick in, and participate in the selection of it's version.


So for instance, you could depend on B version 1 or higher, and the 
optional dependency could be on v1.5 or higher, it will select the 
highest version of 1.5


dub.selections.json only applies to the primary project. So the decision 
on which versions of which dependencies to use is decided by the whole tree.


-Steve


Re: Template alias parameter: error: need 'this' for ...

2023-02-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/24/23 7:00 AM, Elfstone wrote:


Seems like the same bug is still there after ten years.



`static` should not affect module-level functions, but also, this code 
should work without `static`.


Reported, not sure if there's a previous bug, it was hard to come up 
with a good description:


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

-Steve


Re: Lazy and GC Allocations

2023-02-20 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/20/23 1:50 PM, Etienne wrote:

On Monday, 20 February 2023 at 02:50:20 UTC, Steven Schveighoffer wrote:

See Adam's bug report: https://issues.dlang.org/show_bug.cgi?id=23627



So, according to this bug report, the implementation is allocating a 
closure on the GC even though the spec says it shouldn't?


The opposite, the delegate doesn't force a closure, and so when the 
variable goes out of scope, memory corruption ensues.


I've been writing some betterC and the lazy parameter was prohibited 
because it allocates on the GC, so I'm wondering what the situation is 
currently


It shouldn't. Now, lazy can't be `@nogc` (because that's just what the 
compiler dictates), but it won't actually *use* the GC if you don't 
allocate in the function call.


I just tested and you can use lazy parameters with betterC.

-Steve


Re: Lazy and GC Allocations

2023-02-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/19/23 9:15 PM, Steven Schveighoffer wrote:
Indeed, you can't really "save" the hidden delegate somewhere, so the 
calling function knows that the delgate can't escape.


I stand corrected, you can save it (by taking the address of it).

And it's explicitly allowed by the spec.

But it still doesn't allocate a closure!

See Adam's bug report: https://issues.dlang.org/show_bug.cgi?id=23627

-Steve


Re: Lazy and GC Allocations

2023-02-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/19/23 7:50 PM, Etienne wrote:

Hello,

I'm wondering at which moment the following would make an allocation of 
the scope variables on the GC. Should I assume that the second parameter 
of enforce being lazy, we would get a delegate/literal that saves the 
current scope on the GC even if it's not needed? I'm asking purely for a 
performance perspective of avoiding GC allocations.


```
void main() {
  int a = 5;
  enforce(true, format("a: %d", a));
}
```


enforce takes a lazy variable, which I believe is scope by default, so 
no closure should be allocated.


Indeed, you can't really "save" the hidden delegate somewhere, so the 
calling function knows that the delgate can't escape.


-Steve


Re: Big struct/class and T.init

2023-02-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/19/23 1:26 PM, Steven Schveighoffer wrote:

Testing with run.dlang.io, switching between `char` and `int` changes 
the ASM output to show whether it's stored or not.


And BTW, you can override this by assigning a zero default:

```d
struct S
{
char[16384] array = 0; // no .init storage
}
```

-Steve


Re: Big struct/class and T.init

2023-02-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/19/23 1:11 PM, Guillaume Piolat wrote:

If my understanding is correct, the mere fact of having a:


     struct S
     {
     char[16384] array;
     }

And then using it anywhere, will necessarily lead to a S.init being 
created and linked, leading to a binary size inflation of 16kb.

This is not a super high concern, but can inform design decisions.

Is this correct?


Yes.

that's not the case for all-zero .init though. At least in 
`TypeInfo.initializer`, it's pointing to null with array size indicating 
the amount of zeroes to write.


Testing with run.dlang.io, switching between `char` and `int` changes 
the ASM output to show whether it's stored or not.


-Steve


Re: How can I easily determine the last charachter of a file?

2023-02-14 Thread Steven Schveighoffer via Digitalmars-d-learn

```d
myFile.seek(-1, SEEK_END);
ubyte c[1];
myFile.rawRead(c[]);
if(c[0] == '\n') // ends in newline
```

-Steve


Re: Simplest way to convert an array into a set

2023-02-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/13/23 1:04 PM, Matt wrote:
Obviously, there is no "set" object in D, but I was wondering what the 
quickest way to remove duplicates from an array would be. I was 
convinced I'd seen a "unique" method somewhere, but I've looked through 
the documentation for std.array, std.algorithm AND std.range, and I've 
either missed it, or my memory is playing tricks on me. That, or I'm 
looking in the wrong place entirely, of course


If you sort, you can use the `std.algorithm.iteration.uniq` function to 
get that information. I don't believe there's a specific method to 
remove duplicates in place.


Also, although there isn't a set type, you can use `bool[T]` as a crude 
set type.


-Steve


Re: My vibe-d test app is crashing on Windows

2023-02-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/13/23 8:12 AM, Steve wrote:
The app is just a test echo server. JSON sent in the body of a POST 
request is echoed back to the client. On Pop!_OS it works fine but on 
Windows it responds, there's a delay of about 10 seconds and then it 
crashes with the error:


```
Error Program exited with code -1073741819
```



As mentioned, that's an access violation. So something is wrong in the 
vibe library on windows.


I confirmed it works fine for me on Linux.

Did you try without the async call? Try and reduce which part of it is 
causing the failure.


Also when you launch/build the app with dub there's a shed load of 
deprecation warnings, e.g.:

```
\Local\dub\packages\vibe-d-0.9.5\vibe-d\stream\vibe\stream\wrapper.d(334,23): 
Deprecation: reference to local variable `this` assigned to non-scope parameter 
`bytes` calling `writeToStream`
```

I'm a D newbie so it's quite possibly something I'm doing wrong ...


This is the hellscape that we are in for with dip1000 around the corner. 
It's not your fault, many many programs/libraries have not been updated 
to deal with dip1000, and it likely will be this way for a while.


-Steve


Re: ddbc with Vibe-d

2023-02-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/12/23 3:29 PM, Steve wrote:

In my case args will just be the body of the HTTPServerRequest which is 
JSON. How can I get that JSON and pass it to async() in a manner that 
ensures I get a worker thread?


I think it needs to be immutable if it's a reference.

-Steve


Re: How does the function 'iota' get its name?

2023-02-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/12/23 2:17 PM, ccmywish wrote:

Hi, everyone!

I'm very new to D. I see a function called 
[iota](https://dlang.org/library/std/range/iota.html)


`Iota` seems a [Greek letter](https://en.wikipedia.org/wiki/Iota). Why 
does it relate to range?


It came from C++. See notes here: 
https://en.cppreference.com/w/cpp/algorithm/iota


-Steve


Re: ddbc with Vibe-d

2023-02-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/12/23 1:01 PM, Steve wrote:

On Sunday, 12 February 2023 at 15:24:14 UTC, Steven Schveighoffer wrote:
Any synchronous calls will just be synchronous. They aren't going to 
participate in the async i/o that vibe uses.


In other words, when you block on a call to sqlite, it will block 
everything else in your web server until that completes.





Would this be the correct approach to stop it blocking?:
```d
auto result = async(, args...).getResult();
```


That might work, depending on args. As documented in the API, if 
anything in args are mutable references, then it is run as a task, and 
the same problem still applies (it will use a fiber, and count on the 
concurrency of vibe's fibers to deal with the asynchronicity).


If it is possible, it will run in a worker thread, and then it can 
execute concurrently.


I believe you can do:

isWeaklyIsolated!(typeof(args))

to see if it will run in another thread.

I admit not having any experience with this function.

-Steve


Re: ddbc with Vibe-d

2023-02-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/12/23 6:05 AM, Steve wrote:

Hi,

I'm trying D for the first time and so far I'm really impressed with 
both D and vibe-d.


My test project is an application server and I want to use SQLite3 as 
its database. I understand Vibe.d uses an async model under the hood and 
so my question is are Vibe-d and ddbc compatible?


Thanks.


Any synchronous calls will just be synchronous. They aren't going to 
participate in the async i/o that vibe uses.


In other words, when you block on a call to sqlite, it will block 
everything else in your web server until that completes.


There are several projects that are built to work with vibe-d sockets. 
mysql-native is one, and vibe-d-postgresql is another.


I don't know if there is an sqlite project that is vibe-specific. But 
sqlite typically is using files anyway, or maybe even memory, so you 
aren't waiting on network i/o.


-Steve


Re: Gneric linkedList range adaptor

2023-02-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/10/23 5:10 PM, Ben Jones wrote:
I'm trying to write a range adaptor for linked list types.  The range 
type seems to work OK, but my helper function to deduce the node type 
has a compiler error.  My hunch is that `nextField` loses its 
association with T when I'm trying to pass it as a template parameter 
inside the helper method, but I can't use __traits(child) there to fix it.




This seems like a bug in the compiler.

I did try simplifying, whereas, instead of `T` being a pointer, I just 
used `T*` everywhere, and things got a lot simpler.


But it still fails in the same way.

The fact that explicitly specifying the `T` instead of using IFTI works 
suggests for sure that the compiler should accept it.


-Steve


Re: How to write a library

2023-01-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/21/23 5:53 PM, Matt wrote:
I am trying to write a graphics engine for my university capstone 
project, and really wanted to give it a try in D, as both a talking 
point, and because I love the language. I'm using dub to build the 
library, and the demo application that'll use it.


However, I've come across a problem. In C/C++, when you build a library, 
you compile and link the source, then provide the header files for the 
library user to include. I have built the library, but what is the D 
equivalent to header files, and what do I have to do to prepare and use 
my library in another project?


D uses modules, not header files. So no header files are *necessary*.

However, there is one case where you might want to use import files (D's 
equivalent to header files), and that's if you want to declare a 
specific API without providing the implementation.


For a project such as a university project, I would say this isn't 
necessary, as you don't need to obscure the implementation source from 
the users of your library.


If you do want to look into import files, for D, they are `.di` files, 
and should include prototypes for all the public functions you are 
providing, and definitions for all the types. Templates need to be 
included fully implemented source code, not just prototypes (just like C++).


-Steve


Re: Is there a way to get a template’s parameters and constraints?

2023-01-20 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/20/23 12:15 PM, Quirin Schroll wrote:
Is there a trait (or a combination of traits) that gives me the 
constraints of a template?


Example:
```D
void f(T1 : long, T2 : const(char)[])(T x) { }
template constraintsOf(alias templ) { /*Magic here*/ }
alias constraints = constraintsOf!f; // tuple(long, const(char)[])
```

At the moment, I care about constraints that are types. I don’t care 
about value or alias constraints (e.g. `opBinary(string op : "+")(..)` 
or `f(alias x : something)()`, but if it works for types, it should 
probably work for other constraints as well.


For what I want, `constraintsOf` may expect every template parameter to 
be a type and to have a constraint.


No, there is no way to introspect anything about a template's details 
until its instantiated.


-Steve


Re: Non-ugly ways to implement a 'static' class or namespace?

2023-01-20 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/20/23 6:28 AM, thebluepandabear wrote:


This type of semantics is not possible in D, which sucks.


Well, static methods do exactly this.

If you want to disable class creation, then use `@disable this();`, if 
you want to make all methods static, put `static:` at the top of the class.


Note that at this point, the class becomes a namespace. You can use a 
template as a namespace as well, though it can be a bit ugly:


```d
template Algo_ns()
{
   void drawLine(Canvas c, Pos from, Pos to) {...}
}

// need this to avoid the instantiation syntax
alias Algo = Algo_ns!();
```

The benefit here is that other things that classes do (generate 
typeinfo, add to the type system, etc.) would be wasted, so this is not 
done for a template.


-Steve


Re: How to Add CSS and JS to vibe.d templates

2023-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/23 11:44 PM, seany wrote:

Hi

Howcan one add CSS and JS to vibe.d templates? Here is my setup (vibe.d 
project initiated with dub using dub init myproject vibe.d):


./public:
main.css  main.js

./source:
app.d

./views:
auth2fa.dt  fail.dt  login.dt  pair.dt  passfail.dt  userfail.dt


I am trying to add a css file using `link(rel="stylesheet", 
type="text/css", href="main.css")` in the diet templates, but it has no 
effect. I took the files from here: 
https://codepen.io/ricardoolivaalonso/pen/YzyaRPN


Keep in mind, this literally translates to a `link` tag in the HTML. So 
here is what happens:


1. your vibe project is running, and passes out the compiled template to 
the browser.
2. The browser sees the link tag, and attempts to ask the server for the 
file "main.css"
3. The vibe project tries to match that to its routes, and cannot find 
it, and so returns an error.


So this takes 2 steps to remedy:

1. Register a `serveStaticFiles` route with the glob `public/*`. See the 
docs here: https://vibed.org/api/vibe.http.fileserver/serveStaticFiles
2. Change your link to refer to `public/main.css`, instead of just 
`main.css`.


This is how it looks in my code:

```d
 router.get("/public/*", serveStaticFiles(""));
```

And the links look like:

```pug
link(rel="stylesheet",href="/public/css/flatpickr.min.css")
```

as an example. Note that I put my css files into a css subdirectory 
under public, and my javascript files under a js subdirectory. It all 
depends on how you want to set it up.


-Steve


Re: What is the 'Result' type even for?

2023-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/23 10:34 PM, Ruby The Roobster wrote:

On Friday, 20 January 2023 at 03:30:56 UTC, Steven Schveighoffer wrote:

On 1/19/23 10:11 PM, Ruby The Roobster wrote:
...

The point is to be a range over the original input, evaluated lazily. 
Using this building block, you can create an array, or use some other 
algorithm, or whatever you want. All without allocating more space to 
hold an array.




I get the point that it is supposed to be lazy.  But why are these basic 
cases not implemented?  I shouldn't have to go write a wrapper for 
something as simple as casting this type to the original type.  This is 
one of the things that one expects the standard library to do for you.


A range simply does not provide the API you are seeking. It provides 3 
methods:


front
popFront
empty

That's it. It does not provide appending. If you want appending or 
random access, use an array:


```d
auto c = "a|b|c|d|e".split('|');
static assert(is(typeof(c) == string[]));
// or:
auto c2 = "a|b|c|d|e".splitter('|').array; // convert range to an array
```

-Steve


Re: What is the 'Result' type even for?

2023-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/23 10:11 PM, Ruby The Roobster wrote:

Take this example:

```d
import std;
void main()
{
     auto c = "a|b|c|d|e".splitter('|');
     c.writeln;
     string[] e = ["a", "b", "c", "d", "e"];
     assert(c.equal(e));
     typeof(c).stringof.writeln;
}
```

The program prints:

["a", "b", "c", "d", "e"]
Result

What is the purpose of this 'Result' type?  To serve as a generic 
range?  Because, it seems to only cause problems.  For example, you 
cannot assign or cast the result type into a range, even when the type 
has the same inherent function:


```d
string[] c = "a|b|c|d|e".splitter('|'); // fails
string[] d = cast(string[])"a|b|c|d|e".splitter('|'); // also fails
```


The `Result` type is an internal type that provides a lazily-evaluated 
range of the original string. That is, no array is allocated, and the 
actual searching of the `|` character isn't done until you start 
fetching each element.


It returns windows into the *original* string, and builds each window 
one element at a time (via slicing).


So when you say "cast to a range", you are incorrectly stating the type 
`string[]` as a "range", when you are trying to cast to an array of 
strings. The `Result` type *is* a range, it's a range of strings. But it 
is not an array. If you want an array, you can use the `split` function, 
which allocates an array to hold all the slices.



And if you need to perform a set operation?

```d
c[] ~= "lolno"; // fails, as [] isn't defined for Result.
```


Right, because a `Result` is not an array. Appending is an array 
operation, not a range operation.


Then what is the point of this type, if not to just make things 
difficult?  It cannot be casted, and vector operations cannot be 
performed, and it seems to just serve as an unnecessary generalization.


The point is to be a range over the original input, evaluated lazily. 
Using this building block, you can create an array, or use some other 
algorithm, or whatever you want. All without allocating more space to 
hold an array.


-Steve


Re: Vibe.d Diet Templatesand Forms

2023-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/23 6:24 PM, seany wrote:

Hello

Please consider this diet template:

     doctype html
     html(lang="es", dir="ltr")
     head
     meta(name="viewport", content="width=device-width, 
user-scalable=no, initial-scale=1.0")

     meta(charset="utf-8")
     link(rel="stylesheet", type="text/css", href="main.css")
     href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700;800=swap; rel="stylesheet">


Did you mean to include straight HTML here? I don't think that is supported.

Please notice the line `form(id= ...`. This line is causing the 
following error:





     login.dt(29,45): Error: found `method` when expecting `;` 
following `return` statement

     login.dt(29,51): Error: found `=` instead of statement
     login.dt(28,12): Error: missing closing `)` after `if ("form"`
     login.dt(28,21): Error: found `)` when expecting `;` following 
statement

     login.dt(28,36): Error: found `method` when expecting `)`
     login.dt(28,42): Error: found `=` when expecting `)`
     login.dt(28,43): Error: found `""` when expecting `)`
     login.dt(28,45): Error: found `)` instead of statement
/root/.dub/packages/diet-ng-1.8.1/diet-ng/source/diet/html.d(246,8): 
Error: template instance 
`diet.html.compileHTMLDietFileString!("login.dt", contents, 
DefaultDietFilters).exec!(StreamOutputRange!(InterfaceProxy!(OutputStream), 1024LU))` error instantiating

/root/.dub/packages/vibe-d-0.9.5/vibe-d/http/vibe/http/server.d(351,66):    
instantiated from here: 
`compileHTMLDietFileString!(StreamOutputRange!(InterfaceProxy!(OutputStream), 
1024LU))`
     source/app.d(41,5):    instantiated from here: 
`render!"login.dt"`



What is the problem? How can I resolve it? Thank you.


The easiest way to see what the diet compiler is producing is to 
uncomment the line that outputs the compiled file to the console during 
compilation. That is located here: 
https://github.com/rejectedsoftware/diet-ng/blob/856bf6d75127955565b3b5edd9b1f4418b8ec7c3/source/diet/html.d#L234


With that being said, how diet works is to convert the diet template 
directly into D code. It relies on the translation to produce valid D 
code (no specialized parsing or semantic-aware processing is done, it's 
just a direct translation from diet AST to D). What is happening here is 
the diet compiler is not producing valid D code. This can happen when 
there are bugs, but usually only when there are D "escapes", which don't 
correctly set up the syntax (like if you include a curly brace, which 
isn't expected)


However, in your code, I don't see any "escapes", so I'm not sure what 
could cause it there.


I will note that most of the time, when I get diet errors like that the 
error is not on that specific line, but on something that happened 
before to confuse the D compiler. That html `link` node might be the 
issue, but again, I'm not sure what is intended there.


-Steve


Re: Nested sibling classes

2023-01-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/12/23 12:05 PM, seany wrote:

How can I make it, that classes b and c can access each other, and 
create instances of each other freely? Thank you.




So to just point out something that wasn't discussed by Salih:

When you declare a field of a class with an initializer, *that 
initializer is run at compile-time*. Which means, that even if it did 
work, every instance of every b would start out with the same exact `C` 
object (not a copy, the same one).


This is different than many other languages which treat initializers as 
part of the constructor (and run when you initialize a class). In D, the 
bits are simply copied into the new memory as the default state.


For this reason you should almost *never* initialize a class reference 
in a non-static field. Consider that if you ever modified that instance 
named `C`, all new instances of `b` would have a reference to that 
modified instance!


The reason the compiler doesn't like it is because it doesn't know how 
to initialize a `c` at compile time, since it needs the context pointer 
to the outer class.


Just moving initialization into the constructor should fix the problem, 
you don't need to make them static. Now, maybe you didn't intend to have 
a nested class with a reference to the outer class, and in that case, 
you should make it static.


-Steve


Re: enum functions

2023-01-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/10/23 7:55 AM, Adam D Ruppe wrote:

On Sunday, 8 January 2023 at 18:42:58 UTC, Salih Dincer wrote:
I'm wondering 2 things; firstly, does having an enum mean there is no 
auto-return? Or could it be CTFE?


It means nothing. The keyword tells the parser a function is about to 
begin, which triggers return type inference (exactly the same as 
`auto`), but otherwise it is completely ignored.


Mostly correct. `enum` is a storage class, which means a *declaration* 
is about to begin. Once the declaration is decided as a function 
definition, type inference is performed, and the storage class is 
checked to see how it affects the declaration. In some cases, there is 
an effect, in some there is not.


```d
static foo() {} // static does nothing here
final bar() {} // final does nothing here
enum baz() {} // enum does nothing here
__gshared fun() {} // __gshared does nothing here

struct S
{
   // return type is int *, `this` (unused) is const
   const foo() { return new int; }
   // same for immutable, shared, inout
}
```

Aside from the const/immutable/shared/inout storage classes (which do 
affect semantics, but maybe in slightly confusing ways) there are some 
which are pretty obvious and also work with type inference:


1. deprecated
2. extern
3. abstract
4. override
5. synchronized
6. auto
7. scope
8. nothrow
9. pure
10. ref

-Steve


Re: what wrong with this alias

2023-01-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/8/23 12:42 AM, Qusatlegadus wrote:

     auto s = 1234.to!string.map!q{a - '0'}.sum;
works fine.


but if i do an alias

     alias comb = to!string.map!q{a - '0'}

     Error: unknown, please file report on issues.dlang.org

What's wrong with this alias?


Aside from the problem with the code, that error alone deserves a bug 
report so...


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

-Steve


Re: Address of a class object

2023-01-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/4/23 2:27 PM, Ali Çehreli wrote:

On 1/4/23 10:48, H. S. Teoh wrote:

 > Allocations are not necessarily consecutive; the GC may have its own
 > strategy of allocation that doesn't follow a linear sequence.

That was one of my guesses. So, I put the objects into a 2-length static 
array but the difference was still 0x20. (?)


Are you putting the class *references* in a 2-length static array? 
That's just going to be 2 pointers in an array, and won't affect where 
they are allocated on the heap.



 > Furthermore, GC-allocated blocks may be larger than the request size
 > because there may be some extra management information stored in the
 > block (but outside the pointer range returned).

Good point. I think the minimum size of a dynamically allocated memory 
of the current GC implementation is 32 bytes.


It is 16 bytes, but there are no 24-byte bins. Here are the bin sizes:

https://github.com/dlang/dmd/blob/4dc7259a89950b0a0feda05b8c35e52cadd00c95/druntime/src/core/internal/gc/impl/conservative/gc.d#L1402-L1424

And of course, this could change again.

Basically, follow H. S. Teoh's advice, stop worrying about the addresses 
given out by the GC, it's not important.


-Steve


Re: Is there such a JSON parser?

2023-01-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/1/23 6:28 PM, torhu wrote:
I need to parse some JSON data into various data structures, so I'm 
looking for a parser based on events or ranges. One that doesn't just 
load the file and build a data structure that represents the whole 
thing. So not std.json, at least.


It's pretty rough-edged, but https://code.dlang.org/packages/jsoniopipe 
will do this. It has mechanisms to jump to specific object members, and 
to rewind to a cached point. It does not use any intermediate 
representation.


-Steve


Re: Compile time vs run time -- what is the difference?

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

On 12/27/22 9:31 PM, thebluepandabear wrote:
I am reading through the free book on learning D by Ali Çehreli and I am 
having difficulties understanding the difference between compile time 
execution and run time execution in D language.


Compile time execution is running your code being compiled *while being 
compiled*. It allows you to generate compile-time data without having to 
write specialized "compile time only" constructs like templates or 
explicitly marked functions (as other languages typically do).


Compile time data doesn't consume any runtime to execute, it's already 
done by the time your binary is running. It also is usable *at compile 
time*, for things like `static if`, or `mixin`.


The intermediate language being executed is the parsed and semantically 
analyzed AST nodes.


-Steve



Re: Can you simplify nested Indexed types?

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

On 12/27/22 10:31 AM, Sergei Nosov wrote:

On Tuesday, 27 December 2022 at 15:20:24 UTC, Salih Dincer wrote:

On Tuesday, 27 December 2022 at 15:09:11 UTC, Sergei Nosov wrote:

Consider, I have the following code:

```d
    auto a = [3, 6, 2, 1, 5, 4, 0];

    auto indicies = iota(3);
    auto ai = indexed(a, indicies);
    //ai = indexed(ai, iota(2));

    writeln(ai);
```


I confuse about comment line that I mark...

SDB@79


Not sure I'll be more helpful, but I'll try to add more details.

I have an array and I use `indexed` on it. Conceptually, I now have a 
second array, but it doesn't exist in memory explicitly - only a 
function to map indicies from "second array" to "first array" is stored; 
all the values are stored once - in the "first array".


Now, I want to have third array that will do the same trick with the 
second array. The problem is that the second array is not really an 
array (but, conceptually, it is an array with random access). If I 
create a new variable with `auto` as type - obviously, it works. But can 
I use the same variable I used to store the "second array"? (In the 
provided code that doesn't work because of the type mismatch).


So the short answer is no.

The long of it is that Indexed is using a source range to give it 
indexes. In order to save it as the same type, you need to resolve the 
source of the indexes, when indiexed with the new source range, into the 
same type, which is not something the library can do. It would have to 
be specialized to recognize it's using iota as the index range, and then 
transform the iotas into one iota call. Which isn't impossible, but 
would be something specialized to this problem.


What could be an answer is to have a function that takes 2 iotas, and 
provides the values as if you were applying the indexes of one to the 
other, something like:


```d
iota!T translate(T)(iota!T orig, iota!T mapping)
{
   // you write this part
}
```

Then you can possibly define a function that can convert it properly.

-Steve


Re: Preventing nested struct destructor accessing stack frame

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

On 12/16/22 7:17 AM, Nick Treleaven wrote:

This code segfaults when the GC calls the dtor after the unittest succeeds:

```d
unittest
{
     int i;
     struct S
     {
     ~this() { i++; }
     }
     (*new S).destroy;
}
```

It seems destroy clears the context pointer. Is there a way to test if 
the context pointer is null in the dtor, to prevent the increment?


Check if the struct is the init value?

```d
~this() { if(this !is this.init) ++i;}
```

Not ideal I guess, because really it's the context pointer you care about.

-Steve


Re: Confusion about `Random`

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

On 12/23/22 10:07 AM, jwatson-CO-edu wrote:

On Friday, 23 December 2022 at 00:58:01 UTC, Steven Schveighoffer wrote:
Without the rest of the code, and how random is called, I have a 
hunch... Are you using threads by any chance?


If, for instance, your calls to rand01 are done in a new thread, that 
new thread will have a *default* state of Mt19937.


Good question, Steve, but I do not intentionally start any threads.  
Below is the machinery that interprets a for-loop.  Do you see anything 
that would enclose a previous state of the RNG?




Your code looks like it's making a function pointer, and that function 
pointer directly uses the global RNG.


I'm not seeing how your code could be copying the RNG somehow, as I'm 
assuming it's not manipulating the generated code from the compiler.


If it's not a threading problem, the only other possibility I can think 
of is that your loop code is not truly calling that function over and over.


I'd start instrumenting rand01 with some printouts, and see if it's 
doing what you expect. If it's not, throw and catch an exception, and 
print the stack trace (or use a debugger) to help understand what is 
happening.


I have been puzzled in the past with behavior that seemed to be 
reasonable, but given the way the implementation happened, did 
unexpected things (like caching values).


-Steve


Re: Confusion about `Random`

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

On 12/22/22 11:23 AM, jwatson-CO-edu wrote:
I am confused about why Program 1 produces random output but Program 2 
does not.


---

### Program 1
```d
import std.stdio;
import std.conv;
import std.random;

Mt19937 rnd;

double rand01(){
     // Uniform random sampling in [0,1)
     return uniform( 0.0, 1.0, rnd);
}

void main(){
     rnd = Random( unpredictableSeed );
     for( uint i = 0; i < 6; i++ ){
     writeln( rand01() );
     }
}
```

Output:
```
0.35332
0.0687847
0.563096
0.37718
0.321598
0.530525
```

---

### Program 2
 sparrow_core.d
```d
// ...

Mt19937 rnd; // Randomness

void init_random(){
     // Seed the RNG with the clock
     rnd = Random( unpredictableSeed );
}

// ...

double rand01(){
     // Uniform random sampling in [0,1)
     return uniform( 0.0, 1.0, rnd);
}

// ...

// Build a dict of primitive symbols
primitiveSymbols["rand"] = function Atom*(){
     // Random number on [0,1)
     return new Atom( rand01() ); // Construct an Atom holding a random 
value

};

// ...

void init_SPARROW(){
     // Populate necessary global structures
     init_reserved(); // - Reserved symbols
     init_env(); // -- Global context
     init_primitives(); // Special atoms and Primitive Functions
     init_specials(); // - Special forms
     init_random(); // --- RNG
}
```

 app.d
```d
void main( string[] args ){

     Atom* res = null;

     if( _DEBUG_VERBOSE )  writeln( "Args are: " ~ args.to!string );

     // Populate necessary interpreter components
     init_SPARROW();

     // ... Interpreter repeatedly invokes primitive symbol "rand"

}
```

Output:
```
0.961451
0.961451
0.961451
0.961451
0.961451
0.961451
```

Note: I have enclosed `uniform` so deeply because I am implementing the 
random number feature of a [computer 
language](https://github.com/jwatson-CO-edu/SPARROW).


---

What is the reason for this? Has the compiler optimized away the 
`uniform` call to a single double number?

What is the main difference between Program 1 and Program 2? Both seem to:
* Have a global RNG `rnd`
* Seed RNG after `main` starts.
* Generates a random number on [1,0) from a function.

So I would expect both programs to behave the same...




Without the rest of the code, and how random is called, I have a 
hunch... Are you using threads by any chance?


If, for instance, your calls to rand01 are done in a new thread, that 
new thread will have a *default* state of Mt19937.


I tried out just a non-seeded instance, and it did not produce that 
exact number, so this may not be the case.


But in case you are, you should be aware that globals get one instance 
per thread, and are default initialized.


-Steve


Re: How to use version in dub?

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

On 12/13/22 3:35 PM, ryuukk_ wrote:

On Tuesday, 13 December 2022 at 20:01:40 UTC, torhu wrote:

On Tuesday, 13 December 2022 at 19:50:15 UTC, torhu wrote:

On Tuesday, 13 December 2022 at 19:28:44 UTC, Leonardo A wrote:

Hello. How to use version in dub?

https://dlang.org/spec/version.html
"The version level and version identifier can be set on the command 
line by the -version"


I tried everything but noting.


In SDL syntax, either at the top level, in a configuration, or build 
type:


```
versions "something" "other"
```


To be more clear: When using dub you need to put this in the dub file, 
dub.sdl or dub.json. If you want to be able to choose from the command 
line, use a configuration:


```
configuration "something" {
    versions "something"
}
```

Then you can do:
```
dub build -c=something
```


How can this be the official solution?

It should be as easy as dub build -v "something"


Arbitrary version specification is pretty suspect. For optional version 
support, there should be an official configuration that does the right 
thing, and then you select that configuration.


You also can do `DFLAGS="-version=something" dub` if you like to live on 
the edge.


-Steve


Re: How to compiler dlang code on Apple M1?

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

On 12/13/22 10:20 AM, Steven Schveighoffer wrote:
Yeah, that's a known issue: 
https://github.com/ldc-developers/ldc/issues/3864


Try building with `-b plain` to avoid the debug build


Oh, also, I have MACOSX_DEPLOYMENT_TARGET=11 in my environment, that 
helps to avoid it as well.


-Steve



Re: How to compiler dlang code on Apple M1?

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

On 12/13/22 9:35 AM, zoujiaqing wrote:

On Saturday, 3 December 2022 at 20:33:59 UTC, Steven Schveighoffer wrote:


The issue is dub. Make sure you are using the dub built for ARM.

What Apple does is if any program in the same process group is x86 
specific, then all the executed programs that are universal (including 
the linker) will switch to that mode.


The linker thinks you are building on x86, even though the compiler is 
doing ARM64. I ran into this early on too. Switching to the dub that 
ships with ldc built for ARM solved it!


-Steve



```[zoujiaqing@mac server % ~/Programs/ldc/bin/dub run --compiler=ldc2 
--arch=arm64-apple-macos

Performing "debug" build using ldc2 for aarch64, arm_hardfloat.
taggedalgebraic 0.11.22: target for configuration "library" is up to date.
eventcore 0.9.20+commit.4.g6744ae7: target for configuration "cfrunloop" 
is up to date.

server ~master: building configuration "application"...
Linking...
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: alignment (1) of atom 'anon' is too small and may result in 
unaligned pointers
ld: warning: pointer not aligned at address 0x100334231 ('anon' + 561 
from 
.dub/build/application-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-FA51B7352B8B88D87B3B8911362A8A52/server.o)
ld: warning: pointer not aligned at address 0x1003350DB ('anon' + 2025 
from 
../../eventcore/.dub/build/cfrunloop-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-18F6DB0DFA53563841F49715E25DF4FC/libeventcore.a(eventcore.driver.o))
ld: warning: pointer not aligned at address 0x1003398EB ('anon' + 1759 
from 
../../eventcore/.dub/build/cfrunloop-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-18F6DB0DFA53563841F49715E25DF4FC/libeventcore.a(eventcore.drivers.posix.driver.o))
ld: warning: pointer not aligned at address 0x10033B426 ('anon' + 696 
from 
../../eventcore/.dub/build/cfrunloop-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-18F6DB0DFA53563841F49715E25DF4FC/libeventcore.a(eventcore.drivers.posix.events.o))
ld: warning: pointer not aligned at address 0x10033C2A1 ('anon' + 618 
from 
../../eventcore/.dub/build/cfrunloop-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-18F6DB0DFA53563841F49715E25DF4FC/libeventcore.a(eventcore.drivers.posix.kqueue.o))
ld: warning: pointer not aligned at address 0x10033C942 ('anon' + 1186 
from 
../../eventcore/.dub/build/cfrunloop-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-18F6DB0DFA53563841F49715E25DF4FC/libeventcore.a(eventcore.drivers.posix.pipes.o))
ld: warning: pointer not aligned at address 0x10033EE5E ('anon' + 1258 
from 
../../eventcore/.dub/build/cfrunloop-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-18F6DB0DFA53563841F49715E25DF4FC/libeventcore.a(eventcore.drivers.posix.processes.o))
ld: warning: pointer not aligned at address 0x100342E2A ('anon' + 872 
from 

Re: Is remove safe using foreach

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

On 12/13/22 6:22 AM, Per Nordlöw wrote:

On Monday, 12 December 2022 at 17:29:00 UTC, Steven Schveighoffer wrote:
Removing keys while iterating is not supported. It will break, in 
confusing ways, and possibly include a null pointer dereference.


IRC, the specs says that it's an error to modify a foreach aggregate but 
the compiler curretly doesn't diagnose it.


It does say this, but the explanation is misleading. The aggregate must 
be *loop invariant*, which means that modifying the aggregate must not 
affect the current iteration state. However, the exact words are:


> The aggregate itself must not be resized, reallocated, free'd, 
reassigned or destructed while foreach is iterating over the elements.


However, comically, just after the example it has this note:

> Note: Resizing or reassigning a dynamic or associative array during 
foreach is still @safe.


Which both contradicts the direct words in the rule, and is wrong in the 
case of resizing an associative array (which can easily mess up the 
foreach iteration).


In reality, the only thing that should be disallowed is invalidating the 
foreach iteration as defined on the original. How this is enforced is 
implementation defined by the *object itself*. The compiler cannot know 
how iteration interacts with an aggregate, so it is on the aggregate to 
define the rules.


As an example, I specifically allowed removal of the currently iterating 
element in my container library, dcollections. The mechanism used was 
opApply with a ref bool that you would set if you wanted to remove the 
element after that loop iteration. This did not change which elements 
were iterated over, so it was loop invariant.


Array and AA iteration rules should be clearly defined. And the general 
rules should be adjusted to delegate iteration restrictions to the 
aggregate, provided the iteration is still loop invariant.


I'll see if I can create a PR to reword the restrictions.

-Steve


Re: Is remove safe using foreach

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

On 12/12/22 8:45 PM, Steven Schveighoffer wrote:


for(auto r = aa.byKey, auto k = r.front; !r.empty; r.popFront)


err... forgot the continual front assignment
I think it's more like:

for(auto r = aa.byKey; !r.empty; r.popFront) {
   auto k = r.front;
   // foreach body
}

-Steve


Re: Is remove safe using foreach

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

On 12/12/22 7:54 PM, lili wrote:
is foreach Syntactic sugar?, like for-range in C++, if it is, compiler 
how implement





Yes it is syntax sugar. The lowering depends on what the item you're 
iterating is.


For an associative array `byKey`, it is converting the AA into a range 
of keys, and for a range, the compiler does:


foreach(k; aa.byKey)

=>

for(auto r = aa.byKey, auto k = r.front; !r.empty; r.popFront)

(note that the declaration isn't valid syntax in D, but the compiler can 
handle it)


How it's lowered isn't technically important, just know that it iterates 
over each key.


-Steve


Re: Is remove safe using foreach

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

On 12/12/22 12:23 PM, lili wrote:

```
int[string] aa = ["ok":1, "aaa":2, "ccc":3, "ddd":4];
 foreach (k ; aa.byKey)
 {
     if (k == "aaa") {
     aa.remove(k);
     aa["ww"] = 33;
     }

     if (k == "ww") {
     aa.remove(k);
     aa["vv"] = 33;
     }
 }

writeln(aa); // output ["ok":1, "ddd":4, "vv":33, "ccc":3] is ok
```



Removing keys while iterating is not supported. It will break, in 
confusing ways, and possibly include a null pointer dereference.


Instead, either iterate over `aa.keys`, which makes a copy of the keys 
into an array, store the keys to remove for later processing, or 
construct a new AA with the indicated keys removed.


-Steve


Re: Structure initializer VS lambda function

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

On 12/12/22 3:54 AM, realhet wrote:

Hi,

I'm writing a DLang parser and got confused of this.
What is a good way to distinguish lambda functions and structure 
initialization blocks.


Both of them are {} blocks.

I'm thinking of something like this:

1. checking inside (on the first hierarchy level inside {})
    ,   => must be a struct initializer
    ;   => must be a lambda
    no , and no ;  => check it from the outside


2. checking outside (on the same hierarchy level as the {}):
    () before {}   ->  lambda
    => before {}   ->  lambda
    () after {}    ->  lambda  //this check feels wrong to me.
    otherwise  ->  struct initializer

But I think it's logically loose.
I have only the syntax tree, I have no access to semantics. I don't know 
if an identifier is a struct for example.


Is there a better way to do this?

Thank You in advance!


This has actually been discussed recently on discord, I believe the 
difference is if you see a statement inside the braces (e.g. a semicolon).


It's not a great situation, and I think if we removed the ability to do 
lambdas with `{}` without leading parentheses, it could clear this up 
pretty well.


-Steve


Re: Advent of Code 2022

2022-12-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Saturday, 10 December 2022 at 20:49:03 UTC, Christian Köstlin 
wrote:

Is anybody participating with dlang in the advent of code 22?
It would be interesting to discuss dlang specific things from 
the puzzles.


Mine: https://github.com/schveiguy/adventofcode

-Steve


Re: Is there such concept of a list in D?

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

On 12/10/22 1:11 AM, thebluepandabear wrote:


I was wondering more if there is an object oriented way of creating 
arrays, like in Java there is an `ArrayList`, in C++ there is 
`std::vector`, etc.


In D, you just use `T[]` for an array, it's similar to `std::vector`.

-Steve


Re: Is there such concept of a list in D?

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

On 12/10/22 12:46 AM, thebluepandabear wrote:
In most languages there is some sort of `List` type, is that the same 
for D?


D doesn't focus on interfaces, we have concepts, like ranges.

Sorry, it's hard to answer your question without asking more questions: 
are you looking for a linked list? A list API? A specific list interface?


-Steve


Re: How to compiler dlang code on Apple M1?

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

On 12/3/22 1:59 PM, zoujiaqing wrote:

```
dub build --compiler=ldc2 --arch=arm64-apple-macos
     Starting Performing "debug" build using ldc2 for aarch64, 
arm_hardfloat.

     Building taggedalgebraic 0.11.22: building configuration [library]
     Building eventcore 0.9.20+commit.4.g6744ae7: building configuration 
[cfrunloop]

     Building server ~master: building configuration [application]
  Linking server
ld: warning: ignoring file 
../../../.dub/packages/taggedalgebraic-0.11.22/taggedalgebraic/.dub/build/library-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-60F6D8BEA34F8F5E792A98EA27B02D2235262A4E0795062F91FA90871411535D/libtaggedalgebraic.a, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
ld: warning: ignoring file 
/opt/homebrew/Cellar/ldc/1.30.0_1/lib/libdruntime-ldc.a, building for 
macOS-x86_64 but attempting to link with file built for macOS-arm64
ld: warning: ignoring file 
.dub/build/application-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-7AC1A4B8AFD7D9F59DB01E667A3DCF19DD437F41E741F5937BDCF58FAE6AA922/server.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
ld: warning: ignoring file 
../../eventcore/.dub/build/cfrunloop-debug-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.30.0-ED6AFABD5E24BB6BCED6FD74F2DE88CF39B648360CE187983206459095D4677D/libeventcore.a, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
ld: warning: ignoring file 
/opt/homebrew/Cellar/ldc/1.30.0_1/lib/libphobos2-ldc.a, building for 
macOS-x86_64 but attempting to link with file built for macOS-arm64

Undefined symbols for architecture x86_64:
   "_main", referenced from:
  implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see 
invocation)

Error: /usr/bin/cc failed with status: 1
Error ldc2 failed with exit code 1.
```


The issue is dub. Make sure you are using the dub built for ARM.

What Apple does is if any program in the same process group is x86 
specific, then all the executed programs that are universal (including 
the linker) will switch to that mode.


The linker thinks you are building on x86, even though the compiler is 
doing ARM64. I ran into this early on too. Switching to the dub that 
ships with ldc built for ARM solved it!


-Steve


  1   2   3   4   5   6   7   8   9   10   >