Re: Limits of implicit conversion of class arrays

2024-03-23 Thread FeepingCreature via Digitalmars-d-learn
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

On Saturday, 23 March 2024 at 09:08:45 UTC, Per Nordlöw wrote:

Is there a reason why

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

fails as

[1]: cannot implicitly convert expression `ds` of type 
`Derived[]` to `Base[]`

[2]: cast from `Derived[]` to `Base[]` not allowed in safe code

?


The first and second is unsound (infamously allowed in Java). 
Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of the 
ds slice.


—
Dmitry Olshansky
CEO @ Glow labs
https://olshansky.me


Note that it works if the classes are const:

```d
const(Base)[] bs;
const(Derived)[] ds;
bs ~= ds; // pass
bs = ds; // pass
bs = cast(const(Base)[])ds; // pass
```

Exactly because you can't replace existing entries.


Re: Setting field of struct object

2024-01-22 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:

On Monday, 22 January 2024 at 08:27:36 UTC, Joel wrote:


```d
import std;

struct Person {
string name, email;
ulong age;
auto withName(string name) { this.name=name; return this; }
auto withEmail(string email) { this.email=email; return 
this; }

auto withAge(ulong age) { this.age=age; return this; }
}

void main() {
Person p;

p.withName("Tom").withEmail("joel...@gmail.com").withAge(44);

writeln(p);
}
```


VS:`C++`

```d
struct Person {
string name, email;
ulong age;
}
Person a{"n","email",33};
```


D:

```d
import std.stdio;

struct Person {
string name, email;
ulong age;
}

void main() {
Person p = Person(name: "n", email: "email", age: 33);
writefln!"%s"(p);
}
```




Re: Delegates and values captured inside loops

2024-01-20 Thread FeepingCreature via Digitalmars-d-learn

On Saturday, 20 January 2024 at 15:59:59 UTC, Anonymouse wrote:
I remember reading this was an issue and now I ran into it 
myself.


```d
import std.stdio;

void main()
{
auto names = [ "foo", "bar", "baz" ];
void delegate()[] dgs;

foreach (name; names)
{
dgs ~= () => writeln(name);
}

foreach (dg; dgs)
{
dg();
}
}
```

Expected output: `foo`, `bar`, `baz`
Actual output:   `baz`, `baz`, `baz`

If I make `names` an `AliasSeq` it works, but I need it to be a 
runtime array.


Is there a workaround?


```
foreach (name; names)
{
dgs ~= ((name) => () => writeln(name))(name);
}
```
lol


Re: Nested delegates and closure allocations

2024-01-16 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 16 January 2024 at 15:39:07 UTC, Anonymouse wrote:
If I make a `scope` variable of the delegate and pass *it* to 
`receiveTimeout`, there no longer seems to be any mention of 
the closure in the error (given 2.092 or later).


```d
void foo(Thing thing) @nogc
{
void sendThing(const string where, int i)
{
send(thing, where, i);
}

scope scopeSendThing = 
receiveTimeout(Duration.zero, scopeSendThing);
}
```

Ignoring that it doesn't compile for other reasons; provided 
`scope scopeSendThing = ` compiles -- as in, 
`` is eligible for `scope` -- is this a valid 
workaround?


Correct. The problem is that `receiveTimeout` is defined as a 
template variadic function: it *can* take a scoped function, but 
it doesn't (can't) declare that its argument is always scoped, so 
since scoped parameters are opt-in, it defaults to unscoped. And 
 has to also default to unscoped, because you can pass 
unscoped values to scoped parameters but not the other way 
around, so it defaults to the most generic type available. With 
your scoped variable you provide DMD the critical hint that 
actually you want the closure to be scoped, and once the value is 
scoped it stays scoped.


Re: Nested delegates and closure allocations

2024-01-16 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 16 January 2024 at 10:56:58 UTC, Anonymouse wrote:

I'm increasingly using nested delegates to partition code.

```d
void foo(Thing thing)
{
void sendThing(const string where, int i)
{
send(thing, where, i);
}

sendThing("bar", 42);
}
```

...
3. Those referenced stack variables that make up the closure 
are allocated on the GC heap, unless:


* The closure is passed to a scope parameter.
* The closure is an initializer for a scope variable.
* The closure is assigned to a scope variable.


I'm generally not storing the delegates or passing them around 
as values, so I don't think the thing about scope variables and 
parameters *directly* applies.


Am I safe as long as I don't do something like, pass 
`` as an argument to `std.concurrency.receive`?


Yes.


Re: Trying to understand map being a template

2024-01-06 Thread FeepingCreature via Digitalmars-d-learn

On Saturday, 6 January 2024 at 17:57:06 UTC, Paul Backus wrote:

On Friday, 5 January 2024 at 20:41:53 UTC, Noé Falzon wrote:
In fact, how can the template be instantiated at all in the 
following example, where no functions can possibly be known at 
compile time:


```
auto do_random_map(int delegate(int)[] funcs, int[] values)
{
auto func = funcs.choice;
return values.map!func;
}
```

Thank you for the insights!


It works for the same reason this example works:

```d
void printVar(alias var)()
{
import std.stdio;
writeln(__traits(identifier, var), " = ", var);
}

void main()
{
int x = 123;
int y = 456;

printVar!x; // x = 123
printVar!y; // y = 456
x = 789;
printVar!x; // x = 789
}
```


To clarify, what this actually compiles to is:

```d

void main()
{
  int x = 123;
  int y = 456;
  void printVar_x()
  {
 import std.stdio;
 writeln(__traits(identifier, x), " = ", x);
  }
  void printVar_y()
  {
 import std.stdio;
 writeln(__traits(identifier, y), " = ", y);
  }
  printVar_x;
  printVar_y;
  x = 789;
  printVar_x;
}

```

Which lowers to:

```d
struct mainStackframe
{
  int x;
  int y;
}

void printVar_main_x(mainStackframe* context)
{
   import std.stdio;
   writeln(__traits(identifier, context.x), " = ", context.x);
}

void printVar_main_y(mainStackframe* context)
{
   import std.stdio;
   writeln(__traits(identifier, context.y), " = ", context.y);
}

void main()
{
  // this is the only "actual" variable in main()
  mainStackframe frame;
  frame.x = 123;
  frame.y = 456;
  printVar_main_x();
  printVar_main_y();
  frame.x = 789;
  printVar_main_x();
}


Same with `map`.


Re: Dirty DMD

2023-11-18 Thread FeepingCreature via Digitalmars-d-learn

On Saturday, 18 November 2023 at 18:52:07 UTC, JN wrote:
Latest DMD for Windows downloaded from here: 
https://downloads.dlang.org/releases/2.x/2.105.3/dmd-2.105.3.exe reports version as dirty:


DMD64 D Compiler v2.105.3-dirty
Copyright (C) 1999-2023 by The D Language Foundation, All 
Rights Reserved written by Walter Bright


what does it mean by dirty?


Oops. It means whoever built it had uncommitted changes in their 
version of the code. It's probably harmless though - somebody 
trying to smuggle in changes could just disable that annotation.


Re: Request you advise : isValidFilename

2023-09-22 Thread FeepingCreature via Digitalmars-d-learn
On Friday, 22 September 2023 at 17:52:51 UTC, FeepingCreature 
wrote:
"Integer representation" here refers to the ANSI index or 
Unicode codepoint, ie. the filename must not contain `\x00` to 
`\x31`.


Er oops, make that `\x00` to `\x1f`.


Re: Request you advise : isValidFilename

2023-09-22 Thread FeepingCreature via Digitalmars-d-learn

On Friday, 22 September 2023 at 17:44:50 UTC, Vino wrote:

Hi All,

  Request you help in understanding why the below code is 
always returning true when it should return false as per the 
documentation.


Documentation
```
filename must not contain any characters whose integer 
representation is in the range 0-31.

```


"Integer representation" here refers to the ANSI index or Unicode 
codepoint, ie. the filename must not contain `\x00` to `\x31`.


Re: dlang custom keyword for struct/class

2023-09-17 Thread FeepingCreature via Digitalmars-d-learn
On Sunday, 17 September 2023 at 15:55:37 UTC, Vitaliy Fadeev 
wrote:

Is it possible to write like this in D?

```d
struct Message
{
   ulong timestamp;
}

