Re: Are there anything like leetcode.com but that supports D?

2021-10-24 Thread jfondren via Digitalmars-d-learn

On Sunday, 24 October 2021 at 14:14:48 UTC, Imperatorn wrote:
On Sunday, 24 October 2021 at 05:46:48 UTC, Dr Machine Code 
wrote:
I'd like that to some friends getting start with programming. 
Sadly that platform doesn't support D.


May I ask what platform?


It's in the subject: leetcode.com


Re: Possible runtime bug in preprocessing of command line arguments passed to the D main

2021-10-24 Thread jfondren via Digitalmars-d-learn

On Sunday, 24 October 2021 at 14:21:52 UTC, Basile B. wrote:

What do you think ?


I'm very surprised that this is even allowed. Apparently it's 
Linux userspace that normally complains about it: 
https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/progname.c#n54


The manpages just say

```
   v - execv(), execvp(), execvpe()
   The char *const argv[] argument is an array of pointers to 
null-terminated strings  that  represent
   the argument list available to the new program.  The first 
argument, by convention, should point to
   the filename associated with the file being executed.  The 
array of pointers must be terminated  by

   a null pointer.
```

With nothing to the contrary, I'd take "must be terminated by a 
null pointer" as "can't itself be a null pointer".


On OpenBSD this fails outright:

```
RET   execve -1 errno 14 Bad address
```

You can get `execv` from `core.sys.posix.unistd`


Re: Are there anything like leetcode.com but that supports D?

2021-10-24 Thread jfondren via Digitalmars-d-learn

On Sunday, 24 October 2021 at 05:46:48 UTC, Dr Machine Code wrote:
I'd like that to some friends getting start with programming. 
Sadly that platform doesn't support D.


Here are a few:

https://www.codingame.com/
https://www.spoj.com/
https://www.hackerrank.com/




Re: Dub failing to use the linker correctly.

2021-10-22 Thread jfondren via Digitalmars-d-learn
On Friday, 22 October 2021 at 19:56:37 UTC, Ruby The Roobster 
wrote:
I have a simple vibe-d project built with dub.  Running the 
command, dub build --force returns the following output:


I'd start by running `dub -v build --force` instead, to see the 
exact commands that dub is running.


Re: Can we use "ImportC" used yet?

2021-10-21 Thread jfondren via Digitalmars-d-learn
On Thursday, 21 October 2021 at 22:23:50 UTC, data pulverizer 
wrote:

Hi,

I'm getting an odd issue with ImportC when I import a header 
converted with `gcc -E -P ...` some of the types signatures in 
functions don't come through with their proper names but as 
`__tagXX` where `XX` is some number. It's got to the point 
where the type itself might get imported correctly, but the 
same type in a function might be `__tag28` or some other 
mangled name so when I create an instance of the proper type 
and try to call the respective function, I get a type error.


I'd first check that the type names look OK in the processed C. 
If they do, then it's an importc bug. Those are still getting 
reported, but yours might be new. Worth checking out.


It might also be a bug that's been fixed since release--try dmd 
master on it. These were fixed a few days ago:


fix Issue 22404 - importC: Error: cannot pass argument 'ENUMMEM' 
of type 'int' to parameter '__tag2
fix Issue 22402 - importC: Error: can't subtract '__tag2[1]' from 
pointer


Also, with some definitions in the C file, when I try to 
`#undef` something to get some conditional C definitions to be 
converted with `gcc -E -P ...`, nothing happens.


d doesn't do any C preprocessing, so any problem here is with 
gcc. Your `#undef`s may be coming before the C preprocessor's own 
`#define`s and have no effect.



Thanks.





Re: Casting between structs of the same size is treated as a bit cast?

2021-10-19 Thread jfondren via Digitalmars-d-learn

On Wednesday, 20 October 2021 at 04:14:37 UTC, Dave P. wrote:
I am confused on how casting structs works. According to point 
9 of https://dlang.org/spec/expression.html#CastExpression:


Casting a value v to a struct S, when value is not a struct of 
the same type, is equivalent to:


```d
S(v)
```


It says `value v` and `struct S`, but you go on to cast a struct 
into another struct.


Point 9 is exhibited by

```d
struct Foo {
int i;
}

unittest {
int n = 2;
Foo f = cast(Foo) n;
}
```

However, the following program compiles and the resulting 
execution indicates the bits are just being reinterpreted.

...
Is this a bug in my understanding? Bug in the spec? Bug in the 
compiler?


It looks at least like a gap in the spec. Adding "or a struct to 
another struct" to point six would fit the observed behavior.


Re: std.format doesn't want to work

2021-10-17 Thread jfondren via Digitalmars-d-learn

On Sunday, 17 October 2021 at 12:53:07 UTC, solidstate1991 wrote:

On Sunday, 17 October 2021 at 05:22:17 UTC, russhy wrote:
On Saturday, 16 October 2021 at 22:47:09 UTC, solidstate1991 
wrote:

When I make this call
```
format(" %3.3f"w, avgFPS);
```
my program immediately crashes with an access violation 
error. The debugger out is different between x86 and x86-64.


I've made all sanity checks, so I need some other suggestions.


what is the type of avgFPS?


I's a double, but I've tried to pass it as real and float too, 
with the same exact error being generated.


then it's likely that some memory corruption prior to format() 
has broken the GC, and format's allocation of a string is what's 
failing. Try sprinkling `@safe` and and see what it complains 
about; try valgrind; try reducing your problem. I don't think we 
can help you more without a way to replicate the fault.


Re: Can we use "ImportC" used yet?

2021-10-16 Thread jfondren via Digitalmars-d-learn

On Sunday, 17 October 2021 at 03:38:43 UTC, data pulverizer wrote:

2. Run the commands:

```
gcc -E -P test_og.c > test_c.c
dmd test.d test_c.c && ./test
```

which works. Now I've tried the same thing with library `fftw3` 
and getting:


```
Error: undefined identifier `__float128`
```

Which I guess I have to define somehow in the original c 
directives?


Yep, you have to look at test_c.c and fine the line with that 
error and decide what to do about it.


Re: Can we use "ImportC" used yet?

2021-10-16 Thread jfondren via Digitalmars-d-learn

On Sunday, 17 October 2021 at 02:45:03 UTC, data pulverizer wrote:
While we're on this subject, I've been having similar issues 
now tried compiling @rempas's example file with:


```
gcc test_og.c -c -o test_og.o
dmd test.d test_og.o
```

and get the response:

```
test_og.c(1): Error: identifier or `(` expected
test_og.c(6): Error: identifier or `(` expected
```


You're not doing this with the files in the thread, or you'd get

```
test.d(1): Error: module `test_c` is in file 'test_c.d' which 
cannot be read

```

as test.d is still importing test_c.c, a different file from 
test_og.o


I get your error if the original test_og.c is used but test.d is 
modified to import test_og.c:


```d
import test_og;

void main() {
  hello_world();
}
```

In this case, your compilation to test_og.o doesn't matter; D is 
still trying to import test_og.c, and since that file has CPP 
`#include` directives which importC doesn't support, it's 
erroring out on those.


To link in a C object rather than use importC, you'd need this 
test.d:


```d
extern (C) void hello_world();

void main() {
  hello_world();
}
```

With which:

```
$ gcc test_og.c -c -o test_og.o
$ dmd test.d test_og.o
$ ./test
Hello world!!!
```


Re: Can we use "ImportC" used yet?

2021-10-16 Thread jfondren via Digitalmars-d-learn

On Saturday, 16 October 2021 at 08:19:41 UTC, rempas wrote:

On Saturday, 16 October 2021 at 07:09:16 UTC, jfondren wrote:


This test_og.c works (while obviously breaking some bswap 
functions):


I don't know if I should have known that but what is "bswap"?


I came up with those `#define`s by looking at test_c.c as d 
complained about it. It includes these functions in the final 
result:


```c
static __uint16_t
__bswap_16 (__uint16_t __bsx)
{
  return (__bsx);
}
static __uint32_t
__bswap_32 (__uint32_t __bsx)
{
  return (__bsx);
}
 static __uint64_t
__bswap_64 (__uint64_t __bsx)
{
  return (__bsx);
}
```

initially those were defined in terms of compiler intrinsics that 
d doesn't know about, and since they're not needed for your use, 
I fixed this in the direction of making them no-ops.


They're part of stdlib.h, probably. What they do is endian swaps, 
like the stuff in std.bitmanip


It would be less annoying to compile the original test_og.o 
with gcc and then link it in.


If I understand correctly you mean compile the original file 
with gcc (`gcc test_og.c -o test_og.o`) and then link it with 
DMD (`dmd test.d test_og.o`)? Then what's the point of doing 
that? Isn't this how we did that all this time and why ImportC 
was created so we don't have to manually do the bindings? I'm 
confused...


importC is a new option, but it doesn't make old options go away, 
and in this specific case an older option would've been less 
trouble. That's all I'm saying.


Re: Can we use "ImportC" used yet?

2021-10-16 Thread jfondren via Digitalmars-d-learn

On Saturday, 16 October 2021 at 06:39:46 UTC, rempas wrote:

```
// Filename: test.d
import test_c;

void main() {
  hello_world();
}

// Filename: test_og.c
#include 
#include 

void hello_world() {
  puts("Hello world!!!");
}
```

After that, I'm using: `gcc -E -P test_og.c > test_c.c` to 
preprocess just like you shown and then I'm using the final 
command with DMD: `dmd test.d test_c.c` and I'm getting the 
following error message:


```
/usr/include/stdio.h(246): Error: found `__filename` when 
expecting `,`

```


These are __restrict errors again, but then I get a bunch of 
others as well. This test_og.c works (while obviously breaking 
some bswap functions):


```c
#define __restrict restrict
#define __asm__ asm
#define __extension__
#define __inline
#define __builtin_bswap16
#define __builtin_bswap32
#define __builtin_bswap64
#include 
#include 

void hello_world() {
  puts("Hello world!!!");
}
```

It would be less annoying to compile the original test_og.o with 
gcc and then link it in.


Re: How to make a function that accepts optional struct but can accept struct literal too

2021-10-15 Thread jfondren via Digitalmars-d-learn

On Friday, 15 October 2021 at 20:33:33 UTC, JN wrote:
Is there some nice way of achieving something like this C99 
code in D?


option 1: use an intermediate lambda:

```d
import std.stdio;

struct inputs_t {
int x, y;
} // no ; needed here

void foo(inputs_t* optional_inputs) {
if (!optional_inputs) {
writeln("0 0");
} else {
writeln(optional_inputs.x, " ", optional_inputs.y);
}
}

void main() {
import std.functional : pipe;

foo(null); // prints 0 0
inputs_t(5, 6).pipe!(s => foo()); // prints 5 6
}
```

option 2: use a class

```d
class inputs_t {
int x, y;
this(int x, int y) {
this.x = x;
this.y = y;
}
}

void foo(inputs_t optional_inputs) {
import std.stdio : writeln;

if (!optional_inputs) {
writeln("0 0");
} else {
writeln(optional_inputs.x, " ", optional_inputs.y);
}
}

void main() {
foo(null);
foo(new inputs_t(5, 6));
}
```

option 3: use std.sumtype

```d
import std.sumtype;

struct Point {
int x, y;
}

alias Input = SumType!(Point, typeof(null));

void foo(Input inputs) {
import std.stdio : writeln;

inputs.match!(
(typeof(null) _) => writeln("0 0"),
(Point p) => writeln(p.x, " ", p.y),
);
}

void main() {
foo(null.Input);
foo(Point(5, 6).Input);
}
```

option 4: use overloading

```d
import std.stdio : writeln;

struct Point {
int x, y;
}

void foo() {
writeln("0 0");
}
void foo(Point p) {
writeln(p.x, " ", p.y);
}

void main() {
foo();
foo(Point(5, 6));
}
```

option 5: use S.init, when your exceptional value is handled the 
same


```d
struct Point {
int x, y;
}

void foo(Point p = Point.init) {
import std.stdio : writeln;

writeln(p.x, " ", p.y);
}

void main() {
foo();// 0 0
foo(Point.init);  // 0 0
foo(Point(5, 6)); // 5 6
}
```


Re: Can we use "ImportC" used yet?

2021-10-15 Thread jfondren via Digitalmars-d-learn

On Friday, 15 October 2021 at 20:45:35 UTC, jfondren wrote:

```
0
stat(27, 11, 1, 8592, 1000, 5, 0, 34824, 0, 1024, 0, 
timespec(1634329152, 581807916), timespec(1634329152, 
581807916), timespec(1634272061, 581807916), [0, 0, 0])

9
```

the d programmer did not have to carefully `extern (C)` an 
fstat function, nor define a struct, nor care about issues like 
an evil platform padding its struct with some bytes and 
overwriting the stack unless the d programmer accounts for that.


Speaking of padding the struct, what's what `[0, 0, 0]` at the 
end of my stat() output? I hadn't noticed it before.


```
__syscall_slong_t __glibc_reserved[3];
```

yeah, core.sys.posix.sys.stat doesn't account for that.


Re: Can we use "ImportC" used yet?

2021-10-15 Thread jfondren via Digitalmars-d-learn

On Friday, 15 October 2021 at 18:39:10 UTC, rempas wrote:
Cause I can't find an option in the latest DMD release and 
because the ImportC 
[page](https://dlang.org/spec/importc.html#importing) seems to 
be incomplete (even saying it's under construct), I'm wondering 
if ImportC exists even as prototype but it's hidden or if it's 
not available at all. Anyone knows?


There's no option, you just use a normal import statement when 
the module is named .c instead of .d


I say 'just' but typical C uses the C preprocessor and can't be 
imported as-is.


Here's an example in three files:

```d
// fstat.d
void main() {
import std.stdio : writeln;
import sys_stat : stat_t, fstat;

stat_t buf;
writeln(fstat(0, ));
writeln(buf);
}
```

```c
// sys_stat_wrapper.c
#define __restrict restrict
#include 
typedef struct stat stat_t;
```

```make
# Makefile
fstat: fstat.d sys_stat.c
dmd $<

sys_stat.c: sys_stat_wrapper.c
gcc -E -P $< > $@
```

this is importing sys_stat.c , making space on the stack for a 
stat_t (what's that?), calling fstat on fd 0, and then writing 
the output, which might look like


```
0
stat(27, 11, 1, 8592, 1000, 5, 0, 34824, 0, 1024, 0, 
timespec(1634329152, 581807916), timespec(1634329152, 581807916), 
timespec(1634272061, 581807916), [0, 0, 0])

9
```

the d programmer did not have to carefully `extern (C)` an fstat 
function, nor define a struct, nor care about issues like an evil 
platform padding its struct with some bytes and overwriting the 
stack unless the d programmer accounts for that. This is all 
nice. But you still had to write those three lines of C, to 
smuggle `struct stat` into d and to suppress non-standard 
`__restrict`. And you still need to invoke the C preprocessor as 
a build step.


The next inconvenient thing is: what about when you want a c 
`#define` in d? Say, fstat's potential errors. You have to 
smuggle those as well, and because the C preprocessor fights you, 
you have to not just stuff those people in a box but also prepare 
new names for them. (And if platforms vary in errors? More build 
system work.)


```c
// sys_stat_wrapper.c, continued
#include 
enum errors {
ebadf = EBADF,
eio = EIO,
eoverflow = EOVERFLOW,
};
```

```d
// fstat.d, continued
import sys_stat : errors, ebadf;
writeln(ebadf);
writeln(errors.eoverflow);
}
```

Of course you can rename when importing as usual, or have a 
separate .d module that cleans this interface up where the C 
preprocessor can't interfere.


For function-like `#defines`, perhaps you'll want to write a C 
function that uses it.


In conclusion, ImportC exists and you can use it, and 
complications like smuggling structs are discussed in that page. 
If you're going to wrap a new C library especially, it can take 
on 99% the tedium for you. If you're going to burn down an 
importc-by-hand work that you have already and replace it with 
ImportC, it might be better to wait for dub and gdc to catch up. 
As annoying as it might be to have C constants in your code, they 
do compile with fewer build steps.


Re: Threading challenge: calculate fib(45) while spinning

2021-10-14 Thread jfondren via Digitalmars-d-learn

On Friday, 15 October 2021 at 03:54:17 UTC, Ali Çehreli wrote:

On 10/14/21 8:35 PM, jfondren wrote:
The book, "The Go Programming Language" has this simple 
goroutine example:


Here is one that uses receiveTimeout and OwnerTerminated:



Very nice, replacing Thread.sleep with receiveTimeout and getting 
graceful interruption for free. This also doesn't crash.


Threading challenge: calculate fib(45) while spinning

2021-10-14 Thread jfondren via Digitalmars-d-learn
The book, "The Go Programming Language" has this simple goroutine 
example:


```go
func main() {
go spinner(100 * time.Millisecond)
const n = 45
fibN := fib(n) // slow
fmt.Printf("\rFibonacci(%d) = %d\n", n, fibN)
}

func spinner(delay time.Duration) {
for {
for _, r := range `-\|/` {
fmt.Printf("\r%c", r)
time.Sleep(delay)
}
}
}

func fib(x int) int {
if x < 2 {
return x
}
return fib(x-1) + fib(x-2)
}
```

Attempt #1, with std.concurrency:

```d
import std.concurrency : spawn;
import core.thread : Thread;
import std.stdio : writefln, writef, stdout;
import std.datetime : msecs, Duration;

void main() @safe {
(() @trusted { spawn(, 100.msecs); })();
const n = 45;
const fibN = fib(n); // slow
writefln!"\rFibonacci(%d) = %d"(n, fibN);
}

void spinner(Duration delay) @safe {
(() @trusted { Thread.getThis.isDaemon(true); })();
while (true) {
foreach (char c; `-\|/`) {
writef!"\r%c"(c);
(() @trusted { stdout.flush; })();
(() @trusted { Thread.sleep(delay); })();
}
}
}

int fib(int x) pure @safe @nogc {
if (x < 2)
return x;
return fib(x - 1) + fib(x - 2);
}
```

This version has two problems:

1. a race condition with `isDaemon`: if `main()` ends before 
`isDaemon(true)` is called, then the program never ends because 
the kill-non-daemon-threads module destructor is called while the 
new thread isn't a daemon thread.


2. it crashes about 10% of the time on exit (in dmd, gdc, and 
ldc). valgrind on a gdc build complains about "Conditional jump 
or move depends on uninitialised value(s)" early on.


Attempt #2, with std.parallelism:

```d
import std.parallelism : task, taskPool;
import core.thread : Thread;
import std.stdio : writefln, writef, stdout;
import std.datetime : msecs, Duration;

void main() @safe {
auto spin = task!spinner(100.msecs);
taskPool.put(spin);
const n = 45;
const fibN = fib(n); // slow
writefln!"\rFibonacci(%d) = %d"(n, fibN);
}

void spinner(Duration delay) @safe {
while (true) {
foreach (char c; `-\|/`) {
writef!"\r%c"(c);
(() @trusted { stdout.flush; })();
(() @trusted { Thread.sleep(delay); })();
}
}
}

int fib(int x) pure @safe @nogc {
if (x < 2)
return x;
return fib(x - 1) + fib(x - 2);
}
```

This version continues to spin after the Fibonacci result is 
printed, despite 
https://dlang.org/phobos/std_parallelism.html#.taskPool saying 
that `taskPool` worker threads are daemon by default, and despite 
various attempts to add `isDaemon(true)` calls.


Is there a d version without these problems, and without varying 
substantially from the go (by e.g. having the spinner poll to see 
if it should exit gracefully).


Re: How to check if value is null, today?

2021-10-14 Thread jfondren via Digitalmars-d-learn

On Thursday, 14 October 2021 at 11:58:29 UTC, tastyminerals wrote:
Here is an example code that doesn't work with the new compiler 
anymore:


```
if (someValue.isNull)
```

Attempting to run the above throws:
```
Error: incompatible types for `(0) : (someValue)`: `int` and 
`Nullable!int`

```



Do you have a complete example? Because this runs without error:

```d
import std.typecons : nullable, Nullable;
import std.stdio : writeln;

void main() {
auto a = nullable(1);
auto b = Nullable!int.init;
if (!a.isNull)
writeln(a.get);
if (b.isNull)
writeln("b is null");
}
```


How to test if a string is pointing into read-only memory?

2021-10-12 Thread jfondren via Digitalmars-d-learn
std.string.toStringz always allocates a new string, but it has 
this note:


```d
/+ Unfortunately, this isn't reliable.
 We could make this work if string literals are put
 in read-only memory and we test if s[] is pointing into
 that.

 /* Peek past end of s[], if it's 0, no conversion necessary.
 * Note that the compiler will put a 0 past the end of static
 * strings, and the storage allocator will put a 0 past the end
 * of newly allocated char[]'s.
 */
 char* p = [0] + s.length;
 if (*p == 0)
 return s;
 +/
```

and string literals weren't reliably in read-only memory as 
recently as early 2017: 
https://github.com/dlang/dmd/pull/6546#issuecomment-280612721


What's a reliable test that could be used in a toStringz that 
skips allocation when given a string in read-only memory?


As for whether it's a necessarily a good idea to patch toStringz, 
I'd worry that


1. someone will slice a string literal and pass the test while 
not having NUL where it's expected


2. people are probably relying by now on toStringz always 
allocating, to e.g. safely cast immutable off the result.


Re: Linker error

2021-10-11 Thread jfondren via Digitalmars-d-learn
On Monday, 11 October 2021 at 23:43:17 UTC, Ruby The Roobster 
wrote:

package mixin template move__() {
	pragma(inline) package void mv(Point moveby, ref Skeleton 
tomove)	{

foreach(i;tomove.faces) {
foreach(k;i.lines)  {
foreach(j;k.mid_points) {
j += moveby;
}
k.start += moveby;
k.stop += moveby;
}
i.center += moveby;
}
tomove.center += moveby;
}
}


It compiles if this `pragma(inline)` is removed.


Re: Managing malloced memory

2021-10-11 Thread jfondren via Digitalmars-d-learn

On Monday, 11 October 2021 at 12:09:07 UTC, Imperatorn wrote:

On Wednesday, 6 October 2021 at 18:06:38 UTC, anon wrote:
I interface to a C library that gives me a malloced object. 
How can I manage that pointer so that it gets freed 
automatically.

What I've thought of so far:
* scope(exit): not an option because I want to return that 
memory


Explain again why scope exit isn't an option


The explanation is "I want to return that memory".


```d
int* not_an_option() {
import core.memory : pureMalloc, pureFree;

int* p = cast(int*) pureMalloc(int.sizeof);
scope (exit)
pureFree(p);
return p;
}

unittest {
not_an_option()[0] = 1;
}
```

valgrind: Invalid write of size 4


Re: Create array from range

2021-10-09 Thread jfondren via Digitalmars-d-learn

On Saturday, 9 October 2021 at 23:58:14 UTC, Greg Strong wrote:
This should be a simple question, but I'm having difficult 
finding an answer.  How do I filter some elements of an array 
into a new array?  The filter! function returns a range, but I 
can't seems to assign it to a new array.  I get:


Cannot implicitly convert expression of type 
FilterResult!(__lambda10 ...


Nothing I try to construct a new array seems to work.


std.array.array does this:

https://dlang.org/phobos/std_array.html

and some other functions in that module are similar.

A value of output ranges like FilterResult is that you can decide 
how or whether to allocate an array of the results: you could 
allocate a new array with `.array` or you could consume the 
results as they come, or you could out pick a particular result, 
or you could populate a static array...


```d
int example(R)(R range) @nogc {
import std.range : take, enumerate;

int[5] ints;

foreach (size_t i, n; range.enumerate.take(ints.length))
ints[i] = n;

// just to do something with the array
int sum;
foreach (n; ints)
sum += n;
return sum;
}

unittest {
import std.range : iota;
import std.algorithm : filter;

assert(20 == iota(100).filter!"a%2==0".example);
}
```


Re: Python's list equivalent with std.variant?

2021-10-03 Thread jfondren via Digitalmars-d-learn

On Sunday, 3 October 2021 at 22:22:48 UTC, rjkilpatrick wrote:

```d
void main() {
// When we use `SuperClass[] list;` here, we find 'a' is 
hidden by the base class

Variant[] list;

// Attempting to append derived class instances to list
list ~= new DerivedClass(1.0f);
list ~= new OtherDerivedClass;

list[0].a;
list[0].to!(get!(list[0].type)).a.writeln;
}
```


This works:

```d
void main() {
Variant[] list;

list ~= new DerivedClass(1.0f).Variant;
list ~= new OtherDerivedClass().Variant;

writeln(list[0].get!DerivedClass.a);
}
```

Parameters passed in !() need to be statically known, at 
compile-time, so `get!(list[0].type)` doesn't make sense with a 
runtime list.


If everything in the list is going to be a child of some class, 
then you don't need std.variant at all, you can just use OOP:


```d
import std.stdio : writeln;

class SuperClass {
this() {
}
}

class DerivedClass : SuperClass {
public:
this(float a) {
this.a = a;
}
float a;
}

class OtherDerivedClass : SuperClass {}
class YetAnotherDerivedClass : SuperClass {}

void main() {
SuperClass[] list;

list ~= cast(SuperClass) new DerivedClass(1.0f);
list ~= cast(SuperClass) new OtherDerivedClass;
list ~= cast(SuperClass) new YetAnotherDerivedClass;

writeln((cast(DerivedClass) list[0]).a);

foreach (obj; list) {
if (auto deriv = cast(DerivedClass) obj) {
writeln("I found a DerivedClass: ", deriv.a);
} else if (cast(OtherDerivedClass) obj) {
writeln("I found an OtherDerivedClass");
} else {
writeln("I found an unexpected child: ", obj);
}
}
}
```

output:

```
1
I found a DerivedClass: 1
I found an OtherDerivedClass
I found an unexpected child: variant.YetAnotherDerivedClass
```

Object casts like that are `null` when the cast is invalid.

If you don't necessarily have a superclass, but still do have a 
definite number of possible member types, you can use std.sumtype:


```d
import std.stdio : writeln;
import std.sumtype;

struct A { float a; }
struct B { }
struct C { }
alias Alpha = SumType!(A, B, C);

void main() {
Alpha[] list;

list ~= A(1.0f).Alpha;
list ~= B().Alpha;
list ~= C().Alpha;

list[0].tryMatch!((A a) => writeln(a.a));

foreach (obj; list) {
obj.match!(
(A a) => writeln("I found A(", a.a, ")"),
(B _) => writeln("I found B"),
(C _) => writeln("I found C"),
);
}
}
```

output:

```
1
I found A(1)
I found B
I found C
```


Re: Mutually recursive template expansion

2021-10-01 Thread jfondren via Digitalmars-d-learn

On Friday, 1 October 2021 at 14:03:06 UTC, Stephen wrote:

This code should work should mutual recursion be supported.


It still wouldn't work, because structs are value types and it's 
impossible to say how large either struct is:


Error: struct `mutualrec.Ar` no size because of forward reference

With s/struct/class/ it still wouldn't work because this is a 
mixin problem rather than a problem of template mutual recursion:


```d
mixin(q{ class Ar { Br b; } });
mixin(q{ class Br { Ar b; } });
```

mutualrec2.d-mixin-1(1): Error: undefined identifier `Br`, did 
you mean class `Ar`?


This seems like a surprising limitation of mixin, though, which 
isn't highlighted by the spec.


Re: Dynamically binding to D code using extern(D)

2021-09-30 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 18:09:46 UTC, Hipreme wrote:
I write this post as both a learning tool, a question and an 
inquiry.


There are just a lot of drawbacks in trying to do function 
exporting while using D.


The terms that people use are a bit sloppy. There are three kinds 
of 'linking' here:


1. static linking, performed during compilation, once. If linking 
fails, the compile files.
2. dynamic linking (option 1), performed when an executable 
starts up, before your program gains control, by the system 
linker. If linking fails, your program never gets control.
3. dynamic linking (option 2), performed arbitrarily at runtime, 
by your program. If linking fails, you can do whatever you want 
about that.


All of the loadSymbol and 'userdata module' hassle that you're 
frustrated by is from option 2. Option 1 is really the normal way 
to link large shared libraries and there's nothing to it. What 
your code looks like that loads a shared library is just `import 
biglib;`, and the rest of the work is in dub, pkg-config, 
`LD_LIBRARY_PATH`, etc. Phobos is commonly linked in this way.


Pretty much anything that isn't a plugin in a plugin directory 
can use option 1 instead of option 2.



extern(C) advantages:

- Code callable from any language as it is absolutely intuitive
- Well documented



You can call scalding water 'hot' even when you're fresh from 
observing a lava flow. People still find the C ABI frustrating in 
a lot of ways, and especially when they encounter it for the 
first time.


But the C ABI rules the world right now, yes. The real advantages 
are


- it 'never' changes
- 'everyone' already makes it easy to use


extern(C) disadvantages:

- You will need to declare your function pointer as extern(C) 
or it will swap the arguments order.


- you're limited to using C's types
- you can't use overloading, lazy parameters, default values; you 
can't rely on scope parameters, etc., etc.
- you can't casually hand over GC-allocated data and expect the 
other side to handle it right, or structs with lifetime functions 
that you expect to be called
- very little of importance is statically checked: to use a C ABI 
right you need to very carefully read documentation that needs to 
exist to even know who is expected to clean up a pointer and how, 
how large buffers should be. (I wasn't feeling a lot of the C 
ABI's "absolute intuitiveness" when I was passing libpcre an 
ovector sized to the number of pairs I wanted back rather than 
the correct number of `pairs*3/2`)


Option 2 dynamic linking of D libraries sounds pretty 
frustrating. Even with a plugin architecture, maybe I'd prefer 
just recompiling the application each time the plugins change to 
retain option 1 dynamic linking. Using a C ABI instead is a good 
idea if just to play nice with other languages.


And if you were wanting something like untrusted plugins, a way 
to respond to a segfault in a plugin, like I think you mentioned 
in Discord, then I'd still suggest not linking at all but having 
separate applications and some form of interprocess communication 
(pipes, unix sockets, TCP sockets) instead of function calls. 
This is something that you could design, or with D's reflection, 
generate code for against the function calls you already have. 
But this is even more work that you'll have to do. If we add "a 
separate process telling you what to do with some kind of 
protocol" as a fourth kind of linking, then the respective effort 
is


1. free! it compiles, it's probably good!
2. free! if the program starts, it's probably good!
3. wow, why don't you just write your own loadSymbol DSL?
4. wow, why don't you just reimplement Erlang/OTP and call it 
std.distributed? maybe protobufs will be enough.


Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 03:13:28 UTC, jfondren wrote:

As provided, loadSymbol without the "static if":

965K libhipengine_api.a

with `mixin(loadSymbol("name"))` instead of a template:

749K libhipengine_api.a


The difference goes down to 66K vs. 60K with `dub -brelease 
--compiler=gdc`. ldc's not as slim but still much better than 
dmd, and -brelease is actually much less significant. So dmd's 
the main culprit for the bloat here. huh.


But since you have importPaths-ldc perhaps you weren't using dmd 
to begin with.


Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 02:31:50 UTC, Hipreme wrote:

https://github.com/MrcSnm/HipremeEngine/tree/hotload/api

You may try messing at the module api.graphics.g2d.renderer2d

There is a function called initG2D

Try changing it from loadSymbols to each one loadSymbol.

You can just dub at the folder api.


The version I checked out, 2874073b54, doesn't have a loadSymbols.

As provided, loadSymbol without the "static if":

965K libhipengine_api.a

with `mixin(loadSymbol("name"))` instead of a template:

749K libhipengine_api.a

https://gist.github.com/jrfondren/d776ccffb105f464b53c53712656a1d3

That's probably disappointing, since it's a much less pleasant 
interface, but what you could do is take the both entire 
`extern(C) void function() beginSprite; ... 
loadSymbol!beginSprite;` blocks and put them in one string 
literal that you process with a function and mixin once. Now 
instead of an annoying macro alternative you have a DSL for 
DLL-extern functions.


Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 01:44:57 UTC, jfondren wrote:

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a symbol, 
it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


If symName is always a string literal, then you don't need to 
append a "\0"; string literals always have a trailing NUL after 
them, and they autoconvert to const(char)[] so you don't need 
the .ptr either.


Playing around with this, with a mock-up of your code, doesn't 
change object size at all.


Is the actual source available, that you're seeing this with?


Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a symbol, 
it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


If symName is always a string literal, then you don't need to 
append a "\0"; string literals always have a trailing NUL after 
them, and they autoconvert to const(char)[] so you don't need the 
.ptr either.


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread jfondren via Digitalmars-d-learn

On Thursday, 23 September 2021 at 14:23:40 UTC, eugene wrote:

On Thursday, 23 September 2021 at 14:00:30 UTC, eugene wrote:


For the moment I am personally quite happy


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

import core.memory : GC;

auto Main = new Main();
GC.addRoot(cast(void*)Main);
Main.run();

auto stopper = new Stopper();
GC.addRoot(cast(void*)stopper);
stopper.run();
```

Fine, works!


Nice. I thought of GC.addRoot several times but I was distracted 
by the general solution of using object lifetimes with it, so 
that a struct's destructor would call GC.removeRoot. For your 
case just pinning these and forgetting about them is the easiest 
way to do it.


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread jfondren via Digitalmars-d-learn

On Thursday, 23 September 2021 at 13:30:42 UTC, eugene wrote:

So, in C it is MY (potentially wrong) code.
In D, it is NOT MY code, it is GC.


Actually in both cases it is MY+the compiler's code. A very 
similar example from C-land (without my digging up the exact 
details) is something like


```c
for (int i = 0; i >= 0; i++) {
  // exit loop on signed integer overflow
}
```

where gcc 2.95 would do what "MY code" said, but later gcc 
versions would 'optimize' into an infinite loop (followed by dead 
code that can now be removed):


```c
for (;;) {
  // never exit loop
}
```

Because in math, positive numbers never +1 into negative numbers. 
And in C this is undefined behavior which is (modern 
understanding:) complete license for the compiler to do anything 
at all. And on the specific architecture we are specifically 
compiling for there is specific behavior--but who cares about 
that, this is optimization! And if you complained about it, well 
you were a sloppy coder actually, for wanting the target 
architecture's actual behavior with your actual code as you 
actually wrote it. (If you feel like defending C's honor here, 
please, I've heard it already. Everybody thinks very highly of 
the nasal demons joke.)


There are other cases where very security-minded software had 
defensive code that an optimizer decided would never be needed, 
that then exposed a software vulnerability, or there are 
'unnecessary' writes that are intended to remove a password from 
memory:


https://duckduckgo.com/?q=dead+code+elimination+security+vulnerability


Re: foreach(ubyte j;0 .. num) is bugging out

2021-09-22 Thread jfondren via Digitalmars-d-learn
On Thursday, 23 September 2021 at 00:30:45 UTC, Ruby The Roobster 
wrote:
I figured out something weird. The variable 'i' is passed by 
reference, yet the variable 'i' of the loop isn't being 
incremented by posfunc.  I assume foreach creates a new i 
variable at the start of each new loop.


Yep:

```
$ rdmd --eval 'foreach (i; 0 .. 5) { writeln(i); i++; }'
0
1
2
3
4
```


Re: foreach(ubyte j;0 .. num) is bugging out

2021-09-22 Thread jfondren via Digitalmars-d-learn
On Thursday, 23 September 2021 at 00:06:42 UTC, Ruby The Roobster 
wrote:

So, I have the following function:
```d
	writeln(tempcolor); //For this matter, the program 
correctly reports tempcolor as 1...
		for(ubyte j = 0;j < tempcolor; j++ /*trying ++j has same 
effect*/ )	{ //tempcolor is 1, yet this sloop gets executed 
twice...

writeln();
			posfunc(ftext, main, exp, temp, i, j, points , x);   
 //Orignally foreach loop, but 
switching to for loop has same effect...

}
```


Needs more print in your print debugging:

```d
writeln("tempcolor: ", tempcolor);
...
writeln("in tempcolor with j: ", j);
```

output:

```
tempcolor: 1
in tempcolor with j: 0
...
... numbers
...
tempcolor: 0
tempcolor: 0
tempcolor: 0
tempcolor: 0
tempcolor: 0
tempcolor: 0
tempcolor: 0
tempcolor: 0
tempcolor: 0
tempcolor: 1
in tempcolor with j: 0
...
... numbers
...
```

Here's a oneliner to reproduce to abc.txt:

```
rdmd --eval '"00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 
00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 01".split(" 
").map!(s => cast(char) s.to!ubyte).write' > abc.txt

```


Re: Program crash: GC destroys an object unexpectedly

2021-09-22 Thread jfondren via Digitalmars-d-learn

On Wednesday, 22 September 2021 at 08:03:59 UTC, eugene wrote:

On Tuesday, 21 September 2021 at 20:28:33 UTC, jfondren wrote:

Everything is Ok now,


I don't think this is reliably OK. If you're not using Stopper 
later in the function, and if there are no other references to 
it, then the GC can collect it. It just has no obligation to 
collect it, so minor differences like this might prevent that 
from happening for particular compilers/options/versions.


I saw a thread on this forum named
'Why are so many programmers do not like GC'
or something like that.

After this adventure I would add my 5 cents:
because (sometimes, ok) it behaves absolutely
unpredictable, depending on operation order,
"particular compilers/options/versions" etc.


Nondeterminism in heap collection is a very common complaint, but 
here we have data is that apparently on the stack that is 
collected nondeterministically. I can't say I like that.


Re: Program crash: GC destroys an object unexpectedly

2021-09-21 Thread jfondren via Digitalmars-d-learn

On Tuesday, 21 September 2021 at 20:17:15 UTC, eugene wrote:

Now, change operation order in the main like this:

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

auto Main = new Main();
auto stopper = new Stopper();

Main.run();
stopper.run();
```

```
d-lang/edsm-in-d-simple-example-2 $ ./test | grep STOPPER
'STOPPER' registered 5 (esrc.Signal)
'STOPPER' registered 6 (esrc.Signal)
'STOPPER @ INIT' got 'M0' from 'SELF'
'STOPPER' enabled 5 (esrc.Signal)
'STOPPER' enabled 6 (esrc.Signal)
```

Everything is Ok now,


I don't think this is reliably OK. If you're not using Stopper 
later in the function, and if there are no other references to 
it, then the GC can collect it. It just has no obligation to 
collect it, so minor differences like this might prevent that 
from happening for particular compilers/options/versions.


C# and Go have 'keepalive' functions to avoid similar behavior, 
and Java's just as aggressive about potential collection. It's 
just something that mostly doesn't matter until it becomes an 
incredibly weird bug with code like yours.


Re: Program crash: GC destroys an object unexpectedly

2021-09-21 Thread jfondren via Digitalmars-d-learn

On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote:
I do not understand at all why GC considers those sg0 and sg1 
as unreferenced.

And why old gdc (without -Os) and old ldc do not.


Conclusion:

There's nothing special about sg0 and sg1, except that they're 
part of Stopper. The Stopper in main() is collected before the 
end of main() because it's not used later in the function and 
because there are apparently no other references to it that the 
GC can find (because the only reference is hidden inside the 
Linux epoll API).


More discussion:

https://forum.dlang.org/thread/siajpj$3p2$1...@digitalmars.com
http://dpldocs.info/this-week-in-d/Blog.Posted_2021_09_20.html

Misaligned pointers are one way to hide objects from the GC but 
in this case they really weren't relevant. I just had a confused 
idea of the epoll API, because I'd only ever used it with a 
single static array that all epoll functions referenced, 
similarly to poll(). But actually epoll copies the event 
structures that you give it, and returns them on epoll_wait. 
That's wild.


Re: MobI? Really?

2021-09-21 Thread jfondren via Digitalmars-d-learn

On Tuesday, 21 September 2021 at 16:14:52 UTC, Chris_D wrote:
jfondren: Sorry, but I am talking about documentation.  For me, 
online web pages don't qualify; they are in the cloud, unreal, 
with no substance.  Does anyone really read 300 pages online, 
in a web browser?  Of course not.


You can download them to a local copy, and you can generate them 
locally. But usually I am not reading 300 pages but going to a 
specific part of the documentation to look a specific thing up, 
and there I'm usually online anyway.


As a thing to read from beginning to end rather than a spot 
reference I think the current spec would be very wanting for a 
few reasons, like internal hyperlinks and little of the 
justificatory text that 'annotated' specifications tend to have. 
For a recent example, in https://dlang.org/spec/garbage.html it 
just says "Do not misalign pointers if those pointers may point 
into the GC heap". Why not? If you can get away with it on a 
particular architecture, maybe it's fine? Actually, it's a big 
deal.


What I'd like is Perl's offline documentation. Just type 'perldoc 
perl' into a unix system and look at it. Or 'perldoc -f stat', 
'perldoc -q columns'.



Jordi Sayol: PDF!  ePub!  Now that's what I call documentation!

But that's on SourceForge.  My first port of call to learn 
about D was, and is, dlang.org, where the *only* links to the 
"D Programming Language Specification" in any downloadable 
format are for the Mobi.


  Chris


I haven't had consistent results with requesting updates to the 
online docs, but you could try just adding a link to this page. 
There are other offsite links and they occasionally need tending 
to, as well.


A more immediate place to make a change is 
https://wiki.dlang.org/The_D_Programming_Language , where it'd be 
very easily to slide a few extra links onto the 'D Language 
Specification' link at the top right.


The wiki isn't only accessible through Community/Wiki; several of 
the Resources links on dlang.org also point to it.


Re: Why dtor are not executed when removing a struct from associative arrays?

2021-09-20 Thread jfondren via Digitalmars-d-learn

On Monday, 20 September 2021 at 12:23:00 UTC, Learner wrote:

I was expecting something like going out of scope for that

```(D)
import std.stdio;

struct S
{
~this()
{
writeln("S is being destructed");
}
}

void main()
{
S[int] aa;
aa[1] = S();
aa.remove(1);
writeln("Why no dtor call on remove?");
}

I was expecting S instance dtor called
S is being destructed
```


This looks to me like a bug, as

```d
import core.memory : GC;
GC.collect;
```

immediately after the `.remove` will call the struct's destructor.

I only see https://issues.dlang.org/show_bug.cgi?id=20379 as 
related, though.


Here's another workaround:

```d
alias purge = (kv, k) { kv[k] = typeof(kv[k]).init; kv.remove(k); 
};

```

with the same caveat of the `.init` structs also getting 
destructed later, you can use that in place of `.remove`.


Re: Program crash: GC destroys an object unexpectedly

2021-09-19 Thread jfondren via Digitalmars-d-learn

On Sunday, 19 September 2021 at 08:51:31 UTC, eugene wrote:
reference-containing struct that vanishes on the return of 
your corresponding function
I do not think it's a problem, otherwise **both programs would 
not work at all**.


The GC doesn't reliably punish objects living past there not 
being any references to them because it's not always operating. 
If you have a tight loop where the GC is never invoked, you can 
do what ever crazy things you want. Your program doesn't crash 
until you hit ctrl-C after all.



Look...
I have added stopper into an array...

```d
Stopper[] stoppers;
auto stopper = new Stopper();
stoppers ~= stopper;
stopper.run();
```

and, you won't believe, this have fixed the problem -
the objects, referenced by sg0 and sg1 are not destroyed 
anymore.


This is a sufficient patch to prevent the segfault:

```
diff --git a/echo_client.d b/echo_client.d
index 1f8270e..5ec41df 100644
--- a/echo_client.d
+++ b/echo_client.d
@@ -32,7 +32,7 @@ void main(string[] args) {
 sm.run();
 }

-auto stopper = new Stopper();
+scope stopper = new Stopper();
 stopper.run();

 writeln(" === Hello, world! === ");
```

The `scope` stack-allocates Stopper.

This is also a sufficient patch to prevent the segfault:

```
diff --git a/echo_client.d b/echo_client.d
index 1f8270e..0b968a8 100644
--- a/echo_client.d
+++ b/echo_client.d
@@ -39,4 +39,6 @@ void main(string[] args) {
 auto md = new MessageDispatcher();
 md.loop();
 writeln(" === Goodbye, world! === ");
+writeln(stopper.sg0.number);
+//writeln(stopper.sg1.number);
 }
```

either one of those writelns will do it.

Without either of the above, STOPPER is destroyed a few seconds 
into a run of echo-client:


```
$ ./echo-client | grep STOPPER
'STOPPER' registered 24 (esrc.Signal)
'STOPPER' registered 25 (esrc.Signal)
'STOPPER @ INIT' got 'M0' from 'SELF'
'STOPPER' enabled 24 (esrc.Signal)
'STOPPER' enabled 25 (esrc.Signal)
(seconds pass)
stopper.Stopper.~this(): STOPPER destroyed
```

You can hit ctrl-C prior to Stopper's destruction and there's no 
segfault. (On my system, it won't show the usual 'segfault' 
message to the terminal when grep is filtering like that, but if 
you turn on coredumps you can see one is only generated with a 
ctrl-C after Stopper's destroyed.)


So this looks at first to me like a bug: dmd is allowing Stopper 
to be collected before the end of its lexical scope if it isn't 
used later in it. Except, forcing a collection right after 
`stopper.run()` doesn't destroy it.


Here's a patch that destroys Stopper almost immediately, so that 
a ctrl-C within milliseconds of the program starting will still 
segfault it. This also no longer requires the server to be active.


diff --git a/engine/edsm.d b/engine/edsm.d
index 513d8a5..ea9ac3a 100644
--- a/engine/edsm.d
+++ b/engine/edsm.d
@@ -176,6 +176,8 @@ class StageMachine {
 "'%s @ %s' got '%s' from '%s'", name, 
currentStage.name, eventName,

 m.src ? (m.src is this ? "SELF" : m.src.name) : "OS"
 );
+import core.memory : GC;
+GC.collect;

 if (eventName !in currentStage.reflexes) {

valgrind:

```
^C==14893== Thread 1:
==14893== Jump to the invalid address stated on the next line
==14893==at 0x2: ???
==14893==by 0x187A3C: void disp.MessageDispatcher.loop()
==14893==by 0x1BED89: _Dmain
```

with Stopper's collection prevented and some logging around 
reactTo:


```
^Csi.sizeof = 128
about to react to Message(null, stopper.Stopper, 0, esrc.Signal)
'STOPPER @ IDLE' got 'S0' from 'OS'
goodbye, world
reacted
 === Goodbye, world! ===
1
ecap.EventQueue.~this
stopper.Stopper.~this(): STOPPER destroyed
```

So the problem here is that ctrl-C causes that message to come 
but Stopper's been collected and that address contains garbage. 
Since the Message in the MessageQueue should keep it alive, I 
think this is probably a bug in dmd.


Re: Extract base type of any array?

2021-09-18 Thread jfondren via Digitalmars-d-learn

On Sunday, 19 September 2021 at 03:58:41 UTC, Kirill wrote:
How can I get the base type of any 
(multidimensional/static/dynamic/associative) array?


Example:
```
void main() {
int[][] intArr;
double[4][] doubleArr;
string[string][] strArr;

intArr.example; // T = int
doubleArr.example; // T = double
strArr.example; // T = string
}

void example(T)(<...> data) {
// extract the base of data (inside func's body or in <...>)
// preferably, T must become data's base type
}
```


This almost works, but as `string` is an array type it needs some 
kind of rule to stop there:


```d
unittest {
int[] intArr;
double[4][] doubleArr;
string[string][][] strArr;

assert(is(BaseType!(typeof(intArr)) == int));
assert(is(BaseType!(typeof(doubleArr)) == double));
assert(is(BaseType!(typeof(strArr)) == immutable(char)));
}

template BaseType(T) {
static if (__traits(isStaticArray, T))
alias BaseType = BaseType!(typeof(T.init[0]));
else static if (is(T == U[], U))
alias BaseType = BaseType!U;
else static if (is(T == V[K], K, V))
alias BaseType = BaseType!V;
else
alias BaseType = T;
}
```

mix of BaseType!T from core.internal.array.equality and rank!T 
from Philippe Sigaud's D Templates Tutorial at 
https://github.com/PhilippeSigaud/D-templates-tutorial


Re: MobI? Really?

2021-09-18 Thread jfondren via Digitalmars-d-learn

On Saturday, 18 September 2021 at 20:40:56 UTC, Chris_D wrote:
The "D Programming Language Specification" seems to be the most 
important documentation for D.  Is it really only available as 
Mobi?  That is the most bizarre choice of format I've ever seen.


  Chris


No, it's not *only* available as mobi. It's also right here: 
https://dlang.org/spec/spec.html


Re: Program crash: GC destroys an object unexpectedly

2021-09-18 Thread jfondren via Digitalmars-d-learn

On Saturday, 18 September 2021 at 09:39:24 UTC, eugene wrote:

The definition of this struct was taken from
/usr/include/dmd/druntime/import/core/sys/linux/epoll.d

...

If the reason for crash was in EpollEvent alignment,
programs would segfaults always very soon after start,
just right after the very first return from epoll_wait().


The struct's fine as far as libc and the kernel are concerned. 
epoll_wait is not even using those 64 bits or interpreting them 
as containing any kind of data, it's just moving them around for 
the caller to use. It's also not a hardware error to interpret 
those bits where they are as a pointer. They are however not 
64-bit aligned so D's GC is collecting objects that only they 
point to.


Re: yet another segfault - array out of bound is not caught by try catch

2021-09-17 Thread jfondren via Digitalmars-d-learn

On Friday, 17 September 2021 at 11:10:33 UTC, seany wrote:
Compile with `dub build --compiler=ldc2 `. this should enable 
array bound checking options.


By default, yes. run `dub -v build --compiler=ldc2` to see the 
exact commands that dub runs.



But should it not be caught by range error ?


Based on what you've said, yes it should.


If I do `print l`in gdb, i find :
$1 = {length = 0, ptr = 0x0}
With `print l[0]` i get: `Attempt to take address of value not 
located in memory.`.


i.e., a segfault. null (or 0x0 (or 0)) isn't part of the memory 
addresses your program is allowed to access, so memory protection 
prevents the attempt to access it.



What absolute rookie mistake am I committing?


From this it doesn't sound like you are committing one, but if 
you're wanting bounds checking to be a normal part of program 
logic, and not something that only ever happens due to a 
programmer's error, then I think you're cutting against the grain 
of the language, where


- bounds checking is easily removed from all but @safe functions 
with normal flags


- flags exist to remove it from @safe functions also

- the *Error family of exceptions, including RangeError are not 
intended to be catchable


- raising and immediately catching an exception like this is 
slower and more verbose than an explicit test.


Rather than returning an empty array on an error and expecting a 
caller to catch RangeError, you could throw a normal exception on 
error, and then you have tools like `std.exception.ifThrown` to 
make dealing with that exception nicer.


Re: GC seems to crash my C-code function

2021-09-17 Thread jfondren via Digitalmars-d-learn

On Friday, 17 September 2021 at 06:27:40 UTC, frame wrote:

Thanks, I'm just careful with casting.
Does it really allocate from a literal if it's used on the 
stack only? Is `-vgc` switch reliable?


looks to me like it calls

```d
// object
private U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if 
(__traits(isPOD, T))

{
if (__ctfe)
return _dupCtfe!(T, U)(a);

import core.stdc.string : memcpy;
auto arr = _d_newarrayU(typeid(T[]), a.length);
memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * 
a.length);

return *cast(U[]*) 
}
```

->

```d
// rt.lifetime
extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t 
length) pure nothrow @weak

{
...
auto info = __arrayAlloc(size, ti, tinext);
...
}
```

->

```d
// rt.lifetime
BlkInfo __arrayAlloc(size_t arrsize, const scope TypeInfo ti, 
const TypeInfo tinext) nothrow pure

{
...
auto bi = GC.qalloc(padded_size, attr, tinext);
...
}
```

->

```d
// gc.impl.conservative.gc
BlkInfo qalloc( size_t size, uint bits, const TypeInfo ti) 
nothrow

{

if (!size)
{
return BlkInfo.init;
}

BlkInfo retval;

retval.base = runLocked!(mallocNoSync, mallocTime, 
numMallocs)(size, bits, retval.size, ti);


if (!(bits & BlkAttr.NO_SCAN))
{
memset(retval.base + size, 0, retval.size - size);
}

retval.attr = bits;
return retval;
}
```

which you can also follow in an objdump. Conclusion: -vgc is 
missing this GC allocation.


To stack-allocate a mutable copy of a string literal go with

```d
@safe @nogc nothrow unittest {
enum S = "hello world";
char[S.length+1] s1 = S;
char* s2 = [0];

// Normally you'd expect s1.ptr[s1.length] here,
// but the '\0' byte is explicitly part of s1 due to length+1 
above.

assert(s1[s1.length-1] == '\0');

(() @trusted {
import core.stdc.stdio : puts;
import std.string : fromStringz;

puts(s2);
assert(s2.fromStringz == S);
})();
}
```


Re: Merge 2 structs together (into a single struct)?

2021-09-16 Thread jfondren via Digitalmars-d-learn
On Friday, 17 September 2021 at 05:01:36 UTC, james.p.leblanc 
wrote:
Again, thanks to you and many of the D community with helping 
to learn and

appreciate the capabilities of D.  It is nice to be here.


Yeah. The improved joinStruct is nice enough that I think it's 
probably a good thing to do.


And there's this, some kind of Jai innovation:

```d
struct Object {
float[2] position, velocity, facing;
float size;
}

struct Player {
mixin parent!Object;
int hp;
}

mixin template parent(Struct) {
static foreach (i, alias f; Struct.tupleof) {
mixin("typeof(f) ", __traits(identifier, f), " = 
Struct.init.tupleof[i];");

}
}

void main() {
import std.stdio : writeln;

writeln(Player([0, 0], [0, 0], [0, -1], 5.0, 100));
}
```


Re: dub segfault and range error handling

2021-09-16 Thread jfondren via Digitalmars-d-learn

On Thursday, 16 September 2021 at 20:49:28 UTC, seany wrote:

I compile with : `dub build -b release --compiler=ldc2`


The result executing the compiled binary 'myproj' is is ( 
whether `writeln (a[1])` is uncommented, or the  `test()` 
function is uncommented) some random number, usually negative 
with large absolute value, such as `-1894658200` .



If this is embedded in a class, then the result is segfault.

Is this expected behavior?


Yes. You have a -release build, "defaulting to disabled 
asserts/contracts/invariants, and bounds checks in @safe 
functions only", and you have an array out of bounds in a @system 
function, so your array out of bounds goes unchecked.


Re: Merge 2 structs together (into a single struct)?

2021-09-16 Thread jfondren via Digitalmars-d-learn
On Thursday, 16 September 2021 at 20:12:03 UTC, james.p.leblanc 
wrote:

Is there some obvious, and simple solution to this
conundrum of mine?


I would consider AAs.

```d
struct A {
int alpha;
float x = 1.23;
}

struct B {
int beta;
float y = 4.4;
string s = "this is fine.";
}

string joinstruct(A, B)(string name) {
string s = "struct " ~ name ~ " {";
alias memA = __traits(allMembers, A);
alias memB = __traits(allMembers, B);
alias initA = A.init.tupleof;
alias initB = B.init.tupleof;
static foreach (i; 0 .. memA.length) {
s ~= typeof(__traits(getMember, A, memA[i])).stringof;
s ~= " ";
s ~= memA[i];
s ~= " = ";
s ~= initA[i].stringof;
s ~= ";\n";
}
static foreach (i; 0 .. memB.length) {
s ~= typeof(__traits(getMember, B, memB[i])).stringof;
s ~= " ";
s ~= memB[i];
s ~= " = ";
s ~= initB[i].stringof;
s ~= ";\n";
}
s ~= "}";
return s;
}

unittest {
mixin(joinstruct!(A, B)("C"));
import std.stdio;
writeln(C());
}
```


Re: Program crash: GC destroys an object unexpectedly

2021-09-15 Thread jfondren via Digitalmars-d-learn

On Tuesday, 14 September 2021 at 20:59:14 UTC, Ali Çehreli wrote:

On 9/14/21 9:56 AM, eugene wrote:

> On Tuesday, 14 September 2021 at 16:43:50 UTC, jfondren wrote:

>> The misaligned pointer and the
>> reference-containing struct that vanishes on the return of
your
>> corresponding function are both problems for this.
>
> where did you find 'misaligned pointer'?...

I think it's the align(1) for EpollEvent.

I was able to reproduce the segmentation fault and was 
seemingly able to fix it by making the EventSource class 
references alive by adding a constructor:


align (1) struct EpollEvent {
align(1):
uint event_mask;
EventSource es;

  this(uint event_mask, EventSource es) {
this.event_mask = event_mask;
this.es = es;
living ~= es;  // <-- Introduced this constructor for this 
line

  }
/* just do not want to use that union, epoll_data_t */
}

// Here is the array that keeps EventSource alive:
EventSource[] living;

If that really is the fix, of course the references must be 
taken out of that container when possible.


Ali


Yep. This patch is sufficient to prevent the segfault:

```
diff --git a/engine/ecap.d b/engine/ecap.d
index 71cb646..d57829c 100644
--- a/engine/ecap.d
+++ b/engine/ecap.d
@@ -32,6 +32,7 @@ final class EventQueue {
 private int id;
 private bool done;
 private MessageQueue mq;
+private EventSource[] sources;

 private this() {
 id = epoll_create1(0);
@@ -52,6 +53,7 @@ final class EventQueue {

 void registerEventSource(EventSource es) {
 auto e = EpollEvent(0, es);
+sources ~= es;
 int r = epoll_ctl(id, EPOLL_CTL_ADD, es.id, );
 assert(r == 0, "epoll_ctl(ADD) failed");
 }
@@ -63,7 +65,10 @@ final class EventQueue {
 }

 void deregisterEventSource(EventSource es) {
+import std.algorithm : countUntil, remove;
+
 auto e = EpollEvent(0, es);
+sources = sources.remove(sources.countUntil(es));
 int r = epoll_ctl(id, EPOLL_CTL_DEL, es.id, );
 assert(r == 0, "epoll_ctl(DEL) failed");
 }
```

Going through the project and adding @safe: to the top of 
everything results in these errors: 
https://gist.github.com/jrfondren/c7f7b47be057273830d6a31372895895
some I/O, some @system functions, some weird C APIs ... and 
misaligned assignments to EpollEvent.es. So debugging with @safe 
isn't bad, but I'd still like rustc-style error codes:


```
engine/ecap.d(89): Error E415: field `EpollEvent.es` cannot 
assign to misaligned pointers in `@safe` code


$ dmd --explain E415

Yeah see, the garbage collector only looks for pointers at 
pointer-aligned addresses.

```


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread jfondren via Digitalmars-d-learn

On Tuesday, 14 September 2021 at 16:56:52 UTC, eugene wrote:

On Tuesday, 14 September 2021 at 16:43:50 UTC, jfondren wrote:

GC needs to be able to stop your program


nice fantasies...

and find all of the live objects in it. The misaligned pointer 
and the reference-containing struct that vanishes on the 
return of your corresponding function are both problems for 
this.


where did you find 'misaligned pointer'?...


It doesn't seem like communication between us is possible, in the 
"a five-pound phone won't sell" way. You can find this answer 
explained with code in an earlier post.


My suggestion remains: try troubleshooting by making your program 
@safe.


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread jfondren via Digitalmars-d-learn

On Tuesday, 14 September 2021 at 16:15:20 UTC, eugene wrote:

On Tuesday, 14 September 2021 at 16:07:00 UTC, jfondren wrote:

No. And when was the first one?


here:

On Monday, 13 September 2021 at 18:45:22 UTC, jfondren wrote:

 auto p = cast(EpollEvent*) pureMalloc(EpollEvent.sizeof);


What? Allocate struct epoll_event on the heap?
It is a feeble joke ;)


It is an example of deliberately static storage that does not fix 
your problem, thereby proving that the broken lifetimes of the 
struct are not your only problem.


I explained that one at the time, and I explained this one. If it 
comes with an explanation, it's probably not a joke.




```c
static int ecap__add(int fd, void *dptr)
{
struct epoll_event waitfor = {0};
   int flags, r;

waitfor.data.ptr = dptr;

r = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, );
if (-1 == r) {
```

All fd's (sockets, timers etc) are added the same way
and corresponding EventSources are not destroyed by GC.


GC needs to be able to stop your program and find all of the live 
objects in it. The misaligned pointer and the 
reference-containing struct that vanishes on the return of your 
corresponding function are both problems for this.


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread jfondren via Digitalmars-d-learn

On Tuesday, 14 September 2021 at 15:37:27 UTC, eugene wrote:

On Tuesday, 14 September 2021 at 14:56:00 UTC, jfondren wrote:
You could fix this by having a 128-bit struct and passing C an 
index into it


It is another "not so funny joke", isn't it?


No. And when was the first one?


```d
align (1) struct EpollEvent {
align(1):
uint event_mask;
EventSource es;
/* just do not want to use that union, epoll_data_t */
}
static assert(EpollEvent.sizeof == 12);
```


That's 96 bits. Add 32.

```d
class EventSource { }
align(1) struct EpollEvent {
align(1):
uint event_mask;
EventSource es;
}
struct OuterEpollEvent {
int _dummy;
uint event_mask;
EventSource es;
}
EpollEvent* epollEvent(return ref OuterEpollEvent ev) @trusted {
return cast(EpollEvent*) _mask;
}
void dumpEpollEvent(EpollEvent* ev) @trusted {
import std.stdio : writeln;

writeln(*ev);
}

unittest {
// can't be @safe:
// Error: field `EpollEvent.es` cannot modify misaligned 
pointers in `@safe` code

EpollEvent ev;
ev.es = new EventSource; // misaligned
}

@safe unittest { // this is fine
OuterEpollEvent ev;
ev.event_mask = 0;
ev.es = new EventSource; // not misaligned
ev.epollEvent.dumpEpollEvent;
}
```


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread jfondren via Digitalmars-d-learn

On Tuesday, 14 September 2021 at 14:40:55 UTC, eugene wrote:
On Tuesday, 14 September 2021 at 12:09:03 UTC, Steven 
Schveighoffer wrote:

This project is too big and complex


Really, "too big and complex"?
It's as simple as a tabouret :)
It's just a toy/hobby 'project'.


A 5-pound phone isn't "too heavy" for an adult to carry but it 
won't sell well. It's not just about capabilities but what 
efforts people are willing to expend.


I would troubleshoot your issue by gradually making it @safe and 
thinking about exceptions. One exception I didn't think about 
earlier was the 'misaligned pointer' one that I said I suppressed 
just to find the next @safe complaint:


https://dlang.org/spec/garbage.html says:

Do not misalign pointers if those pointers may point into the GC 
heap,


So even if the lifetimes of your EventSource structs are fixed, 
the GC can reap the object they're pointing to. You could fix 
this by having a 128-bit struct and passing C an index into it, 
so to speak.


Re: Program crash: GC destroys an object unexpectedly

2021-09-13 Thread jfondren via Digitalmars-d-learn

On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote:
Then after pressing ^C (SIGINT) the program gets SIGSEGV, since 
references to sg0 and sg1 are no longer valid (they are 
"sitting" in epoll_event structure).


engine/ecap.d(54): Error: field `EpollEvent.es` cannot assign to 
misaligned pointers in `@safe` code
engine/ecap.d(56): Error: cannot take address of local `e` in 
`@safe` function `registerEventSource`


from adding @safe to ecap.EventQueue.registerEventSource, and 
then from using a @trusted block to silence the first complaint.


Instead of using a temporary EpollEvent array in EventQueue.wait, 
you could make the array an instance variable and have 
registerEventSource populate it directly, so that the GC can 
always trace from this array to an EnventSource.


... however, I don't think this fixes your problem, or is your 
only problem, since the segfault's still observed when this 
memory is leaked:


```d
void registerEventSource(EventSource es) {
import core.memory : pureMalloc, GC;

auto p = cast(EpollEvent*) pureMalloc(EpollEvent.sizeof);
p.event_mask = 0;
p.es = es;
GC.addRoot(p);
int r = epoll_ctl(id, EPOLL_CTL_ADD, es.id, p);
assert(r == 0, "epoll_ctl(ADD) failed");
}
```


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread jfondren via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||

https://dlang.org/spec/operatoroverloading.html lists all the 
overloadable operators, and 
https://dlang.org/spec/expression.html has all the operators, so 
"which operators" is a matter of close comparison. "why not" is 
much harder to answer.


Re: Proper way to accept either static or dynamic array as a parameter

2021-09-11 Thread jfondren via Digitalmars-d-learn

On Sunday, 12 September 2021 at 02:44:36 UTC, Alex Bryan wrote:
`T[] dynArr` can be passed (by reference) to a function that 
takes `ref T[] data` but `T[10] data` cannot? Why not?


```d
void add1(ref int[] nums) {
nums ~= 1;
}

unittest {
int[] nums;
nums.add1;
nums.add1;
nums.add1;
assert(nums == [1, 1, 1]);
}
```

the `ref` allows `add1` to extend the length of the slice passed 
to it, with potential reallocation. This doesn't make sense with 
a static array whose length can't be modified.


Re: File difference module similar to the Linux command "comm"

2021-09-11 Thread jfondren via Digitalmars-d-learn

On Saturday, 11 September 2021 at 23:17:31 UTC, Vino wrote:

Hi All,

  May i know whether there is any module similar to  the Linux 
command "comm" (finding difference between 2 files), if present 
can you please guide me through link to the page nor do let me 
know  if there is any other solution.


Eg
File1
list1
list2
list3
lsit5

File2
list1
list3
lsit6

File1 : difference: list6
File2 : difference: list2,list5

From,
Vino


Take a look at https://dlang.org/phobos/std_algorithm_setops.html

With these inputs:

```d
import std.string : strip, splitLines;
import std.algorithm : equal, setDifference;

string[] File1 = q"EOF
list1
list2
list3
list5
EOF".strip.splitLines;

string[] File2 = q"EOF
list1
list3
list6
EOF".strip.splitLines;

unittest {
assert(["list2", "list5"].equal(File1.setDifference(File2)));
assert(["list6"].equal(File2.setDifference(File1)));
}
```


Re: Array permutations

2021-09-11 Thread jfondren via Digitalmars-d-learn

On Saturday, 11 September 2021 at 19:57:26 UTC, jfondren wrote:

auto pairs = list.cartesianProduct(list.drop(1))


This `drop` isn't necessary.


Re: Array permutations

2021-09-11 Thread jfondren via Digitalmars-d-learn

On Saturday, 11 September 2021 at 19:37:42 UTC, Vino wrote:

Hi All,

   Request your help on the below to print the below array as 
"Required output", Was able to get these values 
"[1,2],[2,3],[3,4],[4,5]" by using list.slide(2), need your 
help to get values "1,3],[1,4],[1,5],[2,4],[2,5],[3,5]"


auto list[] = [1,2,3,4,5]

Required output
[1,2],[2,3],[3,4],[4,5],[1,3],[1,4],[1,5],[2,4],[2,5],[3,5]

From,
Vino


I don't see the pattern just from the required output. If you 
have an English description of what you want, it might be easier.


Anyway, take a look at

```d
unittest {
import std.algorithm : cartesianProduct, filter, map, sort;
import std.range : drop;
import std.array : array;

auto list = [1,2,3,4,5];
auto required = 
[[1,2],[2,3],[3,4],[4,5],[1,3],[1,4],[1,5],[2,4],[2,5],[3,5]];

auto pairs = list.cartesianProduct(list.drop(1))
.filter!"a[0] < a[1]"
.map!array
.array;
assert(pairs == [[1, 2], [1, 3], [1, 4], [1, 5], [2, 3], [2, 
4], [2, 5], [3, 4], [3, 5], [4, 5]]);

assert(required.sort.array == pairs);
}
```


Re: How to simply parse and print the XML with dxml?

2021-09-09 Thread jfondren via Digitalmars-d-learn

On Thursday, 9 September 2021 at 23:29:56 UTC, Imperatorn wrote:

On Thursday, 9 September 2021 at 18:40:53 UTC, jfondren wrote:
On Thursday, 9 September 2021 at 17:17:23 UTC, tastyminerals 
wrote:

[...]


dxml.parser is a streaming XML parser. The documentation at 
http://jmdavisprog.com/docs/dxml/0.4.0/dxml_parser.html has a 
link to more information about this at the top, behind 'StAX'. 
Thus, when you're mapping over `xml`, you're not getting 
`some text` at a time, but ``, `some text`, and 
`` separately, as they're parsed. The `` there is an 
`elementStart` which lacks a `text`, hence the error.


[...]


That's a nice trick you did there


Something in the quoted text?

Or if you mean the self-string-importing script that uses the 
content after `__EOF__` , yeah, that's in imitation of Perl's 
`__DATA__` https://perldoc.perl.org/perldata#Special-Literals


Re: How to simply parse and print the XML with dxml?

2021-09-09 Thread jfondren via Digitalmars-d-learn
On Thursday, 9 September 2021 at 17:17:23 UTC, tastyminerals 
wrote:
Maybe I missed something obvious in the docs but how can I just 
parse the XML and print its content?


```
import dxml.parser;

auto xml = parseXML!simpleXML(layout);
xml.map!(e => e.text).join.writeln;
```

throws 
`core.exception.AssertError@../../../.dub/packages/dxml-0.4.3/dxml/source/dxml/parser.d(1457): text cannot be called with elementStart`.


dxml.parser is a streaming XML parser. The documentation at 
http://jmdavisprog.com/docs/dxml/0.4.0/dxml_parser.html has a 
link to more information about this at the top, behind 'StAX'. 
Thus, when you're mapping over `xml`, you're not getting `some 
text` at a time, but ``, `some text`, and `` 
separately, as they're parsed. The `` there is an 
`elementStart` which lacks a `text`, hence the error.


Here's a script:

```d
#! /usr/bin/env dub
/++ dub.sdl:
dependency "dxml" version="0.4.0"
stringImportPaths "."
+/
import dxml.parser;
import std;

enum text = import(__FILE__)
.splitLines
.find("__EOF__")
.drop(1)
.join("\n");

void main() {
foreach (entity; parseXML!simpleXML(text)) {
if (entity.type == EntityType.text)
writeln(entity.text.strip);
}
}
__EOF__


some text


more text

```

that runs with this output:

```
some text
more text
```


Re: Is std.variant useful for types only known at run time?

2021-09-08 Thread jfondren via Digitalmars-d-learn

On Wednesday, 8 September 2021 at 09:55:20 UTC, Chris Piker wrote:
Interesting.  I presume that the big win for using std.sumtype 
over a class set is value semantics instead of reference 
semantics?


There's a lot to say about the precise differences. One practical 
difference that I alluded to earlier is that an incomplete 
`match!` is a compile-time error, so if you later add a fifth 
kind of time encoding to your sumtype, the compiler will give you 
a laundry list of parts of your code to update to handle the new 
case.


So out of curiosity, say each structure implemented a function 
to provide the desired broken-down-time, would the following 
"virtual function" style call work?


```d
import std.sumtype;
struct BDTime { int y, int m, int d, int h, int m, double s };

struct ISO8601 { BDTime bdTime(){ ... }  }
struct FloatEpoch { BDTime bdTime(){ ... } }
struct DoubleEpoch { BDTime bdTime(){ ... } }
struct LongEpoch { BDTime bdTime(){ ... }  }
alias Time = SumType!(ISO8601, FloatEpoch, DoubleEpoch, 
LongEpoch);


void main() {
import std.stdio : writeln;
import std.format : format;

Time e = ISO8601();
BDTime = e.bdTime();
}
```
or would I need to use `match!` to get the right structure type 
and then generate the internal time representation?


You'd get an error like

```
Error: no property `bdTime` for type 
`std.sumtype.SumType!(ISO8601, ...)`

```

bdTime is defined for the individual times and not for the 
sumtype. You could have a match! that pulls out each member and 
calls its individual .bdTime(), but probably a more natural 
solution is to define bdTime only once, against the sumtype, 
where it has an internal `match!` that pulls out the different 
properties of the members that are necessary for each to 
construct a BDTime.


Re: Is std.variant useful for types only known at run time?

2021-09-08 Thread jfondren via Digitalmars-d-learn

On Wednesday, 8 September 2021 at 07:10:21 UTC, Chris Piker wrote:

Hi D

I'm working on data streaming reading module where the encoding 
of each input array isn't known until runtime.  For example 
date-time column values may be encoded as:


   * An ISO-8601 UTC time string (aka char[])
   * A ASCII floating point value with an indicated unit size 
and epoch (aka char[])
   * A IEEE double with an indicated endianness, unit size, and 
epoch. (aka double[])
   * A 64-bit signed in with an indicated endianness, unit 
size, and epoch. (aka long[])


a std.variant.Variant can contain *any* type, but this only four 
types, so I'd look at a std.sumtype of them first:


```d
import std.sumtype;

struct ISO8601 { }
struct FloatEpoch { }
struct DoubleEpoch { }
struct LongEpoch { }
alias Time = SumType!(ISO8601, FloatEpoch, DoubleEpoch, 
LongEpoch);


void main() {
import std.stdio : writeln;
import std.format : format;

Time e = ISO8601();
writeln(e.match!(
(FloatEpoch _) => "doesn't happen",
(DoubleEpoch _) => "doesn't happen",
(LongEpoch _) => "an error to omit, unlike the next 
example",

(ISO8601 time) => format!"%s"(time),
));
}
```

...

I'm wondering if std.variant is useful in cases where type 
information is only known at run-time, since many of the 
flexible data structures I've run across so far in D require 
compile-time information.


It is. It's used for message passing in std.concurrency for 
example, where an actor can receive any kind of type into its 
messagebox. If std.sumtype didn't exist then I might look at 
std.variant or a novel discriminated union of my own or OOP, 
where an option is to try casting to the different subtypes until 
the cast works:


```d
class Encoding { }
class ISO8601 : Encoding { }
class FloatEpoch : Encoding { }
class DoubleEpoch : Encoding { }
class LongEpoch : Encoding { }

void main() {
import std.stdio : writeln;

Encoding e = new ISO8601;
if (!cast(FloatEpoch) e) writeln("it's null");
if (!cast(LongEpoch) e) writeln("it's null");
if (auto time = cast(ISO8601) e)
writeln(time);
}
```


Re: Looking to get typeof parseXML return value

2021-09-06 Thread jfondren via Digitalmars-d-learn

On Tuesday, 7 September 2021 at 04:13:08 UTC, Chris Piker wrote:

Any ideas on how to get the return type of `parseXML` below:
```
import dxml.parser;

const(char)[] _mmfile;
//_mmfile initialization

TYPE??? _entityRng = parseXML!(simpleXML)(_mmfile);
```
*before* calling parseXML, so that it can be a class member 
variable?


Here's a quick script:

```d
#! /usr/bin/env dub
/++ dub.sdl:
dependency "dxml" version="0.4.0"
+/
import dxml.parser;
import std.stdio : writeln;

struct SomeXML {
EntityRange!(simpleXML, string) xml;
}

struct Again {
typeof(parseXML!simpleXML("")) xml;
}

void main() {
auto xml = parseXML!simpleXML("");
pragma(msg, typeof(xml)); // compile time
writeln(typeid(xml)); // runtime

SomeXML some = SomeXML(xml);
foreach (_; 0 .. 4) {
writeln(some.xml.front);
some.xml.popFront;
}
auto again = Again(xml);
writeln(again.xml.front);
}
```

EntityRange have two template parameters, a Config with four 
flags (where simpleXML has all flags set to yes) and the type of 
the forward range supplying characters to be parsed. So, 
`EntityRange!(simpleXML, string)` works as a type of those are 
really what you'll be using, `typeof(parseXML!simpleXML(""))` 
works as a type by seeing what type parseXML returns when invoked 
like that.


Re: "+=" (overloads) with custom array slices on both lhs, and rhs ??

2021-09-05 Thread jfondren via Digitalmars-d-learn
On Sunday, 5 September 2021 at 20:49:08 UTC, james.p.leblanc 
wrote:

On Sunday, 5 September 2021 at 20:38:29 UTC, Paul Backus wrote:
Please post the source code for `myarray_mod` so that we can 
reproduce the errors you're seeing.


Hello Paul,

Thanks for having a look ...

James


Here's a reduction of your myArray.d that works with your 
unchanged usage code:


```d
module myArray;
import std.stdio;

struct myArray {
int* ptr;
size_t length;

myArray opIndex() {
return this;
}

int opIndex(size_t i) {
return ptr[i];
}

void opIndexOpAssign(string op)(int val, int ind) {
if ((op == "+") || (op == "-") || (op == "*") || (op == 
"/")) {

mixin(" ptr[ind] " ~ op ~ "= val;");
}
}

myArray opSlice(size_t start, size_t end) {
return myArray([start], end - start);
}

void opOpAssign(string op)(int rhs) if (op == "+") {
foreach (i; 0 .. length) {
mixin("ptr[i] " ~ op ~ "= i;");
}
}

void opOpAssign(string op)(myArray rhs) if (op == "+") {
foreach (i; 0 .. length) {
mixin("ptr[i] " ~ op ~ "= rhs.ptr[i];");
}
}
}
```


Re: Forum posting question ... how post a thread question with color syntax highlighting ??

2021-09-05 Thread jfondren via Digitalmars-d-learn
On Sunday, 5 September 2021 at 17:48:51 UTC, james.p.leblanc 
wrote:

Dear All,

I have noticed that quite a few posts and responses on this
forum include d snippets made with **nicely colored syntax 
highlighting.**

(I do not mean just the bold markdown text.)

This increases post clarity significantly.

How is this being done?  (I hope that this is not considered off
topic.  My goal would be able to make such posts myself.  But 
also,

if more post in this manner, it may help many.)

Best Regards,
James


There's a checkbox below the post next to 'Enable Markdown'. 
You've found that with the bold markdown. If you click 
'Markdown', it's a link to https://forum.dlang.org/help#markdown 
which includes an example of syntax highlighting:


\```d
// I have a backslash in front of \```
string s = "so this isn't highlighted";
\```

```d
// no backslash
string s = "this has d syntax highlighting";
```


Re: Why can't the DMD compiler accept files or directories with white spaces even delimited by quotes?

2021-09-04 Thread jfondren via Digitalmars-d-learn

On Saturday, 4 September 2021 at 23:50:33 UTC, Marcone wrote:

Example:

dmd "hello world.d"


```
$ cat hello\ world.d
module helloworld;
void main() {
import std.stdio : writeln;
writeln("without the explicit 'module', this file would");
writeln("be inferred to have an invalid module name.");
}
$ dmd 'hello world.d'
$ ./hello\ world
without the explicit 'module', this file would
be inferred to have an invalid module name.
$ sed -i 1d hello\ world.d
$ dmd 'hello world.d'
hello world.d: Error: module `hello world` has non-identifier 
characters in filename, use module declaration instead

```


Re: why is it a class property cannot be used like a.b ~= c; ?

2021-09-04 Thread jfondren via Digitalmars-d-learn

On Saturday, 4 September 2021 at 23:33:39 UTC, someone wrote:

```d
public class cSomething {

   private:

   dstring pstrWhatever = null;

   public:

   @safe dstring whatever() { return pstrWhatever; }
   @safe void whatever(const dstring lstrWhatever) { 
pstrWhatever = lstrWhatever; }


}

void main() {

   cSomething lobjSomething = new cSomething();
   lobjSomething.whatever = r"abc"d;
   lobjSomething.whatever ~= r"def"d; /// Error: 
`lobjSomething.whatever()` is not an lvalue and cannot be 
modified


}
```


You're returning a copy of a slice, so if this compiled nothing 
useful would happen anyway. This works if `whatever()` returns 
`ref dstring` instead, with no other changes. Search 
https://dlang.org/spec/function.html for 'lvalue' and this pops 
right up.


Re: Phobos Unittest

2021-09-04 Thread jfondren via Digitalmars-d-learn

On Saturday, 4 September 2021 at 20:06:27 UTC, Per Nordlöw wrote:
On Saturday, 4 September 2021 at 20:05:17 UTC, Per Nordlöw 
wrote:

```sh
time dmd import_std.d -o-
```


should be

```sh
time dmd -unittest import_std.d -o-
```


When you generate the object files, I get 13K vs. 75K from a file 
containing just `import std;`. More than parsing is happening 
differently.


```
$ objdump -dwr --no-show-raw-insn importstd.o |ddemangle | grep 
-oP 'std[\w.]+'|sort|uniq -c|sort -n|awk '$1 > 1'

 28 std.uni.InversionList
 28 std.uni.MultiArray
 30 std.encoding.BOM
 31 std.array.Appender
 35 std.concurrency.List
 35 std.concurrency.Message
 38 std.uni.CowArray
 44 std.variant.VariantN
 56 std.typecons.Tuple
 56 std.uni.BitPacked
 66 std.uni.GcPolicy
```


Re: Run-time setting of immutable variable?

2021-09-02 Thread jfondren via Digitalmars-d-learn

On Thursday, 2 September 2021 at 17:17:15 UTC, DLearner wrote:
Surely there is no inconsistency - at run time the array is in 
a fixed place,  so ArrPtr is (or at least should be) a 
constant, but the contents of the array

can vary as the program runs.


In the case of `immutable(T)* ArrPtr`, the contents of the 
pointed-to array cannot vary as the program runs. If it's 
immutable, nothing in the program ever mutates it. In the case of 
`const(T)* ArrPtr`, the contents of the pointed-to array can vary 
as the program runs, and the only restriction is that the array 
can't be mutated through ArrPtr.


If what you mean is that you want the *pointer* to never change, 
`T * const ArrPtr` in C syntax, but that you don't care if the 
pointed-to array changes via ArrPtr or any other reference, then 
I don't think D can express this. You could make ArrPtr a 
function:


```d
void main() {
int[] xs = [1, 2, 3, 4];
int* p() { return [2]; }
p[0] = 0;
assert(xs == [1, 2, 0, 4]);
p++; // Error: ... not an lvalue and cannot be modified
}
```


Re: Documentation generator is not working

2021-09-02 Thread jfondren via Digitalmars-d-learn
On Thursday, 2 September 2021 at 16:20:32 UTC, Vinod K Chandran 
wrote:

Hi all,
I am playing with ddoc. I wrote this code--
```d
import std.stdio : log = writeln;

void main() {
log("Experimenting with dDoc");
}

/// A sample function.
/// Let's check what we will get in documentation.
/// abc - A simple string
void sample(string abc) {log(abc);}
```
And then, compile it with "-D" switch. At first, I saw an html 
file is generated. But I deleted it and compiled again. This 
time, no html file is generated. What's wrong with this ?


What commands are you running? What you describe doing, works:

```
$ cat file.d
import std.stdio : log = writeln;

void main() {
log("Experimenting with dDoc");
}

/// A sample function.
/// Let's check what we will get in documentation.
/// abc - A simple string
void sample(string abc) {log(abc);}

$ dmd -D file

$ w3m -dump file.html|grep -A1 function
A sample function. Let's check what we will get in 
documentation. abc - A

simple string

$ rm -fv file.html
removed 'file.html'

$ dmd -D file

$ w3m -dump file.html|grep -A1 function
A sample function. Let's check what we will get in 
documentation. abc - A

simple string
$
```


Re: Dustmite and linking error

2021-09-02 Thread jfondren via Digitalmars-d-learn

On Thursday, 2 September 2021 at 11:04:12 UTC, JG wrote:

Hi,

We hit a linking error (after upgrading to dub 1.26.0). I 
thought I would try to use dustmite to create a reduced error 
test case. One week later it is still running (depth 22). I 
don't suppose there is anyway of determining when it will 
finish?


Possibly it's not a compiler error at all but a name-mangling 
change combined with some stale objects in your build.


Re: Question on Immutability

2021-08-31 Thread jfondren via Digitalmars-d-learn

On Tuesday, 31 August 2021 at 05:42:22 UTC, ag0aep6g wrote:

On 31.08.21 02:50, Mike Parker wrote:
Member functions marked as immutable can be called on both 
mutable and immutable instances.


That's not true.


Demonstrated:

```d
struct S {
int x;
int get() immutable { return x; }
}

unittest {
auto s1 = S(1);
const s2 = S(2);
immutable s3 = S(3);
assert(s1.get == 1); // Error: is not callable using a 
mutable object
assert(s2.get == 2); // Error: is not callable using a 
`const` object

assert(s3.get == 3);
}
```

s/immutable/const/ and all those uses are acceptable.


Re: byte + byte = int: why?

2021-08-29 Thread jfondren via Digitalmars-d-learn

On Sunday, 29 August 2021 at 15:57:18 UTC, Paul Backus wrote:

On Sunday, 29 August 2021 at 15:42:18 UTC, Ali Çehreli wrote:
Depending on the situation, you may want to use std.conv.to, 
which does a value range check and throws an exception to 
prevent an error:


byte foo(byte a, byte b) {
  import std.conv : to;
  return (a + b).to!byte;
}

void main() {
  foo(42, 42);// Works
  foo(100, 100);  // Throws ConvOverflowException
}


I was going to suggest `std.experimental.checkedint` as an 
alternative here, but it turns out that it does integer 
promotion too--`Checked!byte + Checked!byte == Checked!int`.


This seems obviously wrong to me, but according to run.dlang.io 
it's always worked that way.


(a.checked + b).get is int, but this works:

```d
import std.experimental.checkedint;

byte foo(byte a, byte b) {
auto c = a.checked;
c += b;
return c.get;
}

unittest {
import std.exception : assertThrown;
import core.exception : AssertError;

foo(42, 42);
assertThrown!AssertError(foo(100, 100));
}
```

... after Phobos is patched.

```
error: undefined identifier ‘Lhs’, did you mean alias ‘Rhs’?
```


Re: A way to mixin during runtime?

2021-08-27 Thread jfondren via Digitalmars-d-learn

On Friday, 27 August 2021 at 10:34:27 UTC, Kirill wrote:

Each csv file will be different.

For example:
```
name;surname;age;grade
Alex;Wong;18;87
John;Doe;19;65
Alice;Doe;18;73
etc...
```

I'd like to extract the data types automatically. For instance, 
if using tuples:

```
Tuple!(string, string, int, int) ...
```
instead I'd like to have:
```
auto mytuple = read_csv(path); // returns Tuple!(string, 
string, int, int)[]

```


mytuple needs to have a type that's known at compile-time, so 
this isn't possible. In the types are only dynamically known, 
then you have to deal in dynamic types. One way could be to have 
a read_csv that returns an array of 
https://dlang.org/phobos/std_variant.html


Re: Mixin/static if issue

2021-08-25 Thread jfondren via Digitalmars-d-learn

On Wednesday, 25 August 2021 at 22:52:23 UTC, DLearner wrote:

On Wednesday, 25 August 2021 at 22:33:00 UTC, H. S. Teoh wrote:
[...}


I think what you meant to write is:

   static if (typeof(mixin(VarName)).stringof == "uint") {

You want the type of the variable named by VarName, not the 
type of VarName.



T


I understand your reasoning, but:

```
void main() {
   import std.stdio;

   uint TestVar = 5;

   string mxnWrite_Size_t(string VarName) {

  static if (typeof(mixin(VarName)).stringof == "uint") {

 return `write("` ~ VarName ~ `");`;
  } else {

 return `writeln("Apparently TestVar not a uint");`;  
  }
   }

   mixin(mxnWrite_Size_t("TestVar"));
}
```
produced Error: variable `VarName` cannot be read at compile 
time


Contrast:

```d
void main() {
   import std.stdio;

   uint TestVar = 5;

   string mxnWrite_Size_t(string VarName)() {

  static if (typeof(mixin(VarName)).stringof == "uint") {

 return `write("` ~ VarName ~ `");`;
  } else {

 return `writeln("Apparently TestVar not a uint");`;  
  }
   }

   mixin(mxnWrite_Size_t!"TestVar");
}
```

Output: TestVar


Re: alias this - am I using it wrong?

2021-08-25 Thread jfondren via Digitalmars-d-learn

On Wednesday, 25 August 2021 at 12:11:01 UTC, Johann Lermer wrote:

```d
14 void main ()
15 {
16 auto ac = new Alias_Class;
17 Test_Struct ts = ac;  // compiles
18 ac = ts;  // compiles as well - why?
19
20 auto tc = new Test_Class;
21 ts = tc.ac;   // compiles
22 tc.ac = ts;   // again this compiles, but seg 
faults

23 }
```


line 17: ac.ts is copied into main's ts
line 18: main's ts is copied back into ac.ts

You can confirm this by changing t, doing the copy, and then 
checking t.


line 21: segfaults because tc.ac is null, and you're trying to 
copy tc.ac.ts into main's ts


Re: foreach() behavior on ranges

2021-08-24 Thread jfondren via Digitalmars-d-learn

On Tuesday, 24 August 2021 at 08:36:18 UTC, frame wrote:
Consider a simple input range that can be iterated with 
empty(), front() and popFront(). That is comfortable to use 
with foreach() but what if the foreach loop will be cancelled? 
If a range isn't depleted yet and continued it will supply the 
same data twice on front() in the next use of foreach().


I think you strayed from the beaten path, in a second way, as 
soon as your range's lifetime escaped a single expression, to be 
possibly used in two foreach loops. With ranges, as you do more 
unusual things, you're already encouraged to use a more advanced 
range. And ranges already have caveats for surprising behavior, 
like map/filter interactions that redundantly execute code. So I 
see this as a documentation problem. The current behavior of 'if 
you break then the next foreach gets what you broke on' is 
probably a desirable behavior for some uses:


```d
import std;

class MyIntRange {
int[] _elements;
size_t _offset;

this(int[] elems) { _elements = elems; }

bool empty() { return !_elements || _offset >= 
_elements.length; }


int front() { return _elements[_offset]; }

void popFront() { _offset++; }
}

void main() {
auto ns = new MyIntRange([0, 1, 1, 2, 3, 4, 4, 4, 5]);
// calls writeln() as many times as there are numbers:
while (!ns.empty) {
foreach (odd; ns) {
if (odd % 2 == 0) break;
writeln("odd: ", odd);
}
foreach (even; ns) {
if (even % 2 != 0) break;
writeln("even: ", even);
}
}
}
```


Re: compile time compression for associatve array literal

2021-08-23 Thread jfondren via Digitalmars-d-learn

On Monday, 23 August 2021 at 14:04:05 UTC, Brian Tiffin wrote:
That's the goal.  It's an optional goal at this point.  I'm not 
*really* worried about size of object code, yet, but figured 
this would be a neat way to shrink the compiled code generated 
from some large COBOL source fragments embedded in D source.


The decompression needs to happen at runtime, where these 
libraries are still useful. The compression could happen through 
CTFE once some suitable compression code is written in D, but 
that's not actually required to get the results of


1. your object file contains compressed strings

2. your program decompresses them at runtime

You can still achieve this end by having your build system 
compress external files that D then includes.


Manually setting this up:

```
$ dd if=/dev/zero bs=$((1024*1024)) count=1024 of=gigabyte.data
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.3655 s, 786 MB/s

$ time zip giga.zip gigabyte.data
  adding: gigabyte.data (deflated 100%)

real0m5.645s
user0m5.470s
sys 0m0.160s

$ du -sh giga.zip
1020K   giga.zip

$ dmd -J. -O zeroes.d

$ du -sh zeroes
3.3Mzeroes

$ time ./zeroes > out.data

real0m3.310s
user0m1.486s
sys 0m1.167s

$ diff -s gigabyte.data out.data
Files gigabyte.data and out.data are identical
```

From this zeroes.d:

```d
import std.stdio : write;
import std.zip;

enum zeroes = import("giga.zip");

void main() {
auto zip = new ZipArchive(cast(char[]) zeroes);
ArchiveMember am = zip.directory.values[0];
zip.expand(am);
write(cast(char[]) am.expandedData);
}
```


Re: Unexpected result comparing to null

2021-08-23 Thread jfondren via Digitalmars-d-learn

On Monday, 23 August 2021 at 13:00:36 UTC, DLearner wrote:

Hi

The code below compiles and runs producing 'Not null'.

```
void main()
{
   import std.stdio;

   int Var1;
   int* ptrVar;

   ptrVar = 

   if (ptrVar == null) {
  writeln("Null");
   } else {
  writeln("Not null");
   }
}
```

However, should it not fail to compile, as '==' used instead of 
'is'?


Best regards


Perhaps you're thinking of note 12 in 
https://dlang.org/spec/expression.html#equality_expressions ?


Which ends:

"Comparing against null is invalid, as null has no contents. Use 
the is and !is operators instead."


But also begins:

"**For class objects**, the == and != operators are intended to 
compare the contents of the objects, however an appropriate 
opEquals override must be defined for this to work. The default 
opEquals provided by the root Object class is equivalent to the 
is operator."


ptrVal is just an int*, and == against it implies no attempt look 
for a opEquals.


Contrast:

```d
class S {
int* p;
this(int* p) {
this.p = p;
}
}

void main() {
import std.stdio;

int Var1;
auto ptrVar = new S();

if (ptrVar == null) {
writeln("Null");
} else {
writeln("Not null");
}
}
```

Which fails to compile with

```
Error: use `is` instead of `==` when comparing with `null`
```


Re: Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread jfondren via Digitalmars-d-learn

On Sunday, 22 August 2021 at 14:40:29 UTC, james.p.leblanc wrote:
It is a bit scary how you guessed very closely what I am trying 
to
do.  I have a AVX aligned pointers (obtained from fftw_malloc), 
that I

want to protect.

To be a bit more specific.  The code that reads/writes from 
to/from fftw
routines is all pointer based.  But, to allow use of standard 
dlang things
such as "foreach" and friends, I've been cobbling together a 
(naive) wrapper.


This allows me to use standard dlang syntax and operator 
overloads.  I call my
struct "fakeArray" ... since it is meant to behave either as a 
static array,

or a dynamic array as needed.

It **seems** to work pretty well ... but protecting the arrays 
from accidental
programming mistakes (such as the "auto y=x") has been eluding 
me.


OK, rather than roll your own solution, Unique!Foo might do what 
you want, from https://dlang.org/phobos/std_typecons.html#Unique


Re: Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread jfondren via Digitalmars-d-learn

On Sunday, 22 August 2021 at 13:03:20 UTC, james.p.leblanc wrote:

On Sunday, 22 August 2021 at 11:10:33 UTC, jfondren wrote:
On Sunday, 22 August 2021 at 07:58:12 UTC, james.p.leblanc 
wrote:

Hello,

If you don't get an answer that you like, I suggesting posting 
functional code and then stating your dissastisfactions with 
it.


Mattias, jfondren,

Thanks both for your replies, I always learn something from 
them.


I've trimmed my code to a minimal example to give a better idea
of my thinking on this.


I still really don't get what you're trying to do, to the point 
of wanting to know: are you making 'myadd' a field for this 
struct only so that you can check it against the address of the 
variable? Or is it a real example of data you want to protect 
from accidental copies that just, coincidentally, can also be 
used to check if the struct has been copied? And, still, are you 
sure that you want a struct and not a class?


The idea of not polluting the original of a struct requires some 
reference types as members of the struct, or a pointer, as 
otherwise everything is copied and the original is perfectly 
'protected' anyway.


Here's a struct that
1. has an int* as an example of data that shouldn't be copied, 
for example because it would result in a double free on 
destruction
2. protects against bad copies, not by forbidding copies, but by 
nulling the int* with a postblit
3. can then report that it's an original vs. a copy by seeing if 
the int* is null


```d
import std.stdio;
import core.memory : pureMalloc, pureFree;

struct Foo {
int a, b, c;
int* unique;

this(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
unique = cast(int*) pureMalloc(int.sizeof);
*unique = a * b * c;
}

void report() const {
if (unique)
writeln("I'm the original: ", *unique);
else
writeln("I am an incomplete copy :(");
}

this(this) {
unique = null;
}

~this() {
pureFree(unique);
}
}

void alwaysGetsACopy(Foo f) {
assert(f.unique is null);
}

void reportIfOriginal(ref Foo f) {
if (f.unique !is null)
f.report;
}

void main() {
auto x = Foo(1, 2, 3);
auto y = x;

x.report; // I'm an original
y.report; // I'm a copy
x.alwaysGetsACopy; // assertion succeeds
x.reportIfOriginal; // I'm an original
y.reportIfOriginal;
}
```


Re: Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread jfondren via Digitalmars-d-learn

On Sunday, 22 August 2021 at 07:58:12 UTC, james.p.leblanc wrote:

Hello,

Question about a possible strategy to avoid problems with
undesired/unintended copying of a structure:

1) We have a struct, call this **Foo**.

2) We instantiate it with,   **x = Foo(a,b,c);**
   a.  our constructor will initialize a field:  
**this.myadd = **
   b.  this capture the address of our original "x" in 
x.myadd.


Sorry, I don't follow this at all.

Consider:

```d
struct Foo {
int a, b, c;
Foo* myadd;

this(int a, int b, int c) {
myadd = 
this.a = a;
this.b = b;
this.c = c;
}
}

void main() {
import std.stdio : writeln;

Foo x; // initialized with (0, 0, 0, null)
writeln(); // a memory location
x = Foo(1, 2, 3); // (1, 2, 3, )

writeln(); // the exact same memory location
writeln(x.myadd.a); // 1, rather than 0, because ==x.myadd
}
```

There's no saving the original "x" here, it's overwritten by the 
assignment. Are you sure you don't want classes instead, to get 
reference semantics?



4) Our goal is to avoid problems with any accidental copying
   of x ... say by doing:  **auto y=x;**

5) the copy of step 4 **does not use the constructor**, thus 
y.myadd

   would contain the address of x (and not y)


`auto y=x;` actually does call object lifetime functions.

```d
struct CountCopies {
int copies;

this(this) { // postblit
copies++;
}
}

unittest {
CountCopies x;
auto y = x;
auto z = y;
assert(x.copies == 0);
assert(y.copies == 1);
assert(z.copies == 2);
}
```

or with a copy constructor,

```d
struct CountCopies {
int copies;

this(ref return scope const CountCopies rhs) { // copy 
constructor

copies = rhs.copies + 1;
}
@disable this(this); // helps pre-copy-constructor compilers 
reject this code

}

unittest {
CountCopies x;
auto y = x;
auto z = y;
assert(x.copies == 0);
assert(y.copies == 1);
assert(z.copies == 2);
}
```


Some initial experiments lead me to believe this may acheive
part of what I would like.  But, it feels very "hackish" and
ugly.

Is there a better way?


If you don't get an answer that you like, I suggesting posting 
functional code and then stating your dissastisfactions with it.


Re: Unqualified class name

2021-08-21 Thread jfondren via Digitalmars-d-learn

On Sunday, 22 August 2021 at 00:18:18 UTC, Ali Çehreli wrote:
I did not read the linked thread but a "this template 
parameter" seems to work in this case:


class Whoami {
  string name(this This)() const {
return __traits(identifier, This);
  }
}
class AnotherOne : Whoami { }

unittest {
  assert((new Whoami).name == "Whoami");
  assert((new AnotherOne).name == "AnotherOne");
}

void main() {
}

Ali


That's not enough to make runtime dispatch out of static dispatch:

```d
class Whoami {
string name(this This)() const {
return __traits(identifier, This);
}

string rtname() const {
import std.path : extension;

return typeid(this).name.extension[1 .. $];
}
}

class AnotherOne : Whoami { }

unittest {
import std.algorithm : map, equal;

auto list = [new Whoami, new AnotherOne];
assert(list.map!(o => o.name).equal(["Whoami", "Whoami"]));
assert(list.map!(o => o.rtname).equal(["Whoami", 
"AnotherOne"]));

}
```

The next stage of complication is to have compiled library code 
that loops over Whoami[] getting some subtypes of Whoami that 
were defined unknowable to the library.


Re: Unqualified class name

2021-08-21 Thread jfondren via Digitalmars-d-learn
On Saturday, 21 August 2021 at 21:13:58 UTC, Jeremy T. Gibson 
wrote:

On Saturday, 21 August 2021 at 18:27:34 UTC, Ali Çehreli wrote:

return __traits(identifier, typeof(this));


That works perfectly!  Thanks. =)


This is exactly the solution you linked to in your first post, 
and found wanting.


```d
class Whoami {
string name() {
return __traits(identifier, typeof(this));
}
}
class AnotherOne : Whoami { }

unittest {
assert((new Whoami).name == "Whoami");
assert((new AnotherOne).name == "Whoami");
}
```


Re: Unqualified class name

2021-08-21 Thread jfondren via Digitalmars-d-learn
On Saturday, 21 August 2021 at 17:33:51 UTC, Jeremy T. Gibson 
wrote:
is there a simple way to get the unqualified name of a class at 
runtime without having to pass it through std.format?  
`typeid(class).name` always yields the full classname, 
including its module information (i.e., 
"modulename.classname"), where I only want "classname" on its 
own.


https://dlang.org/phobos/object.html#.TypeInfo_Class.name is all 
you have there, and it's just a string, so the simple way is to 
manipulate the string.


This seems a bit silly but I'm not worried about VMS 2.0 coming 
along and changing how extensions work ("nodot".extension == "" 
however, so if module-less classes are possible then this would 
fail with a RangeError):


```d
class Whoami {
string report() {
import std.path : extension;

return "class: " ~ typeid(this).name.extension[1..$];
}
}

class AnotherOne : Whoami {}

unittest {
assert((new Whoami).report == "class: Whoami");
assert((new AnotherOne).report == "class: AnotherOne");
}

string unqualified(string name) {
import std.string : lastIndexOf;
import std.algorithm : min;

const i = name.lastIndexOf('.');
return i == -1 ? name : name[min(i+1, $) .. $];
}

unittest {
assert(typeid(new Whoami).name.unqualified == "Whoami");
assert(typeid(new AnotherOne).name.unqualified == 
"AnotherOne");

assert("".unqualified == "");
assert("x".unqualified == "x");
assert("x.".unqualified == "");
}
```


Re: std.stdio.File is throwing with the message of: "Access Violation"

2021-08-20 Thread jfondren via Digitalmars-d-learn
On Friday, 20 August 2021 at 21:19:09 UTC, Ruby The Roobster 
wrote:
   MessageBoxA(null, "Error", 
cast(char)[])e.msg,MB_OK | ICON_ERROR);


use std.string.toStringz to ensure that e.msg is 0-terminated.


Re: Why the very same code works in main and not in unittest?

2021-08-20 Thread jfondren via Digitalmars-d-learn

On Friday, 20 August 2021 at 16:02:22 UTC, Pablo De Nápoli wrote:

Consider the following code:

void main()
{
  mpd_context_t ctx;
  mpd_t* a;
  mpd_ieee_context(, 128);
  a= mpd_new();
}

It seems to work fine.

...
However, if I put the very same code in the unittest section of 
a module, it fails with

a segmentation fault and I don't understand why!


unittest blocks are just functions, so this is pretty strange. At 
a guess, you have some library setup code and are putting that in 
a module with main() instead of in `shared static this()` in the 
module you're getting mpd_new from, so unit testing is skipping 
this setup code.




Personally, I found the unittest mechanism rather obscure. 
For instance I have tried to debug the problem using gdb and I 
found that the following code was run


module dub_test_root;
...


dub, probably mainly for historical dmd reasons, has some extra 
steps to make unittests more convenient. You can call dmd 
directly with -unittest to avoid that, or accept that it's there.



I rather prefer a separate test program!


unittest builds are generally separate programs. dub manually 
removes your main(), but recent dmd also skip it automatically.


If you mean that you'd prefer to have your tests in separate 
source files, there's nothing stopping you from doing that, 
you're just going slightly off the beaten path. Probably the 
easiest way to do it is to have a configuration that excludes 
your main(), and other configurations that exclude your tests. 
dcd's dub.json shows this off well with its client/server/library 
builds: 
https://github.com/dlang-community/DCD/blob/master/dub.json


Another way to do this is to create a separate 'tests' dub 
application in a subdirectory which includes all of the library. 
Whatever works for you.


Re: "...cannot be interpreted at compile time" I can't find the source of the error!

2021-08-19 Thread jfondren via Digitalmars-d-learn

On Friday, 20 August 2021 at 02:30:53 UTC, Pablo De Nápoli wrote:
Any idea of which could be the cause of trouble or on how to 
get more specific 	diagnosis?


With no extra arguments I get a "compile time context created 
here" addendum. Does that not show up for you or does the line 
not make sense still?


It might also be new. This is with v2.097.1

```
example.d(6): Error: `atoi` cannot be interpreted at compile 
time, because it has no available source code

example.d(12):compile time context created here
example.d(13): Error: no property `val` for type `void`
```

From this code:

```d
extern (C) int atoi(const(char)* nptr);

class N {
int val;
this() {
val = atoi("2");
}
}

void main() {
import std.stdio : writeln;
enum n = new N(); // line 12
writeln(n.val);
}
```


Re: How to get element type of a slice?

2021-08-18 Thread jfondren via Digitalmars-d-learn

On Thursday, 19 August 2021 at 03:32:47 UTC, Jesse Phillips wrote:
On Thursday, 19 August 2021 at 03:29:03 UTC, Jesse Phillips 
wrote:
On Tuesday, 17 August 2021 at 12:33:03 UTC, Ferhat Kurtulmuş 
wrote:

On Tuesday, 17 August 2021 at 12:26:36 UTC, jfondren wrote:
On Tuesday, 17 August 2021 at 12:21:31 UTC, Ferhat Kurtulmuş 
wrote:

[...]


This one's not in std.traits:

```d
import std.range : ElementType;

struct Point { int x, y; }

unittest {
Point[] points;
assert(is(ElementType!(typeof(points)) == Point));
}
```


Hey, thank you again but, I don't want an instance of Point[] 
I need:


alias T = Point[];

alias ElementOfPointSlice =  // element type of T




Sorry last post was not complete. Not tested.


```
 alias T = Point[];
alias ElementOfPointSlice = ElementType!(T);

 unittest {
 assert(is(ElementOfPointSlice == Point));
  }
```


so, what's the problem? This passes tests:

```d
import std.range : ElementType;

struct Point { int x, y; }
alias T = Point[];
alias ElementOfPointSlice = ElementType!(T);

unittest {
assert(is(ElementOfPointSlice == Point));
}
```


Re: Quotes and backticks together in a raw string

2021-08-18 Thread jfondren via Digitalmars-d-learn

On Wednesday, 18 August 2021 at 22:18:59 UTC, Brian Tiffin wrote:

Google fu is failing on this one.


string docs are at https://dlang.org/spec/lex.html

Is there a way to have a raw multi-line string literal with 
both double-quotes and backticks inside?




https://dlang.org/spec/lex.html#delimited_strings give you most 
freedom. Token strings might also be appropriate.


```d
import std.string : stripRight;

enum quotes = q"EX
`backticks`
"doublequotes"
EX".stripRight; // otherwise ends in a newline
```


Re: How to get element type of a slice?

2021-08-17 Thread jfondren via Digitalmars-d-learn
On Tuesday, 17 August 2021 at 12:21:31 UTC, Ferhat Kurtulmuş 
wrote:

Hello folks,

Hope everyone is doing fine. Considering the following code, in 
the first condition, I am extracting the type Point from the 
slice Point[]. I searched in the std.traits, and could not find 
a neater solution something like ElementTypeOf!T. Is there any 
neater solution for it? Thanks in advance.


```d
static if (isArray!VecPoint){
VecPoint dummy;
alias Point = typeof(dummy[0]);
} else static if (isRandomAccessRange!VecPoint){
alias ASeq2 = TemplateArgsOf!VecPoint;
alias Point = ASeq2[0];
} else
static assert(0, typeof(VecPoint).stringof ~ " type is 
not supported");

```

Ferhat


This one's not in std.traits:

```d
import std.range : ElementType;

struct Point { int x, y; }

unittest {
Point[] points;
assert(is(ElementType!(typeof(points)) == Point));
}
```


Re: Concurrency message passing

2021-08-17 Thread jfondren via Digitalmars-d-learn

On Tuesday, 17 August 2021 at 11:05:09 UTC, JG wrote:

Hi

I have a program with two threads. One thread produces data 
that is put in a queue
and then consumed by the other thread. I initially built a 
custom queue to do this, but thought this should have some 
standard solution in D? I looked at std.concurrency and thought 
that message passing could be used. However, the problem is 
that I get the following error.


Error: static assert:  "Aliases to mutable thread-local data 
not allowed."


I am not sure how to solve this.


The error tells you what you can't do. You can do anything other 
than that. What you *should* do depends on what exactly you're 
trying to do. Here are some examples:


Sending shared mutable data:

```d
import std.concurrency, std.stdio, core.atomic;

void incr() {
auto counts = receiveOnly!(shared(int)[]);
foreach (ref n; counts)
atomicOp!"+="(n, 1); // shared(int) can't just be +='d
ownerTid.send(true);
}

void main() {
shared(int)[] counts = [0, 0, 0]; // no issues passing this
spawn().send(counts);
receiveOnly!bool;
writeln(counts);
}
```

Sending immutable data:

```d
import std.concurrency, std.stdio, std.typecons;

void greeter() {
auto who = receiveOnly!(string);
writeln("Hello, ", who);
}

void main() {
char[] who = "John".dup; // mutable, can't be 
sent
spawn().send(who.idup); // create immutable copy to 
send

}
```

Sending scalar data:

```d
import std.concurrency, std.stdio;

__gshared int[3] counts;

void incr() {
auto indexes = receiveOnly!(int, int);
foreach (ref n; counts[indexes[0] .. indexes[1]])
n++;
ownerTid.send(true);
}

void main() {
spawn().send(1, 2);
receiveOnly!bool;
writeln(counts);
}
```


Re: DMD compiler - warning of unused variables

2021-08-16 Thread jfondren via Digitalmars-d-learn

On Monday, 16 August 2021 at 14:14:27 UTC, DLearner wrote:

Hi

Please see code below:
```
void main() {

   import std.stdio;

   size_t i;
   size_t j;

   i = 5;

   writeln("i = ",i);

}

```

Is there a compiler option that would warn that variable 'j' is 
defined but not used?


Best regards


dmd is anti-warning, so it'd have to be an error, which might be 
more annoying than it's worth. `dscanner --report thefile.d` 
includes "Variable j is never modified and could have been 
declared const or immutable." and "Variable j is never used." as 
issues, with line and column numbers.


Re: how to import .lib library

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 10:19:33 UTC, Mike Parker wrote:

On Sunday, 15 August 2021 at 10:12:17 UTC, Timofeyka wrote:


Thank you for your reply!
I wanted to link to my project another project without source 
code.


Yeah, that's not possible. You either need the source or a set 
of D interface files that declares all the symbols you need.


Meaning, it is possible. On Windows where I assume these .lib 
files are:


```
PS C:\Users\jfond> cat math.d
extern(C) int twice(int n) { return n * 2; }

PS C:\Users\jfond> cat mathuser.d
extern (C) int twice(int n);

void main() {
import std.stdio : writeln;

writeln(twice(21));
}

PS C:\Users\jfond> ldc2 -lib math.d
PS C:\Users\jfond> ldc2 mathuser.d math.lib
PS C:\Users\jfond> ./mathuser
42
```

math.lib is written in D but it could've been written just as 
well in C or C++ or anything, as long as it's targeting the C ABI 
in whatever language.


When mathuser.d is compiled, D does not need the source for 
math.lib. That one extern(C) function without a body is 
sufficient to, again targeting the C ABI, say "I am expecting to 
be linked with a function like this", and math.lib supplies that 
function at link time.


D is identical to pretty much every other native-compiled 
language in this respect.


The question you probably want to be asking is, "given a specific 
library from this vendor, what's the most *convenient* way to 
link D against it", or "how should I tell dub to link this D 
application with a .lib file in a parent directory", etc.




Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:56:07 UTC, rempas wrote:

On Sunday, 15 August 2021 at 08:53:50 UTC, Tejas wrote:
External C libraries expect strings to be null terminated, so 
if you do use `.dup`, use `.toStringz` as well.


Yeah, yeah I got that. My question is, if I should avoid 
`cast(char*)` and use `.toStringz` while both do the exact same 
thing?


They don't do the same thing. toStringz always copies, always 
GC-allocates, and always NUL-terminates. `cast(char*)` only does 
what you want in the case that you're applying it a string 
literal. But in that case you shouldn't cast, you should just


```d
const char* s = "John";
```

If you need cast cast the const away to work with a C API, doing 
that separately, at the point of the call to the C function, 
makes it clearer what you're doing and what the risks are there 
(does the C function modify the string? If so this will segfault).


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:11:39 UTC, rempas wrote:

On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:

```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```



Well, that one didn't worked out really well for me. Using 
`.dup.ptr`, didn't added a null terminated character


dup() isn't aware of the NUL since that's outside the slice of 
the string. It only copies the chars in "John". You can use 
toStringz to ensure NUL termination:

https://dlang.org/phobos/std_string.html#.toStringz


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 07:47:27 UTC, jfondren wrote:

On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:

On Sunday, 15 August 2021 at 06:10:53 UTC, rempas wrote:
```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```

So am I going to have an extra runtime cost having to first 
construct a `string` and then ALSO cast it to a string 
literal?


In the above case, "John" is a string that's compiled into the 
resulting executable and loaded into read-only memory, and this 
code is reached that string is duplicated, at runtime, to 
create a copy in writable memory.


Probably a more useful way to think about this is to consider 
what happens in a loop:


```d
void static_lifetime() @nogc {
foreach (i; 0 .. 100) {
string s = "John";
// some code
}
}
```

^^ At runtime a slice is created on the stack 100 times, with a 
pointer to the 'J' of the literal, a length of 4, etc. The cost 
of this doesn't change with the length of the literal, and the 
bytes of the literal aren't copied, so this code would be just as 
fast if the string were megabytes in length.


```d
void dynamically_allocated() { // no @nogc
foreach (i; 0 .. 100) {
char[] s = "John".dup;
// some code
}
}
```

^^ Here, the literal is copied into freshly GC-allocated memory a 
hundred times, and a slice is made from that.


And for completeness:

```d
void stack_allocated() @nogc {
foreach (i; 0 .. 100) {
char[4] raw = "John";
char[] s = raw[0..$];
// some code
}
}
```

^^ Here, a static array is constructed on the stack a hundred 
times, and the literal is copied into the array, and then a slice 
is constructed on the stack with a pointer into the array on the 
stack, a length of 4, etc. This doesn't use the GC but the stack 
is limited in size and now you have worry about the slice getting 
copied elsewhere and outliving the data on the stack:


```d
char[] stack_allocated() @nogc {
char[] ret;
foreach (i; 0 .. 100) {
char[4] raw = "John";
char[] s = raw[0 .. $];
ret = s;
}
return ret; // errors with -preview=dip1000
}

void main() {
import std.stdio : writeln;

char[] s = stack_allocated();
writeln(s); // prints garbage
}
```


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:

On Sunday, 15 August 2021 at 06:10:53 UTC, rempas wrote:
```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```

So am I going to have an extra runtime cost having to first 
construct a `string` and then ALSO cast it to a string literal?


In the above case, "John" is a string that's compiled into the 
resulting executable and loaded into read-only memory, and this 
code is reached that string is duplicated, at runtime, to create 
a copy in writable memory.


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 06:10:53 UTC, rempas wrote:
So when I'm doing something like the following: `string name = 
"John";`

Then what's the actual type of the literal `"John"`?


```d
unittest {
pragma(msg, typeof("John"));  // string
pragma(msg, is(typeof("John") == immutable(char)[]));  // true
}
```

In the chapter [Calling C 
functions](https://dlang.org/spec/interfaceToC.html#calling_c_functions) in the "Interfacing with C" page, the following is said:
Strings are not 0 terminated in D. See "Data Type 
Compatibility" for more information about this. However, 
string literals in D are 0 terminated.


```d
void zerort(string s) {
assert(s.ptr[s.length] == '\0');
}

unittest {
zerort("John"); // assertion success
string s = "Jo";
s ~= "hn";
zerort(s); // assertion failure
}
```

If a function takes a string as a runtime parameter, it might not 
be NUL terminated. This might be more obvious with substrings:


```d
unittest {
string j = "John";
string s = j[0..2];
assert(s == "Jo");
assert(s.ptr == j.ptr);
assert(s.ptr[s.length] == 'h'); // it's h-terminated
}
```



Which is really interesting and makes me suppose that `"John"` 
is a string literal right?
However, when I'm writing something like the following: `char 
*name = "John";`,

then D will complain with the following message:
Error: cannot implicitly convert expression `"John"` of type 
`string` to `char*`


Which is interesting because this works in C.


Well, kinda:

```c
void mutate(char *s) {
s[0] = 'X';
}

int main() {
char *s = "John";
mutate(s); // segmentation fault
}
```

`char*` is just the wrong type, it suggests mutability where 
mutability ain't.


If I use `const char*` instead, it will work. I suppose that 
this has to do with the fact that `string` is an alias for 
`immutable(char[])` but still this has to mean that the actual 
type of a LITERAL string is of type `string` (aka 
`immutable(char[])`).


Another thing I can do is cast the literal to a `char*` but I'm 
wondering what's going on under the hood in this case.


The same thing as in C:

```d
void mutate(char *s) {
s[0] = 'X';
}

void main() {
char* s = cast(char*) "John";
mutate(s); // program killed by signal 11
}
```


Is casting executed at compile time or at runtime?


Compile-time. std.conv.to is what you'd use at runtime. Here 
though, what you want is `dup` to get a `char[]`, which you can 
then take the pointer of if you want:


```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```

So am I going to have an extra runtime cost having to first 
construct a `string` and then ALSO cast it to a string literal?


I hope all that makes sense and the someone can answer, lol





Re: How to extend the string class to return this inside the square bracket?

2021-08-13 Thread jfondren via Digitalmars-d-learn

On Friday, 13 August 2021 at 23:23:55 UTC, Marcone wrote:

On Friday, 13 August 2021 at 23:08:07 UTC, jfondren wrote:

On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:


Isn't there some unario operator template that I can use with 
lambda to handle a string literal?


So, something other than an exact "lit"[0..this.xx(..)] syntax 
is fine?


What didn't you like about `"Hello 
World!".findSplit("o")[0].writeln;` then?


What is a real example of something you want to do?


writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]);

indexOf()is just a simple example, not the goal. I want handle 
literal inside [] like it bellow, but in literal:


string x = "Hello World!";
writeln(x[x.indexOf("e")..x.indexOf("r")]);


```d
unittest {
import std.functional : pipe;
import std.string : indexOf;

assert("Hello, world!".pipe!(x => x[x.indexOf("e") .. 
x.indexOf("r")])

== "ello, wo");
}
```


Re: How to extend the string class to return this inside the square bracket?

2021-08-13 Thread jfondren via Digitalmars-d-learn

On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:


Isn't there some unario operator template that I can use with 
lambda to handle a string literal?


So, something other than an exact "lit"[0..this.xx(..)] syntax is 
fine?


What didn't you like about `"Hello 
World!".findSplit("o")[0].writeln;` then?


What is a real example of something you want to do?


  1   2   >