Message LongMessage
{
ubyte[255] s;
}
//
// it mean
//
// struct LongMessage
// {
// Message _super;
// alias _super this;
// ubyte[255] s;
// }
//
// or
//
// struct LongMessage
// {
// ulong timestamp;
// ubyte[255] s;
// }
```

Is it possible?


No, there's no struct inheritance. But you can just write the 
`alias this` version manually.


Re: isBinary

2023-09-03 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 3 September 2023 at 10:11:22 UTC, Vino wrote:

Hi All,

   Any update as to when the function described in the below 
ticked would be action-ed, I am more interested in isBinary 
(check a file whether is is binary file or not)


http://d.puremagic.com/issues/show_bug.cgi?id=9455

From,
Vino


Those are totally different ideas.

When writing a file, some operating systems support line ending 
conversion. To do that, you explicitly specify that you are 
writing to a text file. Then a "binary file" is just any file 
that is not a text file. However, this is merely a conversion 
process on writing. You cannot discover whether a file is a 
binary file in reverse. At most you can check whether *you 
yourself* opened the file as a binary file.


Re: pointer to std.algorithm.iteration : splitter

2023-08-31 Thread FeepingCreature via Digitalmars-d-learn

On Thursday, 31 August 2023 at 05:16:02 UTC, Vino wrote:

Hi All,

  Request your help on the below error

Program
```
void main()
{
import std.stdio:writeln;
import std.algorithm.iteration : splitter;

auto splitter_ptr = !((a, b) => a.splitter(b).array);
string str = "TEST1;TEST2;TEST3";
auto words = splitter_ptr(str, ';');
foreach (word; words) { writeln(word); }
}
```
```
Error: template instance `splitter!((a, b) => 
a.splitter(b).array)` does not match any template declaration

```

From,
Vino


Why are you trying to take pointers of lots of different things? 
You should pretty much never need pointers in normal D code.


Re: File size

2023-08-23 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 22 August 2023 at 16:22:52 UTC, harakim wrote:
On Monday, 21 August 2023 at 11:05:36 UTC, FeepingCreature 
wrote:
Can you print some of the wrong sizes? D's DirEntry iteration 
code just calls `FindFirstFileW`/`FindNextFileW`, so this 
*shouldn't* be a D-specific issue, and it should be possible 
to reproduce this in C.


Thanks for the suggestion. I was working on getting the list 
for you when I decided to first try and reproduce this on 
Linux. I was not able to do so. Then I opened the Linux File 
Explorer and went to one of the files. There were two files by 
that name, with names differing only by case.


In windows, I only saw one, because Windows Explorer only 
supports one file with an identical case-insensitive name per 
directory. Unsurprisingly, that is also the one that was 
selected by getSize(filename). The underlying windows functions 
must ignore case as well and select the same way as Explorer 
(which makes sense). That explains why Windows Explorer 
reported the same size as getsize(name) in every case, while 
DirEntry.size would match for the file with the same case as 
windows recognized and not for the file with a different case. 
I was able to get into this state because I copied the files 
(merged directories) in Linux.


It was interesting to look into. It seems everything is working 
as designed. It shouldn't be an issue for me going forward 
either as I move more and more towards Linux.


That's hilarious! I'm happy you found it.


Re: File size

2023-08-21 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 21 August 2023 at 07:52:28 UTC, harakim wrote:
I have been doing some backups and I wrote a utility that 
determines if files are an exact match. As a shortcut, I check 
the file size. So far so good on this with millions of files 
until I found something odd: getSize() and DirEntry's .size are 
producing different values.


...

It seems really odd that getSize(sourceFile.name) is returning 
a different number than sourceFile.size. This is an external 
HDD on windows formatted in ntfs that it is reading. I believe 
I originally wrote the files to the file system in Windows, but 
then today I cut and paste them (in the same drive) in Linux. 
However, this is the first time this has happened after 
millions of comparisons and it only happened for about 6 files. 
It does happen consistently though.


I have verified that the file size is that reported by getSize 
and not sourceFile.size and that the files open correctly.


...


Can you print some of the wrong sizes? D's DirEntry iteration 
code just calls `FindFirstFileW`/`FindNextFileW`, so this 
*shouldn't* be a D-specific issue, and it should be possible to 
reproduce this in C.


Re: Finding duplicate elements

2023-08-16 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 15 August 2023 at 17:59:27 UTC, vino wrote:

Hi All,

 Request your help in finding duplicate element without sorting 
as per the below example


```
Example:
string[] args = [" test3", "test2 ", " test1 ", " test1 ", " "];

Output Required:
If duplicate element found then print "Duplicate element found: 
"

else print ["test3", "test2", "test1"];
```
From,
Vino.B


```
import std;
void main() {
string[] args = [" test3", "test2 ", " test1 ", " test1 ", " 
"];

findDuplicates(args);
}
void findDuplicates(string[] args) {
bool[string] dupes;
foreach (arg; args) {
if (arg in dupes) {
writefln!"Duplicate element found: %s"(arg);
return;
}
dupes[arg] = true;
}
writefln!"%s"(dupes.keys);
}
```



Re: toLower

2023-08-15 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 15 August 2023 at 20:09:28 UTC, Joel wrote:
On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature 
wrote:
But does *not* import `std.ascii`! So there's no ambiguity 
inside the `sort` string expression between the two `toLower` 
functions..


How do I get it to work?

I tried std.ascii.toLower. And using alias 
toLower=std.ascii.toLower;


To elaborate more, `toLower` doesn't work because function-scope 
aliases are not considered for UFCS.


```
alias toLower = std.ascii.toLower;

...
// So this does actually work:
.map!toLower
// but this does not, because it looks for a UFCS-capable 
symbol

.map!(c => c.toLower)
// but this does again
.map!(c => toLower(c))

```



Re: toLower

2023-08-15 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote:

How come toLower works in the sort quotes, but not in the map?

```d
void main() {
import std;
"EzraTezla"
.to!(char[])
.byCodeUnit
.sort!"a.toLower c.toLower)
.writeln;
}
```

When you pass a string to a lambda, it's evaluated in 
`std.functional.unaryFun`/`binaryFun`.


At that point, these modules are imported for use in string 
expressions:


```
import std.algorithm, std.conv, std.exception, std.math, 
std.range, std.string;

import std.meta, std.traits, std.typecons;
```

And `std.string` itself publically imports:

```
public import std.uni : icmp, toLower, toLowerInPlace, toUpper, 
toUpperInPlace;

```

But does *not* import `std.ascii`! So there's no ambiguity inside 
the `sort` string expression between the two `toLower` functions..


Re: On assigning const to immutable

2023-07-13 Thread FeepingCreature via Digitalmars-d-learn

On Thursday, 13 July 2023 at 11:55:17 UTC, Ki Rill wrote:
Why does the first example `class A` work, but the second one 
with `class B` does not?

```D
class A {
immutable int a;
this(in int a) {
this.a = a;
}
}

class B {
immutable int[] b;
this(in int[] b) {
this.b = b;
}
}

void main()
{
auto a = new A(1);
auto b = new B([1, 2]);
}
```

It implicitly converts `const` to `immutable`, but fails to do 
the same with an array. Is it intentional? Why?


Yep: `immutable` is data that *cannot ever* change. If you could 
convert `int[]` to `immutable int[]`, you could do this:


```
int[] a = [2];
immutable(int)[] b = a;

auto first = b[0];
a[0] = 3;
auto second = b[0];

// Wait, this fails? I thought `b` was immutable.
assert(first == second);
```

Use `array.idup` (immutable dup) to turn `int[]` into `immutable 
int[]`.


And you can convert `int` to `immutable int` because it's a 
"value copy": you cannot mutate the immutable variable through an 
assignment to the original. Generally speaking, only the 
constness of referenced data matters for assignment.


That's why you can assign `string` to `immutable string`, because 
`string` is `immutable(char)[]`: the referenced data is immutable 
in both cases.


Re: Dynamic array of strings and appending a zero length array

2023-07-08 Thread FeepingCreature via Digitalmars-d-learn

On Saturday, 8 July 2023 at 17:15:26 UTC, Cecil Ward wrote:
I have a dynamic array of dstrings and I’m spending dstrings to 
it. At one point I need to append a zero-length string just to 
increase the length of the array by one but I can’t have a slot 
containing garbage. I thought about ++arr.length - would that 
work, while giving me valid contents to the final slot ?


What I first did was
   arr ~= [];

This gave no errors but it doesn’t increase the array length, 
so it seems. Is that a bug ? Or is it supposed to do that?




You can append an element to an array. You can also append an 
array to an array. Because [] can be an array of any type, the 
compiler guesses that it's an empty `string[]` array and appends 
it to no effect.


Re: Inheritance and arrays

2023-07-03 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:

Hi!

I am a D user coming from java, rather than from C/C++ 
(although obviously also have some exposure to them), and thus 
apparently one of the few people here who likes OO (within 
reason, of course).


So while I appreciate the fact that D closely follows java's 
design, I wonder why there is no implicit inheritance for 
arrays (also the same applies to AAs):


```d
interface I {}
class C : I {}

void main() {
I i;
C c = null;
i = c; // Works

I[] ii;
C[] cc = null;
// ii = cc; // Doesn't work: Error: cannot implicitly 
convert expression `cc` of type `C[]` to `I[]`

ii = cast (I[]) cc; // Works, but why do I need to cast?
}
```


The `cast` version "works", but will crash at runtime.

In D, as opposed to Java, a reference to an object has a 
*different pointer value* than a reference to the interface-typed 
version of that object. This is necessary for efficient compiled 
virtual method calls on the interface. But for the same reason, 
you cannot reinterpret an array of objects to an array of 
interfaces; even if you can implicitly convert each object to 
that interface, there's a difference between automatically 
rewriting a value and automatically rewriting every element of an 
array: one is O(1), the other is O(n) and incurs a GC allocation.


Re: Inheritance and arrays

2023-07-03 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:

Hi!

I am a D user coming from java, rather than from C/C++ 
(although obviously also have some exposure to them), and thus 
apparently one of the few people here who likes OO (within 
reason, of course).


So while I appreciate the fact that D closely follows java's 
design, I wonder why there is no implicit inheritance for 
arrays (also the same applies to AAs):


...

Is this a conscious design decision (if so, why?), or just a 
leak of some implementation detail, but that could eventually 
be made to work?


See also this thread on implementation details: 
https://forum.dlang.org/post/bibtjiiwpiqzzfwgx...@forum.dlang.org


Re: Bug in usage of associative array: dynamic array with string as a key

2023-06-30 Thread FeepingCreature via Digitalmars-d-learn

On Friday, 30 June 2023 at 19:05:23 UTC, Cecil Ward wrote:

I have code roughly like the following:

   dstring str = "name"d;
   uint ordinal =  (( str in Decls.ordinals ) !is null)  ?  
Decls.ordinals[ str ]  :  -1;


struct Decls
   {
   uint[ dstring]   ordinals;
   }

//and
   Decls.ordinals[ str ] = ordinal_counter++;

The problem is that it always returns ordinal== -1 from the 
expression. Can you sort me out?


Impossible to tell without a complete repro, I'm afraid. The 
expression, at least, looks correct at first glance.


Note that you can do `uint ordinal = Decls.ordinals.get(str, 
-1);`.


Re: static if - unexpected results

2023-06-23 Thread FeepingCreature via Digitalmars-d-learn
On Friday, 23 June 2023 at 18:43:06 UTC, Steven Schveighoffer 
wrote:
It should be a spec change. Change POD to say "type" instead of 
"struct".


The goal of `isPOD` is to determine how careful generic code 
needs to be to pass the type around, or copy it. Changing it to 
false implies that it is not "plain old data". I.e. it has a 
destructor, it has hidden members, or it cannot be copied via 
bit copying (all of these do not fit the type in question).


The only other option is to error on calling `__traits(isPOD, 
char)`, but I think that's even worse.


-Steve


Yeah, I think that's also where I'm standing. The current 
behavior seems correct and useful, it's just not documented 
correctly.


Re: static if - unexpected results

2023-06-23 Thread FeepingCreature via Digitalmars-d-learn

On Friday, 23 June 2023 at 14:22:24 UTC, DLearner wrote:

Hi

Was looking for compile-time detection of a struct variable.
However, the following test code gave the two 'FAILS' shown 
below.

Comments?
```
void main() {
   import std.stdio : writeln;
   import std.traits;

   string mxnTst(string VarName) {
  return

  `static if (is(typeof(` ~ VarName ~ `) == char)) {` ~
 `writeln("` ~ VarName ~ ` ", " is a char");` ~
  `} else static if (__traits(isPOD, typeof(` ~ VarName ~ 
`))) {` ~

 `writeln("` ~ VarName ~ ` ", " is a struct");` ~
  `} else static if (is(typeof(` ~ VarName ~ `) == int)) {` 
~

 `writeln("` ~ VarName ~ ` ", " is an int");` ~
  `} else {` ~
 `static assert(false, "mxnTst Variable '` ~ VarName  ~ 
`' is of unknown type");` ~

  `}`
   ;
   }

   char char1;
   int  int1;
   byte byte1;

   struct foo {
  int  fooint;
  char foochar;
   }
   foo foovar1;

   mixin(mxnTst("char1"));   // Expected: char1 is a char. 
Actual: char1 is a char. (ok)
   mixin(mxnTst("int1"));// Expected: int1 is an int.  
Actual: int1 is a struct. (FAIL)
   mixin(mxnTst("foovar1")); // Expected: foovar1 is a struct.  
Actual: foovar1 is a struct. (ok)
   mixin(mxnTst("byte1"));   // Expected: Run to fail with the 
static assert message. Actual: byte1 is a struct. (FAIL)

}
```


```
static assert(__traits(isPOD, int)); // ok.
static assert(__traits(isPOD, byte)); // ok.
```
It's a bug in either the spec or the compiler.


Re: Strange behaviour of __traits(allMembers)

2023-06-18 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 18 June 2023 at 10:21:16 UTC, IchorDev wrote:

On Sunday, 18 June 2023 at 10:04:14 UTC, FeepingCreature wrote:

On Sunday, 18 June 2023 at 09:48:40 UTC, IchorDev wrote:

Does anyone understand why this happens?
Is there any way to subvert this behaviour, or is it actually 
a bug?


Yes, see also my bug report, 
https://issues.dlang.org/show_bug.cgi?id=20008 
"__traits(allMembers) of packages is complete nonsense".


Whaat why has this not been fixed in the 
last 4 years!


I think because nobody *needs* `__traits(allMembers)` of 
packages. Mostly people just learn to skip them while scanning 
modules, and instead of iterating imports, they do the standard 
hack of "generate a list of all files in the project, string 
import it, and generate import statements for each".


Yeah it's ugly. I guess the lesson is, nothing takes as long to 
fix as a bug with a well-known workaround.


Re: Strange behaviour of __traits(allMembers)

2023-06-18 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 18 June 2023 at 09:48:40 UTC, IchorDev wrote:

Does anyone understand why this happens?
Is there any way to subvert this behaviour, or is it actually a 
bug?


Yes, see also my bug report, 
https://issues.dlang.org/show_bug.cgi?id=20008 
"__traits(allMembers) of packages is complete nonsense".


Re: undefined reference to "main"

2023-04-05 Thread FeepingCreature via Digitalmars-d-learn
On Wednesday, 5 April 2023 at 09:19:17 UTC, Alexander Zhirov 
wrote:
How to compile the example given in the book correctly? When 
compiling, an error occurs that the main function is missing. 
If I replace `shared static this()` with `void main()', then 
everything starts. What does the compilation string in `dub` 
and `dmd` look like correctly?


```d
import vibe.d;

shared static this()
{
  auto settings = new HTTPServerSettings;
  settings.port = 8080;
  settings.bindAddresses = ["::1", "127.0.0.1"];
  listenHTTP(settings, );

  logInfo("Please open http://127.0.0.1:8080/ in your 
browser.");

}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{
  res.writeBody("Hello, World!");
}
```


This seems to work for me:

```d
/+ dub.json: {
"name": "test",
"dependencies": {
"vibe-d": "*"
}
} +/
import vibe.d;

shared static this()
{
  auto settings = new HTTPServerSettings;
  settings.port = 8080;
  settings.bindAddresses = ["::1", "127.0.0.1"];
  listenHTTP(settings, );

  logInfo("Please open http://127.0.0.1:8080/ in your browser.");
}

void main() {
runApplication;
}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{
  res.writeBody("Hello, World!");
}
```

Run with

```
dub run --single test.d
```


Re: Can nice D code get a bit slow?

2023-03-08 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 8 March 2023 at 10:49:32 UTC, Markus wrote:
So, having no clue about D (just bought some books), I wanted 
to ask if nice looking code can become slow, in general. In the 
mentioned case it's just that I like the packaging of functions 
into some sort of scope (OOP) versus the flat C and Go stuff. I 
like OOP for this reason, but now I'm unsure whether I might 
stay out of creating classes at all.


Uh, hope you understand my vague question, sorry about that. I 
found D to be the right place because it's not missing any 
essential feature I know of.


Kind regards


If you write D like Java, it will be slow like Java - actually 
slower, because D's GC isn't as good.


If you remember to use structs for value types (no `class 
Vector3f`, `class Point` etc.), you should be fine.


Though as a general rule, don't worry about it too much. Even 
slow D is still fast.


Re: How would the equivalent C type be in D?

2023-03-07 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 1 March 2023 at 09:37:48 UTC, rempas wrote:
Thank you! You are amazing for explaining it! I was so focused 
on thinking that I'm doing something wrong with the type that I 
didn't noticed that the pointers, points to nowhere so the 
function obviously has nowhere to write to. Like... OMG! And I 
want to make a fully fledged compiler when making stupid 
mistakes like that. Btw, When I executed the program, I got 
"Error Program exited with code -11". You said that the code 
was "11". What about that dash? If it is not a "minus" and it's 
just the dash symbol, then what's the idea?


Yay!

(Definitely make a compiler, it's a great way to learn.)

Yes, that is a bit weird. First of all, the actual signal is 11

```
$ grep SIGSEGV /usr/include/bits -R
/usr/include/bits/signum-generic.h:#define  SIGSEGV 
11  /* Invalid access to storage.  */

```

As per the POSIX spec 
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_21_18. signal exits must be reported with exit codes above 128. Customarily, shells will simply add 128 to the signal:


```
$ cat test.c; gcc test.c -otestc; ./testc; echo $?
int main() { int* ip = 0; *ip = *ip; return 0; }
Segmentation fault
139
```

139 being 128 + 11, but POSIX does not specify *how* the signal 
code is converted to an exit code. For instance, Python reports a 
signal 11 exit as -11. Strictly speaking, -11 is "above 128" in 
two's complement, corresponding to unsigned 245. But I don't know 
why Python does this. Presumably your shell does it the same way?


Re: How would the equivalent C type be in D?

2023-03-07 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 1 March 2023 at 09:37:48 UTC, rempas wrote:
Thank you! You are amazing for explaining it! I was so focused 
on thinking that I'm doing something wrong with the type that I 
didn't noticed that the pointers, points to nowhere so the 
function obviously has nowhere to write to. Like... OMG! And I 
want to make a fully fledged compiler when making stupid 
mistakes like that. Btw, When I executed the program, I got 
"Error Program exited with code -11". You said that the code 
was "11". What about that dash? If it is not a "minus" and it's 
just the dash symbol, then what's the idea?


Yay!

Yes, that is a bit weird. First of all, the actual signal is 11

```
$ grep SIGSEGV /usr/include/bits -R
/usr/include/bits/signum-generic.h:#define  SIGSEGV 
11  /* Invalid access to storage.  */

```

As per the POSIX spec 
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_21_18. signal exits must be reported with exit codes above 128. Customarily, shells will simply add 128 to the signal:


```
$ cat test.c; gcc test.c -otestc; ./testc; echo $?
int main() { int* ip = 0; *ip = *ip; return 0; }
Segmentation fault
139
```

139 being 128 + 11, but POSIX does not specify *how* the signal 
code is converted to an exit code. For instance, Python reports a 
signal 11 exit as -11. Strictly speaking, -11 is "above 128" in 
two's complement, corresponding to unsigned 245. But I don't know 
why Python does this. Presumably your shell does it the same way?


Re: How would the equivalent C type be in D?

2023-03-01 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 1 March 2023 at 08:26:07 UTC, FeepingCreature wrote:

```d
uint32_t[1] value;
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value.ptr);
```


To expand on this:

```d
uint32_t[2] value;
uint32_t* value_ptr = value.ptr;
// We are allowed to access the pointer at index 0
// because we declared the value it points to, to be size 2.
value_ptr[0] = 0;
// This is also allowed, because `value_ptr` is
// a pointer to two sequential `uint32_t` in memory.
value_ptr[1] = 0;
// But this access would segfault, because it's trying to write
// to the third element of a two-element array:
value_ptr[2] = 0;
```

Note: I just lied; `value_ptr[2]` would not segfault, for 
somewhat technical reasons; but it *would* corrupt your program's 
memory. At any rate, it's an invalid operation.




Re: How would the equivalent C type be in D?

2023-03-01 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 1 March 2023 at 08:12:05 UTC, rempas wrote:
I'm looking into 
[this](https://www.x.org/releases/X11R7.7/doc/libxcb/tutorial/index.html) tutorial to learn XCB and I'm trying to write the code in D with betterC. In the section 9.1 (sorry, I cannot give a section link, the article does not give us this ability), I'm facing a problem and my program exits with the exit code: "-11". I suspect that this happens because I haven't translated the following code the right way:


```d
uint32_t value[1];
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value);
```

I originally tried to translate this as:

```d
uint[1] value;
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value);
```

But then, when I tried to compile the program, I got the 
following error:


```
Error: function `headers.xcb_create_gc(xcb_connection_t* c, 
uint cid, uint drawable, uint value_mask, const(void)* 
value_list)` is not callable using argument types 
`(xcb_connection_t*, uint, uint, uint, uint[1])`
src/draw.d(18,16):cannot pass argument `value` of type 
`uint[1]` to parameter `const(void)* value_list`

```

So I thought of doing the following:

```d
uint* value;
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value);
```

Now the program complies but I get the "-11" exit code. Another 
thing I thought (which is probably the same thing under the 
hood but done a different way):


```d
const(void)* value;
(cast(ubyte*)value)[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value);
```

Same results. Any ideas?


11 is SIGSEGV. A segfault, or access violation, happens when you 
try to access unallocated memory. In this case, let me annotate 
your code so it's easier to see what's happening:


```d
// null is the default value for a pointer
uint* value = null;
// because `value` is null, the first index also lies at null.
assert([0] is null);
// So we try to store screen.black_pixel at memory address null, 
which is unallocated.

value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value);
```

As there is no memory segment allocated at address null, the CPU 
indicates a segmentation fault, which terminates the program.


So yes, `xcb_create_gc` wants a `uint*` parameter, but not just 
any `uint*` will do: it has to point to valid memory. Going back 
to the first snippet, what's happening here is that in C, arrays 
implicitly convert to pointers, because C doesn't have a notion 
of array types as distinct from pointer types. So you can have a 
variable declared as `uint[1]`, but pass it to a parameter that 
expects `uint*`, and the value that is passed will just be the 
address of the first field of the array. However, even in C, if 
you try to define `value` as `uint*`, it will segfault in the 
same way. Instead, in D, you need to tell the compiler to define 
an array of size 1, and then pass a pointer to the array's first 
member explicitly:


```d
uint32_t[1] value;
value[0] = screen.black_pixel;
// this is what C does under the hood
xcb_create_gc(connection, black, win, mask, [0]);
```

Or shorter, but with the same effect:

```d
uint32_t[1] value;
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value.ptr);
```



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

2023-02-20 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 20 February 2023 at 07:11:49 UTC, Mike Parker wrote:
On Monday, 20 February 2023 at 06:26:34 UTC, FeepingCreature 
wrote:




There have now been three pages produced by three people all 
agreeing with each other.


At what point does it start being spam?


Yes, it's all just noise now. Let's end it here. Further posts 
in this thread will be deleted.


oy vey, shut it down

fucking idiot




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

2023-02-19 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 20 February 2023 at 05:21:44 UTC, forky wrote:

On Friday, 10 February 2023 at 07:04:31 UTC, Max Samukha wrote:


...
Having class-private doesn't preclude module-private. Dennis 
even submitted a PR implementing class-private, but it stalled 
because people couldn't agree on whether class-private should 
be "private to class" or "private to class instance".


It likely the 'disagreement' was intentional .. i.e. to stall 
;-)


But in any case, it should be class private.


There have now been three pages produced by three people all 
agreeing with each other.


At what point does it start being spam?


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

2023-02-16 Thread FeepingCreature via Digitalmars-d-learn

On Thursday, 16 February 2023 at 02:27:23 UTC, Mike Parker wrote:
On Thursday, 16 February 2023 at 02:26:44 UTC, Mike Parker 
wrote:



Wrong. I'm arguing  things:


Geez. "I'm arguing 2 things:"


Springboarding off this post:

This thread is vastly dominated by some people who care very much 
about this issue. Comparatively, for instance, I care very little 
because I think D already does it right.


But then the thread will look unbalanced. This is a fundamental 
design flaw in forum software.


So let me just say: I think D does it right. D does not have 
class encapsulation; it has module encapsulation. This is by 
design, and the design is good.


Re: Is defining get/set methods for every field overkill?

2022-11-23 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 22 November 2022 at 21:45:29 UTC, []() {}() wrote:

On Tuesday, 22 November 2022 at 21:00:58 UTC, []() {}() wrote:




"Being able to declare a “friend” that is somewhere in some 
other file runs against notions of encapsulation." (This is the 
motivation for that article it seems).


I completely disagree with the assertion.

C++ Friend notion does not, not by any means, run against the 
notion of encapsulation.


Sure, it expands the perimeter (i.e. it puts a door in the 
wall).


But, and this is my point, there is a guard standing at the 
door. And that guard knows who has been authorised to pass 
through it. The encapsulation remains. Only its perimeter has 
been expanded.


One could argue that D's approach is just that. It expands the 
perimeter to the module level. But there's no guard at the door 
in D.


Surely, this 'let anyone pass through' design, decreases 
encapsulation? How could it possibly increase encapsulation, as 
claimed, by the author of that article?


If there were a means in the language for controlled sharing 
within a module, *that* would increase encapsulation.


The module is the capsule. D is simply not interested in building 
a capsule around a class. D does not let "anyone" pass through, 
it lets "anyone in the module" pass through, because the module 
is the wall. I think this is a stronger concept of encapsulation 
than C++ friends because the encapsulation is lexical rather than 
just declarative.


Re: Is defining get/set methods for every field overkill?

2022-11-21 Thread FeepingCreature via Digitalmars-d-learn
On Thursday, 17 November 2022 at 04:39:35 UTC, thebluepandabear 
wrote:
I am creating a TUI library and I have a class with the 
following constant fields:


```
class Label : Renderable {
const string text;
const TextAlignment textAlignment;
const Color color;

this(Dimensions dimensions, string text, TextAlignment 
textAlignment, Color color) {

this.dimensions = dimensions;
this(text, textAlignment, color);
}

this(string text, TextAlignment textAlignment, Color color) 
{

this.text = text;
this.textAlignment = textAlignment;
this.color = color;
}

override Cell[] render() const {
Cell[] cells;

for (int x = 0; x < 0 + text.length; ++x) {
cells ~= Cell(Coordinates(x, 0), text[x], color);
}

return cells;
}
}
```

I am debating whether or not I should add getter methods to 
these properties. On one hand, it will inflate the codebase by 
a lot, on the other hand -- in other languages like Java it is 
a good practice:


```
class Label : Renderable {
private const string text;
private const TextAlignment textAlignment;
private const Color color;

this(Dimensions dimensions, string text, TextAlignment 
textAlignment, Color color) {

this.dimensions = dimensions;
this(text, textAlignment, color);
}

this(string text, TextAlignment textAlignment, Color color) 
{

this.text = text;
this.textAlignment = textAlignment;
this.color = color;
}

string getText() const {
return text;
}

TextAlignment getTextAlignment() const {
return textAlignment;
}

Color getColor() const {
return color;
}

override Cell[] render() const {
Cell[] cells;

for (int x = 0; x < 0 + text.length; ++x) {
cells ~= Cell(Coordinates(x, 0), text[x], color);
}

return cells;
}
}
```

It's not a lot of code that has been added but if you have a 
class with say 10 different fields, adding getter methods would 
definitely increase the code size by a lot, so what are you 
guys thoughts on this?


Obligatory note that boilerplate 
https://code.dlang.org/packages/boilerplate exists for just this 
reason:


class Label : Renderable {
@ConstRead
private const string text_;

@ConstRead
private const TextAlignment textAlignment_;

@ConstRead
private const Color color_;

this(Dimensions dimensions, string text, TextAlignment 
textAlignment, Color color) {

this.dimensions_ = dimensions;
this(text, textAlignment, color);
}

override Cell[] render() const {
Cell[] cells;

for (int x = 0; x < 0 + text.length; ++x) {
cells ~= Cell(Coordinates(x, 0), text[x], color);
}

return cells;
}

mixin(GenerateFieldAccessors);
mixin(GenerateThis);
}



Re: "chain" vs "~"

2022-08-06 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 7 August 2022 at 01:22:18 UTC, pascal111 wrote:

Why we use "chain" while we have "~":

'''D
int[] x=[1,2,3];
int[] y=[4,5,6];

auto z=chain(x,y);
auto j=x~y;
'''


Chain doesn't allocate any memory. This can be useful 
occasionally.


Re: Obsecure problem 1

2022-07-31 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 31 July 2022 at 07:43:06 UTC, Salih Dincer wrote:
Why are you using const for strings? After all, they are 
protected by immutable. Moreover, since you do not use refs, 
copies are taken in every function and also you have created 
extra copy for results.




Note sure if I'm misunderstanding, but: D does not copy strings 
on value passing, because they're inherently reference types.


You can think of a string (or any array) as a `struct { size_t 
length; T* ptr; }` combined with a bunch of syntax magic.


Re: alias this - am I using it wrong?

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

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

Hi all,

I have a little problem understanding alias this. I always 
thought, that alias this only makes implicit conversions from 
the aliased object to this. Then, why do lines 18 and 22 
compile in the code below? And, btw, line 22 crashes with a 
segmentation fault.


```d
01 struct Test_Struct {long t;}
02
03 class Alias_Class
04 {
05 Test_Struct ts;
06 alias ts this;
07 }
08
09 class Test_Class
10 {
11 Alias_Class ac;
12 }
13
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 }
```

Johann


ts is a field. You can assign to a field. So when the field is 
aliased to this, you can assign to the field through a class 
reference.


You can disable this behavior by creating a getter in 
Alias_Class, then aliasing it to this:


```
class Alias_Class
{
Test_Struct ts;
Test_Struct getter() { return ts; }
alias getter this;
}
```



Re: using "invariant" with structs ... possible to call when a field value is set??

2021-08-08 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 8 August 2021 at 11:30:41 UTC, james.p.leblanc wrote:

Hello,

With structs, I understand that "invariant checking" is called 
(from dlang tour):


It's called after the constructor has run and before the 
destructor is called.

It's called before entering a member function
invariant() is called after exiting a member function.

But, is is possible to have the invariant checking be performed
whenever a field is directly set?

For example, suppose a struct "S", has a field "x".  I would 
like to

have invariance check in cases such as:

S.x = 4;

Maybe there is a hidden set field function that gets called that
might be exploitable??

Thoughts on this?  Possible?  Better paths that I should 
consider?


Best Regards,
James


You can make a field set function like so:

```
struct S
{
  private int x_;
  int x(int value) { return this.x_ = value; }
  int x() { return this.x_; }
}
```

This will then run invariants.

(boilerplate can automate that for you. 
https://code.dlang.org/packages/boilerplate cough 
self-advertisement cough)


Re: General rule when not to write ;

2021-05-18 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 18 May 2021 at 16:27:13 UTC, Alain De Vos wrote:

After each } i write a ;
And let the compiler tell me it is an empty instruction.
What are the general rules where ; is not needed after a }


Is `;` ever needed after a `}`?

I guess in `void delegate() dg = { writeln!"Hello World"; };`, 
but that hardly counts, because it belongs to the variable 
declaration, not the `{}`.


Re: What are virtual functions?

2021-04-19 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 18 April 2021 at 23:04:26 UTC, ShadoLight wrote:
On Wednesday, 14 April 2021 at 14:06:18 UTC, FeepingCreature 
wrote:

On Wednesday, 14 April 2021 at 13:43:20 UTC, Berni44 wrote:

[..]

Covariance is related ...

[..]


The opposite (contravariance) happens ...

[..]




Nice answer but, just to be clear - D only supports covariance 
on return types at the moment, and doesn't support 
contravariance on parameters, right?


I remember contravariance being periodically requested in the 
past but, AFAICR, it has not been implemented, right? A quick 
search through the forums didn't turn anything up either... and 
this does not compile:


```
class A {}
class B : A {}

class Y {
public void bar (B b) {}
}
class X : Y {
public override void bar (A a){}
}
```


... That doesn't work?! Holy hell. I mean, run.dlang.io confirms, 
but ... *why not*?! If you already support return type 
covariance, parameter contravariance should be easy. It's the 
same thing! You don't need to do anything! Any B is directly a 
valid A! Like, sure, there's versions of this that don't 
trivially work, like mixing interface and class parents, but 
direct superclass contravariance should be easy. ... Weird. I 
don't get it.


Reading https://issues.dlang.org/show_bug.cgi?id=3075 seems like 
it collides with overloading. Except ... it doesn't. Because you 
can't implement multiple overloaded methods with contravariance 
in a subclass, because it doesn't work for interfaces anyway 
(cause they occupy a different interface slot in the class and so 
aren't strictly Liskov.) So the selection of the function to 
override is still unambiguous.


I don't get it.


Re: What are virtual functions?

2021-04-14 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 14 April 2021 at 13:43:20 UTC, Berni44 wrote:
I'm trying to understand, what virtual functions are. I found 
the 
[specs](https://dlang.org/spec/function.html#virtual-functions), but I can't make head or tail of it.


- What is a `vtbl[]`? Obviously a function pointer table. But 
where to find this? The examples don't use it. Maybe something 
inside of the compiler?
- Which of the eight functions in the example are virtual and 
and which not? OK B.abc is said to be virtual, as the comment 
states. But it seems never to be used. And why is it considered 
to be virtual?
- There is also the term "covariant function", which is not 
explained. What is this?




Recommended reading: 
https://en.wikipedia.org/wiki/Liskov_substitution_principle


This is all related to object-oriented programming and class 
inheritance. Because we can put a subclass object into a 
superclass variable (`class Child : Parent { }; Parent parent = 
new Child;`), we cannot look at the *type* of an object variable 
to decide which methods to call, because the object itself may be 
of a subtype. As such, when we call a method `foo` on `Parent`, 
the compiler looks up the class info in a pointer in the first 8 
bytes of the object, finds the method pointer for `foo`, and 
calls it with the object as a hidden parameter. (This is the 
`this` field.)


So a virtual method is a method that is called "virtually", as 
compared to directly by name, by turning the method name into a 
function pointer call via the classinfo.


The list of function pointers for methods in the class info is 
called the virtual method table, or vtable.


Covariance is related to the Liskov principle, and just means 
that because `Child` can be treated as a `Parent`, a method that 
returns `Parent` in the superclass can be overridden (its vtable 
pointer replaced with a new one) by one that returns a `Child` in 
the subclass. In other words, as "Child class replaces Parent 
class", the "return type `Child`" can replace the "return type 
`Parent`"; ie. in the child class you can use a child class of 
the return type, ie. they "vary together" - covariance.


The opposite (contravariance) happens for parameters: if a 
superclass method takes `Child`, the subclass can take `Parent` 
instead - again, because `Child` can turn into `Parent` per 
Liskov.


A different way to think about this is that method parameter and 
return types form a contract that is defined by the superclass 
and fulfilled by the subclass, and the subclass can relax the 
call contract ("I demand from my caller") and restrict the return 
contract ("I promise my caller"). Since the `Child`, by Liskov, 
can do everything the `Parent` can do, demanding less - ie. a 
`Parent` instead of a `Child` - keeps the superclass's call 
contract valid, and promising more - ie. returning a `Child` 
instead of a `Parent`, which may have additional capabilities - 
keeps the superclass's return contract valid.


Re: byte array to string

2021-02-24 Thread FeepingCreature via Digitalmars-d-learn

On Thursday, 25 February 2021 at 06:47:11 UTC, Mike wrote:

hi all,

If i have an array:
byte[3] = [1,2,3];

How to get string "123" from it?

Thanks in advance.


string str = format!"%(%s)"(array);


Re: byte array to string

2021-02-24 Thread FeepingCreature via Digitalmars-d-learn
On Thursday, 25 February 2021 at 06:57:57 UTC, FeepingCreature 
wrote:

On Thursday, 25 February 2021 at 06:47:11 UTC, Mike wrote:

hi all,

If i have an array:
byte[3] = [1,2,3];

How to get string "123" from it?

Thanks in advance.


string str = format!"%(%s)"(array);


Er sorry, typo, that should be "%(%s%)". "Print the elements of 
the array, separated by nothing." Compare "%(%s, %)" for a comma 
separated list.


Re: Foo Foo = new Foo();

2021-02-21 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 21 February 2021 at 18:07:49 UTC, JN wrote:

class Foo
{
}

void main()
{
Foo Foo = new Foo();
}

this kind of code compiles. Is this expected to compile?


Yes, why wouldn't it? main is a different scope than global; you 
can override identifiers from global in main. And "Foo" only 
exists after the declaration, so it doesn't conflict.


Re: 200-600x slower Dlang performance with nested foreach loop

2021-01-27 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 27 January 2021 at 02:14:39 UTC, H. S. Teoh wrote:
Yes, definitely try this.  This will completely eliminate the 
overhead of using an AA, which has to allocate memory (at 
least) once per entry added.  Especially since the data has to 
be sorted eventually anyway, you might as well sort first then 
use the sortedness as a convenient property for fast 
de-duplication.  Since .uniq traverses the range linearly, this 
will be cache-friendly, and along with eliminating GC load 
should give you a speed boost.



T


Associative arrays allocate per entry added?!

https://github.com/dlang/druntime/blob/master/src/rt/aaA.d#L205 
Oh God, associative arrays allocate per entry added!


Re: F*cked by memory corruption after assiging value to associative array

2021-01-25 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 25 January 2021 at 11:15:28 UTC, frame wrote:

After a while my program crashes.

I'm inspecting in the debugger that some strings are 
overwritten after a struct is assigned to an associative array.


- I have disabled the GC.
- All happens in the same thread.
- The strings belong to an object collection inside an object 
created from a d-DLL.
- The object returned by the DLL function is added to the GC 
with GC.addRoot().

- This object also lives in a static array the whole time.
- Not all objects are affected but many.
- The struct itself looks okay also the key for the associative 
array has normal form.


The data is not overwritten by another Thread (only one is 
running) but by the compiler. I'm watching it by memory 
location. It gets always visible first after that assignment. 
But how is this even possible? In theory, how could I ran into 
this issue?


That should really not be possible.

I suspect the memory used by the original data got reused for the 
associative array somehow. But if the GC is off from program 
start, that should really not occur. Do you maybe turn the GC off 
before the AA assignment, but after it's already marked that 
memory freed? Try turning it off completely from the commandline 
with --DRT-gcopt=gc:manual


Re: Handling referencing class parent instances in a GC friendly way.

2020-11-30 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 30 November 2020 at 14:33:22 UTC, realhet wrote:

Hi,

class A{
  A parent;
  A[] items;

  void myDestroy(){
items.each!(i => i.myDestroy);
parent = null;
// after this point I think the GC will release it 
automatically, and it will call ~this() too. Am I right?

  }
}

I have a hierarchy of class instances forward and backward 
linked to its items ant its parent.


What is a proper way to destroy an instance of class A? Is 
calling instance.myDestroy sufficient?


Am I right that this kind of uninitialization MUST not go into 
the ~this() destructor, because of the references the instance 
is holding, the system will never call the ~this()?


Or is there a better way for this type of thing in Dlang?


Thanks in advance!


The GC will release it anyways. The advantage of a GC is that it 
is not deterred by cyclic references, so as soon as no more 
references into A exist, it will disappear, no matter the parent 
pointer.


At least, that's the theory - in practice, since we don't have 
precise stack GC, any spurious or leftover pointer to an A can 
keep the whole tree alive, so the myDestroy cleanup method is 
still valid and recommended. Though you may want to do `items = 
null;` too.


Re: `enum x;` - what is it?

2020-08-19 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 19 August 2020 at 14:43:22 UTC, Victor Porton wrote:
On Wednesday, 19 August 2020 at 14:06:16 UTC, Victor Porton 
wrote:

This declaration does compile:

enum x;

But what is it? Is it an equivalent of

enum x { }

?

What in the specification allows this looking a nonsense

enum x;

?


Oh, found: "An empty enum body (For example enum E;) signifies 
an opaque enum - the enum members are unknown."


But what this "unknown" does mean? How "unknown" differs from 
"none" in this context?


The specification is unclear. It does not define the meaning of 
unknown. I will submit a bug report.


It means exactly what it says. The compiler doesn't know what 
members are in the enum. So you can't declare a variable of it, 
you can't use it directly.. you can p much only use it in 
pointers.


Re: `enum x;` - what is it?

2020-08-19 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 19 August 2020 at 14:06:16 UTC, Victor Porton wrote:

This declaration does compile:

enum x;

But what is it? Is it an equivalent of

enum x { }

?

What in the specification allows this looking a nonsense

enum x;

?


It's an enum type whose members we don't know.

So we can't declare "x var;" but we can declare "x* var;".

It's the enum version of "struct SomeExternCStruct;".


Re: D on lm32-CPU: string argument on stack instead of register

2020-08-05 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 4 August 2020 at 17:36:53 UTC, Michael Reese wrote:
Thanks for suggesting! I tried, and the union works as well, 
i.e. the function args are registered. But I noticed another 
thing about all workarounds so far:
Even if calls are inlined and arguments end up on the stack, 
the linker puts code of the wrapper function in my final binary 
event if it is never explicitly called. So until I find a way 
to strip of uncalled functions from the binary (not sure the 
linker can do it), the workarounds don't solve the size 
problem. But they still make the code run faster.


Try -ffunction-sections -Wl,--gc-sections. That should remove all 
unreferenced functions. It removes all unreferenced sections, and 
writes every function into a separate section.


Re: How to compile to .bin/.iso format

2020-06-17 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 17 June 2020 at 12:39:11 UTC, FeepingCreature wrote:

On Wednesday, 17 June 2020 at 12:30:24 UTC, Quantium wrote:
Hi all! I have a programm in D (The simplest OS), which should 
be compiled into .bin or .iso format to be possible to run it 
on VirtualBox. How can I compile it to .bin / .iso format and 
which compiler should I use?


Try this page? https://wiki.osdev.org/D_Bare_Bones combined 
with https://dlang.org/phobos/core_volatile.html to replace 
volatile.


Update: Tried and it works with ldc 1.20.1 (2.090.1) at least. 
The LDC version of the command is `ldc2 -betterC -m32 -c 
kernel.main.d -ofkernel.main.o -g`.




Re: How to compile to .bin/.iso format

2020-06-17 Thread FeepingCreature via Digitalmars-d-learn

On Wednesday, 17 June 2020 at 12:30:24 UTC, Quantium wrote:
Hi all! I have a programm in D (The simplest OS), which should 
be compiled into .bin or .iso format to be possible to run it 
on VirtualBox. How can I compile it to .bin / .iso format and 
which compiler should I use?


Try this page? https://wiki.osdev.org/D_Bare_Bones combined with 
https://dlang.org/phobos/core_volatile.html to replace volatile.


Re: What's the best way to find out which exceptions may be thrown ?

2020-06-03 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 2 June 2020 at 13:58:13 UTC, Bienlein wrote:
Because of the problems with checked exceptions they were 
deliberately left out in C#. Here is an interview with Anders 
Hejlsberg, the creator of C# at MS, where he explains the 
reasons for this decision: 
https://www.artima.com/intv/handcuffs.html


This wouldn't seem to apply if checked exceptions were inferred 
by default, right? And the issues with Java generics don't apply 
to D, because our metaprogramming infers attributes anyways.


Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])

2020-02-17 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote:

Hi all,

There's something in Phobos for that?

Thank you


Here you go:

import std;

// extract the types that make up the tuple
auto transposeTuple(T : Tuple!Types[], Types...)(T tuples)
{
// templated function that extracts the ith field of an array 
of tuples as an array

auto extractArray(int i)()
{
return tuples.map!(a => a[i]).array;
}
// return tuple of calls to extractArray, one for each tuple 
index
return tuple(staticMap!(extractArray, 
aliasSeqOf!(Types.length.iota)));

}

void main() {
Tuple!(int, double)[] array;
array ~= tuple(1, 2.0);
array ~= tuple(3, 4.0);
Tuple!(int[], double[]) tuple = array.transposeTuple;
assert(tuple[0] == [1, 3]);
assert(tuple[1] == [2.0, 4.0]);
}


Re: dub dustmite struggles

2020-01-19 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 20 January 2020 at 06:48:08 UTC, DanielG wrote:
I can't seem to figure out what dub's dustmite command is 
looking for with its regexes. No matter what I try - no matter 
how simple - the initial test fails.


I am able to run dustmite standalone just fine with the 
following test script:


cd example
dub 2>&1 | grep -F "ScrollView6__initZ+0xd8): undefined 
reference to \`internal'"


However, when I attempt using 'dub dustmite' with 
--linker-regex (or --linker-status, even), the initial test 
always fails. I've also tried simplifying the regex on the 
assumption that I'm not escaping things properly - to no avail.


Is it perhaps something to do with my project structure? My 
project is a library containing an /example subfolder, 
containing an application dub project, and that's where my 
linker error occurs, not in the library itself. So that's where 
I'm attempting to run dub dustmite as well.


I don't know how `dub dustmite` works, but my advice would be to 
use standalone dustmite and write a shellscript that handles your 
success/fail condition with an exit code. That's always worked 
for me, and it makes it easier to externally check what's 
happening.

Ie. test.sh:

---
#!/bin/sh
dub 2>&1 |grep -F "ScrollView6__initZ+0xd8): undefined

reference to \`internal'"

---

dustmite example ../test.sh

Then if you have to recurse into a dub project, just copy it into 
your example folder so it's compiled in, and repeat.


Re: weird behave of Array?

2019-07-29 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 29 July 2019 at 05:58:21 UTC, dmm wrote:

So, d try to be smart, only make thing worse?


D is behaving exactly as it should here. You simply have a wrong 
model of what an array is in D.


In C++, an array owns its memory. In D, an array is a thin 
wrapper around GC managed memory. As such, for instance, you can 
take a reference to an array field, then resize the array, and 
the original reference will still be valid and at its original 
value.


To do what you want, use std.array.Appender, which owns its 
memory.


import std.algorithm;
import std.array;
import std.range;
import std.stdio;
void main() {
Appender!(int[]) app;
10.iota.each!(a => app.put(a));
writefln!"%s, %s"(app.data.ptr, app.data);
app.shrinkTo(0);
10.iota.each!(a => app.put(a));
writefln!"%s, %s"(app.data.ptr, app.data);
}



Re: Overloads not returning appropriate info. [Field reflunkory]

2019-04-07 Thread FeepingCreature via Digitalmars-d-learn

On Sunday, 7 April 2019 at 03:47:25 UTC, Alex wrote:

rules are meant to be broken.


No they're not! Almost by definition not!

More comprehensively, if you break a rule you take responsibility 
for the outcome. You wanna use stringof? "Don't use stringof for 
that." "rules are meant to be broken." -- "Wah, my code doesn't 
work, stringof is shit, bad design, fix D pls." Don't ask 
questions if you don't care about the answers. More importantly, 
don't ignore advice and then complain about it.


You can't expect to lead by authority. Give a good reason why I 
should avoid it and change my current ways and I will.


Your code will break in surprising and unfixable ways. `stringof` 
is not *for* mixin. If you use it for mixin, you will be on your 
own design-wise. The language will not be changed to "fix" the 
"bugs" you run into. It will work until it won't work, and then 
you'll have to rewrite the entire thing anyway.


Don't use stringof for mixin.


Re: Is there something special required to use Appender.clear

2019-01-30 Thread FeepingCreature via Digitalmars-d-learn
On Monday, 28 January 2019 at 15:16:54 UTC, Steven Schveighoffer 
wrote:
It will inspect the allocated length from the GC if the array 
is appendable from the beginning. So it's not always going to 
reallocate.


e.g.:

string x = "abc".idup;

auto app = x.appender;

app ~= "xyz"; // does not reallocate.

-Steve


Fair enough.

My use case is simply the standard usecase of Appender: I want 
to build up an array in a way that reduces GC churn. Maybe 
it's an array of structs that contain const members that I'll 
serialize to JSON and send on a socket. In that case, I know 
for a fact that no references will hang around past the 
serialization. That's what clear _is for._ I don't see why 
this would be different with const or immutable data; if you 
hold references past .clear being called you're in trouble 
*anyways.*


Right, this does seem like a big limitation. Keeping with the 
spirit of how slices don't own the memory in question, Appender 
is being conservative with what it doesn't know.


I wonder if it may be more appropriate to instead of preventing 
clear() on immutable/const arrays, to make it @system. Or maybe 
call it something different "dangerousClear" or something ;)


There definitely should be some way to fail if clear is called 
on an array that was passed into the constructor.


But I'm still not sure we should allow overwriting immutable 
memory without a cast, even in @system code.




My problem is this.

const and immutable are *not* well supported in the standard 
library at the moment. What I want is that I can use the idioms 
of the stdlib, semantically, in a way that lets me *not care* 
about const or immutable, that lets me express the patterns I 
want without having to worry about whether some type deep inside 
my code, a dub library, or phobos itself decided to declare a 
field immutable.


Appender covers two usecases: "capacity caching" and "memory 
reuse." Both of those usecases have two const variations: 
"possibly immutable" and "mutable".


  mutable capacity caching | mutable memory reuse
---+-
immutable capacity caching | immutable memory reuse

But instead of cutting between capacity caching and memory reuse, 
down the middle, Appender cuts between mutable and immutable, 
left to right. I think this is a symptom of a broad negligence of 
constness as a first-class property - constness works sometimes, 
and it's nice if it does, but it can't be *relied* on to be well 
supported. This makes using const in D an eternal uphill 
struggle. Why even go to all the trouble to make a new major 
version of the language just to introduce constness, if it's not 
going to be treated as a first-class concern? I don't want to 
have to sprinkle static if(isAssignable!T) everytime I want to 
use a library type. If Phobos offers me as generic a data 
structure as Appender, parameterized on T, it should work for T, 
regardless of what T is doing, and *certainly* regardless of what 
fields in T are marked const. Especially considering that if a 
field is not marked as const, that hardly means it's not going to 
lead to bugs if its memory is reused while you're referencing it!


Re: Is there something special required to use Appender.clear

2019-01-28 Thread FeepingCreature via Digitalmars-d-learn
On Friday, 25 January 2019 at 14:33:16 UTC, Steven Schveighoffer 
wrote:

On 1/25/19 3:20 AM, FeepingCreature wrote:
On Thursday, 24 January 2019 at 17:49:34 UTC, Ali Çehreli 
wrote:
Aren't the semantics of .clear that it's invalid to access 
references to .data after calling .clear, period? And if not, 
then shouldn't they be? Consider if Appender managed its own 
memory and held on to previously-allocated arrays while you 
were appending, only to free them on .clear. That seems like 
something Appender should be allowed to do. If you don't want 
it, just reinitialize Appender instead of calling .clear.


You are advised not to. But it's not unsafe, as the memory is 
still there.




That's stupid. Why would you advise me not to, if there's no 
problem with it? Either it should be accepted or it should be 
forbidden, just like warnings.


Any reason that the semantics of .clear should be different 
for a starting array? Anyway if so, I'd prefer to just make 
that a runtime error.


Yes, because Appender doesn't know where that memory comes 
from. A string could be, for instance, passed to another thread 
and being used, you wouldn't want to overwrite it.




In which case, you can't reuse the Appender and should not call 
`clear`! It seems like we're gimping functionality of a very 
basic tool for memory efficiency for the sake of not confusing 
users. This rarely pays off.


Generally speaking, overwriting immutable data is UB in D 
anyway.


Making it a runtime error would be possible, but there has to 
be a good reason to make it that way.




I'm mostly fishing around if anyone has an objection to a PR 
to change this.


Without good reasons to change, I don't see why it would be 
accepted.


Maybe you can describe your use case?



My use case is simply the standard usecase of Appender: I want to 
build up an array in a way that reduces GC churn. Maybe it's an 
array of structs that contain const members that I'll serialize 
to JSON and send on a socket. In that case, I know for a fact 
that no references will hang around past the serialization. 
That's what clear _is for._ I don't see why this would be 
different with const or immutable data; if you hold references 
past .clear being called you're in trouble *anyways.*


I consider initializing Appender with an array referencing 
immutable data a borderline error anyways. The entire point of 
Appender is that it caches capacity data of GC managed memory, 
which is never immutable. On the first append to an 
immutable-memory array, it has to reallocate *anyways*. There is 
no benefit to initializing an Appender with immutable memory over 
just appending it first thing, unless you never plan to append to 
it ever.


Re: Is there something special required to use Appender.clear

2019-01-25 Thread FeepingCreature via Digitalmars-d-learn

On Thursday, 24 January 2019 at 17:49:34 UTC, Ali Çehreli wrote:

On 01/24/2019 04:35 AM, FeepingCreature wrote:
> On Tuesday, 27 March 2018 at 12:31:05 UTC, Simen Kjærås wrote:
>> On Tuesday, 27 March 2018 at 12:17:58 UTC, Ellie Harper
wrote:
>>> Sorry if this is a stupid question, but is there something
special
>>> required to call Appender.clear?  When I attempt even just
a simple
>>> use I am getting compile errors relating to `template
object.clear`.
>>
>> From the documentation for Appender:
>>
>>> Note
>>> clear is disabled for immutable or const element types, due
to the
>>> possibility that Appender might overwrite immutable data.
>>
>> Since string is immutable(char)[], clear() is simply not
available for
>> appender!string.
>>
>> --
>>   Simen
>
> Isn't this wrong, though? Appender controls the memory it
references. It
> could just choose to allocate non-immutable memory
internally. As long
> as any const data put into the appender is *returned* as
const, there is
> no chance of immutable memory being overwritten.

I think Appender is trying to protect previous data from 
Appender's later use. If it handed out immutable data, the user 
is expecting it to not change. So, Appender cannot clear it for 
later use.


Ali


Aren't the semantics of .clear that it's invalid to access 
references to .data after calling .clear, period? And if not, 
then shouldn't they be? Consider if Appender managed its own 
memory and held on to previously-allocated arrays while you were 
appending, only to free them on .clear. That seems like something 
Appender should be allowed to do. If you don't want it, just 
reinitialize Appender instead of calling .clear.


Appender is sometimes given a starting array. clear isn't 
callable in that case, and we don't distinguish the difference 
in the type or at runtime.


Any reason that the semantics of .clear should be different for a 
starting array? Anyway if so, I'd prefer to just make that a 
runtime error.


I'm mostly fishing around if anyone has an objection to a PR to 
change this.


Re: Is there something special required to use Appender.clear

2019-01-24 Thread FeepingCreature via Digitalmars-d-learn

On Tuesday, 27 March 2018 at 12:31:05 UTC, Simen Kjærås wrote:

On Tuesday, 27 March 2018 at 12:17:58 UTC, Ellie Harper wrote:
Sorry if this is a stupid question, but is there something 
special required to call Appender.clear?  When I attempt even 
just a simple use I am getting compile errors relating to 
`template object.clear`.


From the documentation for Appender:


Note
clear is disabled for immutable or const element types, due to 
the possibility that Appender might overwrite immutable data.


Since string is immutable(char)[], clear() is simply not 
available for appender!string.


--
  Simen


Isn't this wrong, though? Appender controls the memory it 
references. It could just choose to allocate non-immutable memory 
internally. As long as any const data put into the appender is 
*returned* as const, there is no chance of immutable memory being 
overwritten.