Re: Why is Phobos `Flag` so overthought ?

2024-05-11 Thread cc via Digitalmars-d-learn

On Thursday, 9 May 2024 at 18:48:12 UTC, Nick Treleaven wrote:
 We have a tool in our box already called `true` and that 
solves the problem.  If we had to type out the full name of 
every argument passed to every function ever written we may as 
well just adopt ObjC Cocoa style and call it 
StopWatchWithAutoStartBool().


Strawman.


Not at all.  I mean exactly that.  Why do you believe this 
function is so important it needs to have its argument type 
explicitly stated, when most functions don't?  Either that, or 
you believe all functions should.  It's arbitrary and pointless.


Re: Why is Phobos `Flag` so overthought ?

2024-05-09 Thread cc via Digitalmars-d-learn

On Wednesday, 8 May 2024 at 10:24:07 UTC, Nick Treleaven wrote:

On Wednesday, 8 May 2024 at 04:27:13 UTC, cc wrote:
It doesn't allow a simple boolean to be used as an argument, 
or any other Flag as they are different instantiations of a 
template rather than equivalent aliases.
It is however awful, cumbersome, annoying design and needs to 
be completely phased out now that we have named arguments.


Flag enforces that the argument says what it relates to. `true` 
does not say what it relates to. Named arguments are optional, 
so I don't see how they could make Flag redundant.


It's pointless mandatory verbosity.  StopWatch ctor only takes 
one boolean argument.  It doesn't *need* to specify what it 
relates to.  You either already know, or you have to look it up 
anyway.  Flags made sense when you might get the order of 
multiple bools confused, but if there's only one, *or* if you can 
use named arguments to avoid ambiguity, there's no point in 
demanding every parameter be a unique type.  It's easy to 
remember I can pass a bool to a StopWatch to autostart it.  It's 
less easy to remember that a specific unique type needs to be 
used, and remembering whether the name/casing of that type was 
Start, StartNow, StartAuto, Autostart, AutoStart, autostart, 
autoStart, etc.  We have a tool in our box already called `true` 
and that solves the problem.  If we had to type out the full name 
of every argument passed to every function ever written we may as 
well just adopt ObjC Cocoa style and call it 
StopWatchWithAutoStartBool().


Re: Why is Phobos `Flag` so overthought ?

2024-05-07 Thread cc via Digitalmars-d-learn

On Monday, 6 May 2024 at 17:55:49 UTC, user1234 wrote:

I think this just works:

```d
enum Flag : bool
{
no,
yes
}
```
...
must be a reason but I cant find it RN ;)


In "properly" designed Phobos packages, it's unambiguous.  Take 
for example std.datetime.stopwatch:


```d
import std.typecons : Flag;
alias AutoStart = Flag!"autoStart";
alias MyOtherFlag = Flag!"myOtherFlag";
...
//auto sw = StopWatch(true); // Not allowed
//auto sw = StopWatch(MyOtherFlag.yes); // Not allowed
auto sw = StopWatch(AutoStart.yes);
```
It doesn't allow a simple boolean to be used as an argument, or 
any other Flag as they are different instantiations of a template 
rather than equivalent aliases.
It is however awful, cumbersome, annoying design and needs to be 
completely phased out now that we have named arguments.


Re: Adapting foreign iterators to D ranges

2024-04-24 Thread cc via Digitalmars-d-learn

On Wednesday, 24 April 2024 at 05:08:25 UTC, Salih Dincer wrote:
Yes, `opApply()` works! You just need to use `do while()` 
instead of `while()` because it skips the first item.


It depends on the type of structure being consumed, if it 
provides "next" as a direct pointer then yeah you would need to 
consume the item first before iterating to the next in line.  
However some APIs provide an opaque iterator type where you call 
a "next" method to get the first element, IIRC Lua does something 
like this.


Re: Adapting foreign iterators to D ranges

2024-04-23 Thread cc via Digitalmars-d-learn

On Monday, 22 April 2024 at 11:36:43 UTC, Chloé wrote:
I wish to adapt this interface to a forward range for use with 
foreach and Phobos' range utilities. This amounts to 
implementing empty, front, and popFront, in terms of next and 
some state. But there is a choice to be made regarding the 
first call to next.


Just to offer an alternative solution (since it sometimes gets 
overlooked), there is also the `opApply` approach.  You don't get 
full forward range status, and checking whether it's empty 
essentially requires doing something like std.algorithm 
`walkLength`, but if all you need is basic iteration, it can be a 
simpler solution:


```d
struct Range {
private I iter;
this(I iter) { this.iter = iter; }
int opApply(scope int delegate(T* t) dg) {
while (auto current = next(iter)) {
if (auto r = dg(current))
return r;
}
return 0;
}
}
void main() {
I someIter; // = ...
auto range = Range(someIter);
foreach (const t; range) {
writeln(*t);
}
}
```


Re: Making one struct work in place of another for function calls.

2024-04-17 Thread cc via Digitalmars-d-learn
On Wednesday, 17 April 2024 at 03:13:46 UTC, Liam McGillivray 
wrote:

On Wednesday, 17 April 2024 at 02:39:25 UTC, Paul Backus wrote:
This is called [row polymorphism][1], and it does not exist in 
D.


You could approximate it by making `someFunction` a template, 
and accepting any type `T` that has the necessary members 
instead of only accepting `typeB`. But this is only possible 
if you are free to modify the definition of `someFunction`.


Is there a way I can replace "`TypeB`" in the function 
parameters with another symbol, and then define that symbol to 
accept `TypeB` as an argument, but also accept `TypeA` which 
would get converted to `TypeB` using a function? I'm willing to 
make a function template if it's rather simple.


Normal template approach would be as simple as:
```d
struct TypeA {
int x, y;
string name;
}
struct TypeB {
float x, y;
ubyte[] data;
}
// Strict version, only allows the named structs
float someFunction(S)(S input) if (is(S == TypeA) || is(S == 
TypeB)) {

writefln("input loc: %s,%s", input.x, input.y);
return 0;
}
void main() {
someFunction(TypeA(1,1));
someFunction(TypeB(2,2));
}
```

Or you could write the function like:
```d
// Permission version, accepts any struct with the required 
members
float someFunction(S)(S input) if (is(S == struct) && 
isNumeric!(typeof(S.x)) && isNumeric!(typeof(S.y))) {

writefln("input loc: %s,%s", input.x, input.y);
return 0;
}
```

In fact, you don't even necessarily need the template constraints:
```d
// It just works... usually
float someFunction(S)(S input) {
writefln("input loc: %s,%s", input.x, input.y);
return 0;
}
```
But then you might get (at best) less clear error messages when a 
wrong type is passed, and (at worst) funny business if someone 
passes a type that technically satisfies the function behavior 
but isn't actually a type you expected and is treating those 
members differently.  It's often ideal to have either some type 
of template constraints, or static ifs/static asserts in the 
function body so you know what you're dealing with.


Another solution, without templates, if you can for instance 
modify TypeB but not TypeA, is to give TypeB a constructor that 
takes a TypeA as an argument.

```d
struct TypeA {
int x, y;
string name;
}
struct TypeB {
float x, y;
immutable(ubyte)[] data;
this(float x, float y) { // We need a constructor here now too
this.x = x;
this.y = y;
}
this(TypeA a) {
this.x = a.x;
this.y = a.y;
this.data = cast(immutable(ubyte)[]) a.name;
}
}
float someFunction(TypeB input) {
writefln("input loc: %s,%s", input.x, input.y);
return 0;
}
auto someFunction(TypeA input) => someFunction(TypeB(input));
```
If you cannot modify either struct definition, you could do the 
conversion by hand in the stub instead.


Additionally, if you have many functions and you don't want to 
write stubs for all of them, you could use mixins to generate 
them for you like so:

```d
float someFunctionUno(TypeB input) {
writefln("uno loc: %s,%s", input.x, input.y);
return 0;
}
float someFunctionDos(TypeB input) {
writefln("dos loc: %s,%s", input.x, input.y);
return 0;
}
float someFunctionTres(TypeB input) {
writefln("tres loc: %s,%s", input.x, input.y);
return 0;
}
// Consider also UDAs, iterating member functions, etc
static foreach (sym; "someFunctionUno someFunctionDos 
someFunctionTres".split) {
	mixin(format(`auto %s(TypeA input) => %s(TypeB(input));`, sym, 
sym));

}
void main() {
someFunctionUno(TypeA(1,1));
someFunctionDos(TypeB(2,2));
}
```

There are yet other ways to do it as well.  The solution you'll 
use will depend on more detailed specifics.  In many cases, when 
working with similar data types and you want the function itself 
to be as agnostic as possible about what it's dealing with, 
templates are often the way to go.  D's 
templating/metaprogramming capacities are extremely powerful and 
flexible.  However, it may not necessarily be the right choice if 
you need to rely on very specific handling of the data types in 
question and their layouts.


Re: Opinions on iterating a struct to absorb the decoding of a CSV?

2024-03-31 Thread cc via Digitalmars-d-learn

On Monday, 1 April 2024 at 04:54:46 UTC, cc wrote:
I scoured [Traits](https://dlang.org/spec/traits.html) and 
[std.traits](https://dlang.org/phobos/std_traits.html) looking 
for a simple method to tell whether a member was declared as 
enum but couldn't find one, so if anyone knows a proper way to 
do it please let me know.


Turns out this can be done as part of the panacea that is `is()` 
statements.

```d
static if (is(typeof({enum X = SYM;})))
```


Re: Opinions on iterating a struct to absorb the decoding of a CSV?

2024-03-31 Thread cc via Digitalmars-d-learn

On Thursday, 28 March 2024 at 17:23:39 UTC, Andy Valencia wrote:
I wanted a lightweight and simpler CSV decoder.  I won't post 
the whole thing, but basically you instantiate one as:


That's pretty much the best way to do it.  While `.tupleof` does 
look kind of hacky, and you could instead iterate using 
`___traits(allMembers, T)` and `__traits(getMember, T, 
"symbolname")` which looks more self-documenting, this ends up 
being more of a pain, because it's going to iterate through 
everything in the type, including functions, 
constructors/destructors, aliases, enums, static members, 
inherited members in classes, etc etc, and it's a plate of 
spaghetti to sort them all out, plus there are issues with 
aliasing on top of that.  Sometimes you might want to do that of 
course, but for simple situations like this, `.tupleof` just 
works.


```d
struct Foo {
int x = 1;
float f = 3.14;
string abc = "abc";
string[] xyz;
immutable int i;
const int c;

this(int x) { this.x = x; i = 7; c = 8; }
this(float f) { this.f = f; }
bool speak() { return false; }
bool speak(bool b) { return b; }
	void toString(scope void delegate(const(char)[]) writer) { 
/*...*/ }

alias X = int;
enum E = 3;
static enum F = 4;
static int y = 5;
}
void main() {
Foo foo;
dumpInfo(foo);
}
void dumpInfo(T)(T t) {
import std.traits;
static foreach (idx, field; T.tupleof) {{
alias TYPE = typeof(field);
enum NAME = field.stringof;
writefln("[%s] %s => %s", TYPE.stringof, NAME, t.tupleof[idx]);
}}
writeln;

static foreach (sym; __traits(allMembers, T)) {{
enum bool ISSTATIC = hasStaticMember!(T, sym);
static if (ISSTATIC)
alias SYM = __traits(getMember, T, sym);
else
alias SYM = __traits(getMember, t, sym);
enum NAME = sym;
static if (isType!SYM) { // aliases
writefln("(TYPE) %s : %s", NAME, SYM.stringof);
} else static if (isFunction!SYM) {
alias OVERLOADS = __traits(getOverloads, T, sym);
static foreach (idx, FUNC; OVERLOADS) {
writefln("(FUNC) %s<%s> : %s", NAME, idx, 
typeof(FUNC).stringof);
writefln("\t%s %s %s", ReturnType!FUNC.stringof, 
Parameters!FUNC.stringof, 
ParameterIdentifierTuple!FUNC.stringof); // Useful

}
} else {
alias TYPE = typeof(SYM);

// where is isEnum or isManifestConstant?
			enum bool ISASSIGNABLE = __traits(compiles, 
{__traits(getMember, t, sym) = __traits(getMember, t, sym);});
			enum bool ISASSIGNABLE_IN_CTOR = __traits(compiles, 
{cast()__traits(getMember, t, sym) = cast()__traits(getMember, t, 
sym);});


static if (!ISASSIGNABLE && !ISASSIGNABLE_IN_CTOR) {
// MAYBE it's an enum.  Or something else 
unassignable.
writefln("(ENUM) [%s] %s => %s", TYPE.stringof, 
NAME, SYM);
} else static if (ISSTATIC) {
writefln("(STATIC) [%s] %s => %s", 
TYPE.stringof, NAME, SYM);
} else {
writefln("[%s] %s => %s", TYPE.stringof, NAME, 
__traits(getMember, t, sym)); // SYM doesn't work here

}
}
}}
}
```

```
[int] x => 1
[float] f => 3.14
[string] abc => abc
[string[]] xyz => []
[immutable(int)] i => 0
[const(int)] c => 0

[int] x => 1
[float] f => 3.14
[string] abc => abc
[string[]] xyz => []
[immutable(int)] i => 0
[const(int)] c => 0
(FUNC) __ctor<0> : ref Foo(int x)
Foo (int) AliasSeq!("x")
(FUNC) __ctor<1> : ref Foo(float f)
Foo (float) AliasSeq!("f")
(FUNC) speak<0> : bool()
bool () ()
(FUNC) speak<1> : bool(bool b)
bool (bool) AliasSeq!("b")
(FUNC) toString<0> : void(scope void delegate(const(char)[]) 
writer)

void (scope void delegate(const(char)[])) AliasSeq!("writer")
(TYPE) X : int
(ENUM) [int] E => 3
(ENUM) [int] F => 4
(STATIC) [int] y => 5
```

I scoured [Traits](https://dlang.org/spec/traits.html) and 
[std.traits](https://dlang.org/phobos/std_traits.html) looking 
for a simple method to tell whether a member was declared as enum 
but couldn't find one, so if anyone knows a proper way to do it 
please let me know.


Re: Deriving a struct from another one via template: Easy way to propagate UDAs?

2024-03-15 Thread cc via Digitalmars-d-learn

On Thursday, 14 March 2024 at 23:19:37 UTC, Inkrementator wrote:
I am trying to derive a struct from another. I want to modify 
each field such that type of it goes from some T to Nullable!T, 
preserving all fieldnames and UDAs.


This is trivially easy if your types are visible at module level, 
and mixin is a fine tool for the job.  It doesn't work quite so 
well with [Voldemort 
types](https://wiki.dlang.org/Voldemort_types).


```d
struct MyUDA { int q; }
struct Foo { int f; }
struct MyStruct {
@MyUDA(3) int x;
@MyUDA(4) Foo f;
@MyUDA(5) @MyUDA(7) string s;
}
auto generateUDAs(A...)() {
string[] udaStrs;
static foreach (uda; A)
udaStrs ~= "@(" ~ uda.stringof ~ ")";
return udaStrs;
}
struct Wrapped(S) {
static foreach (idx, field; S.tupleof) {
//pragma(msg, format(... can be used to preview
		mixin(format("%s %s %s;", generateUDAs!(__traits(getAttributes, 
field)).join(' '), Nullable!(typeof(field)).stringof, 
field.stringof));

}
}
void main() {
MyStruct s;
s.x = 3;
s.f = Foo(1);
s.s = null;
Wrapped!MyStruct w;
w.x = s.x;
w.f = s.f;
w.s = s.s;
w.x.nullify;
w.f.nullify;
w.s.nullify; // strings/objects are already nullable though
	static assert(__traits(getAttributes, w.s) == 
AliasSeq!(MyUDA(5), MyUDA(7)));

}
```

If you absolutely must though, you could do something like
```d
enum WrapMixin = q{
struct Wrapped(S) {
static foreach (field; S.tupleof)
			mixin(format("%s %s %s;", 
generateUDAs!(__traits(getAttributes, field)).join(' '), 
Nullable!(typeof(field)).stringof, field.stringof));

}
};
void main() {
struct MyUDA { .
struct MyStruct { .
mixin(WrapMixin);
Wrapped!MyStruct w;
}
```


Re: Can a D library have some types determined by the client program?

2024-03-10 Thread cc via Digitalmars-d-learn

On Saturday, 9 March 2024 at 22:03:34 UTC, Liam McGillivray wrote:
Secondly, I found out that interfaces can't have variables. 
What!? That's crazy! Why wouldn't they? They totally should. 
Doesn't this mean that I will need to use getter and setter 
functions instead of direct access when using interfaces? I 
don't like this.


An interface just defines an interface, a set of method 
signatures that a class can respond to, and must implement.  If 
you want storage and functionality, you can define a base class.  
A derived class can inherit from either one base class or one or 
more interfaces.  Or a combination, but multiple inheritance is 
not a well-liked idea.


```d
class Map {
int someVar = 3;
void someFunc() {
// default behavior
writeln("hello");
}
}

class CustomMap!TierType : Map {
override void someFunc() {
// new behavior
writefln("good day %s %s", someVar, TierType.stringof);
}
}

void main() {
auto map = new Map;
map.someFunc() // hello
map = new CustomMap!uint;
map.someFunc() // good day 3 uint
}
```

In the last line of this code, the variable `map` is still of 
type `Map` (chosen by `auto` when it received `new Map`, but the 
actual class object it references is of type `CustomMap!uint`, 
hence calling a virtual function like `someFunc` calls the 
derived version instead of the original.  Note that functions 
that take template arguments (not included here) don't 
necessarily follow this behavior; mixing templated methods and 
inheritance has some pitfalls.


Re: Can a D library have some types determined by the client program?

2024-03-08 Thread cc via Digitalmars-d-learn

On Friday, 8 March 2024 at 06:03:51 UTC, Liam McGillivray wrote:
A problem I have is that the 3 classes Map, Tile, and Unit 
reference each-other. If I turn Map into a template, than it 
complains about the member variable of Unit declared as `Map 
map;` without arguments. I change this line to `Map!TileType 
map;` but this requires that Unit is also turned into a 
template.


If you don't want Unit to be a template, you can just have Map 
derive from a basic interface or abstract class.  You can also 
have every relevant class share similar templates, you just need 
to remember to supply the template arguments everywhere.  You'll 
need to think about how much interoperation you want between 
these classes.  Does Unit really need to know what TileType map 
is using, or can it just trust that when it asks Map to move, Map 
will handle everything related to tile types?  Generally it's 
best practice to have as much of the inner workings isolated as 
possible and just provide methods to access functionality.  To 
ease some of the template argument!spaghetti, you could insert 
aliases into the classes via fully qualified symbol names.
Another alternative, if everything is defined on one file, you 
could wrap everything in a single template, but I don't usually 
favor this strategy.


```d
//version=Interfaced;
version=AllTemplated;
//version=AllTemplatedAliases;
//version=OneTemplate;

version(Interfaced) {
interface IMap {
Unit addNewUnit();
}
class Map(TileType) : IMap {
Unit[] units;
Unit addNewUnit() {
auto unit = new Unit(this);
units ~= unit;
return unit;
}
}
class Unit {
IMap map;
private this(IMap map) {
this.map = map;
}
}
void main() {
auto map = new Map!uint;
auto unit = map.addNewUnit;
}

} else version(AllTemplated) {
class Map(TileType) {
Unit!TileType[] units;
auto addNewUnit() {
auto unit = new Unit!TileType(this);
units ~= unit;
return unit;
}
}
class Unit(TileType) {
Map!TileType map;
private this(Map!TileType map) {
this.map = map;
}
}
void main() {
auto map = new Map!uint;
auto unit = map.addNewUnit;
}

} else version(AllTemplatedAliases) {
class Map(TileType) {
alias Unit = mymodule.Unit!TileType;
Unit[] units;
auto addNewUnit() {
auto unit = new Unit(this);
units ~= unit;
return unit;
}
}
class Unit(TileType) {
alias Map = mymodule.Map!TileType;
Map map;
private this(Map map) {
this.map = map;
}
}
void main() {
auto map = new Map!uint;
auto unit = map.addNewUnit;
}

} else version(OneTemplate) {
template Map(TileType) {
class Map {
Unit[] units;
auto addNewUnit() {
auto unit = new Unit(this);
units ~= unit;
return unit;
}
}
class Unit {
Map map;
private this(Map map) {
this.map = map;
}
}
}
void main() {
auto map = new Map!uint;
auto unit = map.addNewUnit;
}
}
```

If a given class doesn't really need to know what the template 
parameters are to the other class it's interacting with, I would 
avoid defining too many template types everywhere and just use 
interfaces or abstract parent classes.


After changing `class Unit` to `class Unit (TileType), it 
complains about the line `Unit* occupant;` in Tile.


Are you sure you need a pointer here?  Class objects in D are 
already reference-type by default.


Re: Hidden members of Class objects

2024-03-07 Thread cc via Digitalmars-d-learn
On Thursday, 7 March 2024 at 00:38:30 UTC, Richard (Rikki) Andrew 
Cattermole wrote:


On 07/03/2024 1:28 PM, Carl Sturtivant wrote:

On Wednesday, 6 March 2024 at 23:45:00 UTC, H. S. Teoh wrote:
In D, there's a pointer to the vtable and another pointer to 
a Monitor object (used for synchronized methods).  There was 
talk about getting rid of the Monitor field years ago, but 
nothing has happened yet.


Very interesting: is the monitor field ever touched by 
compiled D code at any point nowadays? Or is it just vestigial?


Yes its opt-in. 
https://dlang.org/spec/statement.html#synchronized-statement


I've stumbled over the Monitor/etc sometimes writing 
serialization, RPC, LUA etc modules iterating over class members, 
looking for UDAs, after trying to separate everything out using 
isFunction/isTemplate/etc, on top of dealing with overload 
spaghetti, I now just explicitly do something dumb like this to 
get those edge cases out of the way:


```d
static foreach (sym; __traits(allMembers, T))
static if 
(!["__ctor","__dtor","__xdtor","Monitor","factory"].canFind(sym)) 
{{

...
```



Re: Searching for i" in the forum

2024-02-26 Thread cc via Digitalmars-d-learn

On Sunday, 25 February 2024 at 01:19:15 UTC, Lysander wrote:

On Friday, 23 February 2024 at 23:18:12 UTC, kdevel wrote:

How do I search for

   i"

in the forum? I get the following errors:

   i" -> Error: malformed MATCH expression: [i"] (1)
   i\" -> Error: malformed MATCH expression: [i\"] (1)
   'i"' -> Error: malformed MATCH expression: ['i"'] (1)
   `i"` -> Error: malformed MATCH expression: [`i"`] (1)
   "i\"" -> Error: malformed MATCH expression: ["i\""] (1)


Use the i\" in the exact phrase box from the advanced search.
Advanced search button is on the error page from the malformed 
match search


This doesn't work.  It autocorrects to `"i\"` and returns the 
word/letter `I`, not `i"` letter followed by a doublequote.
Looks like some adjustment of the search algorithm may be 
necessary in light of upcoming interpolated strings.




Re: How can i find my LAN IP Address using std.socket?

2024-02-18 Thread cc via Digitalmars-d-learn
On Tuesday, 4 February 2014 at 13:02:26 UTC, TheFlyingFiddle 
wrote:
I'm trying to find my own ip address using std.socket with 
little success. How would i go about doing this? (It should be 
a AddressFamily.INET socket)


On Windows, you can use the Win32`GetAdaptersInfo`[1] function to 
get a list of IPv4 adapters and addresses.  If you need IPv6 
addresses or other more modern features, there is the 
`GetAdaptersAddresses`[2] function, however it doesn't seem the 
necessary Windows headers (IPTypes.h / ifdef.h) have been ported 
to D for this yet.


[1] 
https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersinfo
[2] 
https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses


As I attempt to post this, I now see this thread is... 10 years 
old.  Oh well, still relevant I think.


```d
import std.string;
pragma(lib, `mingw/iphlpapi.lib`); // included with dmd

struct Adapter {
string name;
string desc;
struct IPMask {
string ip;
string mask;
}
IPMask[] addresses;
}

Adapter[] getAdapters() {
import core.sys.windows.windows;
//import core.sys.windows.nspapi;
import core.sys.windows.iptypes;
import core.sys.windows.iphlpapi;

void[] buf;
uint size = 0;
auto ret = GetAdaptersInfo(null, );
	assert(ret == ERROR_BUFFER_OVERFLOW && size > 0, "Expected 
GetAdaptersInfo to return ERROR_BUFFER_OVERFLOW to query size of 
buffer");

buf.length = size;
ret = GetAdaptersInfo(cast(IP_ADAPTER_INFO*) buf.ptr, );
assert(!ret, "GetAdaptersInfo error");

auto adpt = cast(IP_ADAPTER_INFO*) buf.ptr;

Adapter[] adapters;

while (adpt) {
scope(success) adpt = adpt.Next;

Adapter adapter;
adapter.name = adpt.AdapterName.fromStringz.idup;
adapter.desc = adpt.Description.fromStringz.idup;

IP_ADDR_STRING addr = adpt.IpAddressList;
auto paddr = 
while (paddr) {
scope(success) paddr = addr.Next;
			adapter.addresses ~= 
Adapter.IPMask(paddr.IpAddress.String.fromStringz.idup, 
paddr.IpMask.String.fromStringz.idup);

}
adapters ~= adapter;
}
return adapters;
}

void main() {
import std.stdio;
auto adapters = getAdapters();
adapters.writeln;
}
```


Re: Generating custom toString for structs

2024-01-11 Thread cc via Digitalmars-d-learn

On Thursday, 11 January 2024 at 12:45:45 UTC, cc wrote:
I don't use the delegate version personally, but if that's 
already working for you, may as well stick with it.


In retrospect, that delegate version is probably quite a bit 
better.


Re: Generating custom toString for structs

2024-01-11 Thread cc via Digitalmars-d-learn

On Sunday, 7 January 2024 at 09:49:36 UTC, Renato wrote:
Hi, I wanted to customize the toString implementation for my 
structs.


So I wrote a mixin for doing that:


Alternative format similar to what you already have:
```d
import std.format;

mixin template ToStringMixin() {
void toString(W)(ref W writer) {
alias T = typeof(this);
		writer.formattedWrite("%s(\n", T.stringof); // See also: 
std.traits.fullyQualifiedName

static foreach (idx, field; T.tupleof) {
			writer.formattedWrite("\t%s: %s\n", T.tupleof[idx].stringof, 
this.tupleof[idx]);

}
put(writer, ")");
}
}

struct Foo {
int x, y;
string s;
mixin ToStringMixin;
}

void main() {
auto foo = Foo(3, 4, "hello");
writeln(foo);
}

```

Note however that the templated version of toString(W) can be 
difficult to debug in some cases as, if it fails to compile, 
std.format will simply ignore it and not use it while the rest of 
the program compiles successfully.  Any compilation error message 
can be seen by instead attempting to call the method directly, 
e.g. something like `auto a = appender!string; foo.toString(a);`.
I don't use the delegate version personally, but if that's 
already working for you, may as well stick with it.


If you wanted to avoid including a mixin in all of your structs, 
another option is to create a generic templated container struct 
with its own toString:


```d
struct ToStringer(T) {
T t; // Consider T* t
void toString(W)(ref W writer) {
//assert(t !is null);
writer.formattedWrite("%s(\n", T.stringof);
static foreach (idx, field; T.tupleof) {
			writer.formattedWrite("\t%s: %s\n", T.tupleof[idx].stringof, 
t.tupleof[idx]);

}
put(writer, ")");
}
}
auto ToString(T)(ref T t) { // syntactic sugar
return ToStringer!T(t);
}

struct Foo {
int x, y;
string s;
}


void main() {
auto foo = Foo(3, 4, "hello");
//writeln(ToStringer!Foo(foo));
writeln(foo.ToString);
}
```



Re: Checking path name

2023-12-14 Thread cc via Digitalmars-d-learn

On Thursday, 14 December 2023 at 09:38:30 UTC, Joel wrote:

On Thursday, 14 December 2023 at 08:47:49 UTC, Anonymouse wrote:

On Thursday, 14 December 2023 at 03:58:37 UTC, Joel wrote:
https://dlang.org/phobos/std_path.html#isValidPath

https://dlang.org/phobos/std_path.html#.isValidFilename


Oh, forgot about std.path

But what's the difference between path and file name?


File name can't contain path separators.


Re: Safer binary reading (or writing) code

2023-12-13 Thread cc via Digitalmars-d-learn

On Tuesday, 12 December 2023 at 09:43:39 UTC, Joel wrote:
I've got this mixin thing, I think it's less typo-prone. I 
haven't been able to make it show the variable's name, though. 
Also, it should be optional whether it prints anything, (it's 
not hard for me to do that though).


```d
// mixin(jread("width")); -> fread(, 1, width.sizeof, 
bfile);
auto jread(string var) => `fread(&`~var~`, 1, `~var~`.sizeof, 
bfile); writeln("read var=", `~var~`);`;

```


When I need to insert a variable name numerous times into a bit 
of mixin code, I often use a replace pattern like this:

```d
mixin(q{
static struct _aa_$FIELD {
KeyType!(typeof(field)) key;
ValueType!(typeof(field)) val;
}
Array!(_aa_$FIELD) $FIELD;
}.replace("$FIELD", myVariableName));
```


Re: Getting all struct members and values with introspection avoiding string mixins

2023-10-05 Thread cc via Digitalmars-d-learn

On Sunday, 1 May 2016 at 09:42:37 UTC, ParticlePeter wrote:
I am logging arbitrary POD struct types with member names and 
data:


void printStructInfo( T )( T info ) {
  foreach( i, A; typeof( T.tupleof )) {
enum attribName = T.tupleof[i].stringof;
writefln( "%s : %s", attribName, mixin( "info." ~ 
attribName ));

  }
}

Is there is some other way to evaluate info.attribName without 
using string mixins?


Cheers, PP


If you have `T info`, T.tupleof[n] will always match up with 
info.tupleof[n].  You can think of `info.tupleof[n]` as being 
rewritten by the compiler in-place as info.whateverFieldThatIs.  
You might try this version (note the double {{ }} with static 
foreach):

```d
void printStructInfo( T )( T info ) {
static foreach( i, A; info.tupleof ) {{
enum attribName = T.tupleof[i].stringof;
writefln( "%s : %s", attribName, info.tupleof[i] );
}}
}
```

Be advised that T.tupleof and __traits(allMembers, T) return two 
different sets of things.  allMembers will probably get you a lot 
of stuff you don't want and will need to write checks to avoid.  
Using .tupleof is a perfectly acceptable practice.


Re: How to get all modules in a package at CT?

2023-10-05 Thread cc via Digitalmars-d-learn

On Thursday, 5 October 2023 at 20:42:26 UTC, mw wrote:

On Thursday, 5 October 2023 at 20:07:38 UTC, user1234 wrote:

No. Sorry.

Generally compile time code cannot interact with the system. 
To be evaluable at compile time code has to be strongly pure, 
that is not the case of the function you would need.


Otherwise you'd need a new traits for that... but that traits 
would violate the rule explained before.


If you want to iterate the package for modules imported in 
it, I'm not sure. __traits(allMembers, package) will list 
names of imported packages but not which modules.


static reflection on import decls is broken, that wont work 
well


So how about at runtime? I just want the compiler to help to 
list them, instead of doing manually.


At runtime, simply:
```d
foreach (m; ModuleInfo) {
writeln(m.name);
}
```

However, Walter has hinted that he wants to remove ModuleInfo at 
some point.


Re: Cool pattern or tragic?

2023-09-24 Thread cc via Digitalmars-d-learn

On Friday, 25 August 2023 at 21:00:08 UTC, Guillaume Piolat wrote:
The idea is to deliberately mark @system functions that need 
special scrutiny to use, regardless of their memory-safety. 
Function that would typically be named `assumeXXX`.

...
That way, @safe code will still need to manually @trust them.


I basically wanted some kind of functionality similar to this but 
with regards to the GC.  Like some way to annotate a function as 
@WillAllocate or something, and forbid calling it unless the 
caller function explicitly acknowledged the allocation (without 
having to wrap everything in @nogc).  Just for fun I experimented 
with a locking GC that used the struct/dtor model to open/re-lock.




Re: Setting struct as default parameter of a function using struct literal?

2023-09-12 Thread cc via Digitalmars-d-learn

On Monday, 11 September 2023 at 17:51:04 UTC, BoQsc wrote:
I would like to set function's default struct for a function in 
a way that it would be visible for the reader to see what 
options are set. Something like `Options option = 
{silenceErrors: false}`


If the function's defaults will always match the default 
initializers of the struct itself,

```d
struct Options {
bool silenceErrors = false;
}
void someFunction(Options option = Options.init) {
writeln(option);
}
```
else:
```d
struct Options {
bool silenceErrors = false;
}
void someFunction(Options option = Options(silenceErrors: true)) {
writeln(option);
}
```



Re: Which D compiler is the most maintained and future-proof? [DMD GDC and LDC]

2023-07-24 Thread cc via Digitalmars-d-learn
On Monday, 24 July 2023 at 09:29:09 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

There isn't a huge concern with which one you use.

Its quite common to use dmd for development, and ldc for 
release for example.


They all share the same frontend, so they really only differ 
between them by their glue code to the relevant backend and 
some modules in druntime that are optional. Oh and inline 
assembly, although there is some compat code in ldc/gdc for dmd 
style.


If dmd dies, so does ldc/gdc basically. Each one sees active 
development although gdc only has one developer. Ldc keeps up 
with the dmd releases pretty well.


Is there any list of known significant "gotchas" with moving to 
LDC from DMD?  Any unexpected surprises to watch out for or be 
careful for?  I'm thinking of all the "features" of DMD that are 
now considered verboten by many users (e.g. compiling with 
-release, disabling of asserts or array bounds checking, etc).  
Known edge cases of compiler optimization causing different 
behavior between vendors?




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

2023-06-05 Thread cc via Digitalmars-d-learn

On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote:
How do I generate `setX` methods for all private mutable 
variables in my class? Do I need to use `__traits`?


```d
mixin template GenerateSetters() {
	static foreach (idx, field; typeof(this).tupleof) static if 
(__traits(getVisibility,field) == "private") {

mixin(q{
void %SETTER(typeof(this.tupleof[idx]) _) {
%NAME = _;
}
}
.replace("%NAME", field.stringof)
			.replace("%SETTER", "set"~toUpper(field.stringof[0..1]) ~ 
field.stringof[1..$])

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

this(int x, int y) {}

mixin GenerateSetters;
}

void main() {
auto rect = new Rectangle(0, 0);
rect.setStrokeWidth(4);
assert(rect.strokeWidth == 4);
}
```


Re: Idiomatic D using GC as a library writer

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

On Sunday, 4 December 2022 at 09:53:41 UTC, vushu wrote:

What are your thoughts about using GC as a library writer?


If your program runs, does some stuff, and terminates, use the GC.
If your program runs, stays up for a while with user occasionally 
interacting with it, use the GC.
If your program runs, and stays up 24/7 doing things in the 
background, use the GC.


If your program is a game meant to run at 60+fps, and any sudden 
skip or interrupt is unacceptable, no matter how minor (which it 
should be), plan carefully about how to manage your game objects, 
because naive GC instantiation and discarding isn't going to cut 
it.  malloc/free, pre-allocated lists, and other strategies come 
into play here.  In a desperate pinch you can also manually 
`GC.free` your GC-allocated objects but this is not recommended.  
The GC can still be used for allocations that are not likely to 
significantly affect performance every frame (strings, occasional 
user-generated information requests, first-load data 
instantiation, Steam avatars, etc) -- but also be even more 
careful when you start mixing and matching.


I find that @nogc is a bit of a false idol though, even in 
situations where the GC is deliberately being avoided.  It simply 
adds too much pain to trying to make everything compliant, and 
certain things just plain don't work (amazingly, the 
non-allocating form of toString can't be @nogc), so I simply 
avoid it and "be careful" (and/or hook into the GC so I can 
monitor if an unexpected allocation happens).  If you're writing 
code that's going to run on a space shuttle or life support 
system, then yeah you might consider the extra effort, but in my 
use cases it simply fails the cost-benefit analysis.


For any strategy, it's still a good idea to have a good 
understanding of or profile your allocations/deallocations so 
you're not just spending memory haphazardly or generating 
excessive collections.


Re: aa.keys, synchronized and shared

2022-11-10 Thread cc via Digitalmars-d-learn

On Friday, 11 November 2022 at 01:09:54 UTC, torhu wrote:

On Thursday, 10 November 2022 at 21:55:26 UTC, torhu wrote:

I'm trying to make a more thread-safe wrapper for AA's:

```
synchronized final class SyncAA(K, V) ///


I chose to fix this by just using `synchronized (this)` inside 
each method instead, for now. Still interested in cleaner 
solutions, but I guess synchronized/shared is a bit of a rabbit 
hole...


That's about what I ended up with, and just declaring my 
references __gshared.  I don't know what's going on with 
shared/synchronized but it sounds like it's unfinished and people 
can't agree on what they're actually supposed to mean.  
__gshared, it just works.
Previous thread: [synchronized/shared associative array .require 
error](https://forum.dlang.org/post/hcbrgpmdufjgjtxtu...@forum.dlang.org)
Also: [synchronized - shared but actually 
useful](https://forum.dlang.org/thread/drrlgymevccozrqms...@forum.dlang.org)


```d
class SyncTable(KEY, VAL) {
private VAL[KEY] table;
auto opIndexAssign(VAL value, KEY key) {
synchronized(this) {
return table[key] = value;
}
}
int opApply(int delegate(ref KEY, ref VAL) dg) {
synchronized(this) {
foreach (key, val; table) {
if (dg(key, val)) return 1;
}
return 0;
}
}
auto opBinaryRight(string op)(KEY key) if (op == "in") {
synchronized(this) {
return key in table;
}
}
auto opDispatch(string s, SA...)(SA sargs) {
synchronized(this) {
static if (SA.length == 0) {
mixin(format("return table.%s;", s));
} else {
mixin(format("return table.%s(%s);", s, sargs.stringof[6 .. 
$-1])); // tuple(_param_0)

}
}
}
}
```

With synchronized on the class, I had to do something like:
```d
synchronized class SyncTable(KEY, VAL) {
// Anything that mutates must reassign unshared back to table!
auto opIndexAssign(VAL value, KEY key) {
auto unshared = cast(T) table;
unshared[key] = value;
table = cast(shared) unshared;
return value;
}
auto require(KEY key) {
auto unshared = cast(T) table;
auto r = unshared.require(key);
table = cast(shared) unshared;
return r;
}
/* ... */
}
```
and it just doesn't feel right.

For mutexes without synchronized, there's also:
```d
struct Lock {
private shared Mutex _mtx;
this(shared Mutex mtx) {
_mtx = mtx;
_mtx.lock();
}
this(this) @disable;
~this() {
if (_mtx)
_mtx.unlock();
_mtx = null;
}
}
class SyncTable(KEY, VAL) {
private VAL[KEY] table;
shared Mutex mtx;
this() {
mtx = new shared Mutex;
}
auto opIndexAssign(VAL value, KEY key) {
auto lock = Lock(mtx);
return table[key] = value;
}
/* ... */
}
```



DConf '22: No-Allocated 0-terminated path strings

2022-10-21 Thread cc via Digitalmars-d-learn
Catching up on the DConf '22 videos, really enjoyed the tricks 
Walter presents here for no-allocation strings:


[DConf '22: Strawberries and Cream aka Delightful Emergent 
Properties of D -- Walter 
Bright](https://www.youtube.com/watch?v=iuP-AWUyjp8)


In the Q segment, the first question asked whether the filename 
in the path example needs memory allocation to be passed to C, 
and is told it does, however the two methods presented can be 
easily combined to provide no-allocation 0-terminated strings 
from `chain()`ed paths by passing an `InputRange` rather than a 
`const(char)` to `toCStringThen`:


```d
//version=AllowMalloc;
auto toCStringThen(alias dg, Range)(Range src) /*nothrow*/ if 
(isInputRange!Range && !isInfinite!Range) {

const len = src.walkLength;
char[512] small = void;
version(AllowMalloc) {
import dmd.common.string : SmallBuffer;
auto sb = SmallBuffer!char(len + 1, small[]);
scope ptr = sb[];
} else {
		enforce(len < small.length, format!"C string buffer overflow 
(%s >= %s)"(len, small.length));

scope ptr = small[];
}
size_t i = 0;
foreach (char c; src)
ptr[i++] = c;
ptr[len] = '\0';
return dg(ptr);
}
void main() {
string path = "include/";
string name = "file";
string ext = ".ext";

auto filename = chain(path, name, ext);
filename.writeln;
filename.byChar.toCStringThen!(
(str) => printf("printf: {%s}\n", str.ptr)
);
}
```
May need to be cleaned up for character types and needs to 
iterate twice if allocations are going to be allowed, and 
walkLength/chain()'s range functions aren't nothrow as far as I 
can tell.  But otherwise thought this was kind of neat, just 
posting it here in case anyone else finds it handy.


Does the GC prioritize same-class when looking for things to free?

2022-09-15 Thread cc via Digitalmars-d-learn
Why is Foo never deallocated here? (`DMD32 D Compiler 
v2.099.0-dirty` win64)

```d
class Foo {
string s;
static size_t count, alloced, dealloced;
this() {
"+Foo".writeln;
count++;
alloced++;
}
~this() {
"~Foo".writeln;
count--;
dealloced++;
}
}
class Bar {
string s;
static size_t count, alloced, dealloced;
this() { count++; alloced++; }
~this() { count--; dealloced++; }
}
void main() {
	static assert(__traits(classInstanceSize, Foo) == 
__traits(classInstanceSize, Bar));


GC.collect();
writeln(GC.stats.usedSize, " START");
{
new Foo;
}
foreach (i; 0 .. 4_000_000) {
new Bar;
if (Foo.dealloced)
break;
}
writeln(GC.stats.usedSize);

writeln("Foo: ", Foo.count);
	writefln("Bar: %,d (%,d - %,d)", Bar.count, Bar.alloced, 
Bar.dealloced);


GC.collect();
GC.minimize();
writeln(GC.stats.usedSize, " END");
```

```
0 START
+Foo
89632
Foo: 1
Bar: 2,800 (4,000,000 - 3,997,200)
64 END
~Foo
```


Re: synchronized/shared associative array .require error

2022-09-04 Thread cc via Digitalmars-d-learn
On Saturday, 3 September 2022 at 14:37:16 UTC, Steven 
Schveighoffer wrote:

On 9/2/22 3:15 PM, cc wrote:

Tried casting away shared as a workaround but I assume that 
will cause some kind of TLS catastrophe.




I think it will be fine, but you may have an issue. You are 
returning a non-shared `VAL`, but your class is `shared`, which 
means `table`, and all the `VAL` and `KEY` inside must also be 
`shared`.


If you cast away `shared` you have to put it back upon return.

TLS should not be involved here at all, so there is no problem 
there.


-Steve


Alright, so this is safe then?
```d
alias VAL[KEY] T;
auto require(KEY key) {
auto unsharedT = cast(T) table;
auto r = unsharedT.require(key);
table = cast(shared) unsharedT;
return cast(shared) r;
}
```
Was a bit surprised to see mutating `unsharedT` left `table` 
unchanged and needed reassigning.


synchronized/shared associative array .require error

2022-09-02 Thread cc via Digitalmars-d-learn

```d
synchronized class SyncTable(KEY, VAL) {
private VAL[KEY] table;
auto require(KEY key) {
return table.require(key);
}
}

auto table = new shared SyncTable!(string, string);
table.require("abc");
```

Fails to compile:
```
// Error: none of the overloads of template `object.require` are 
callable using argument types `!()(shared(string[string]), 
string)`

```

Tried casting away shared as a workaround but I assume that will 
cause some kind of TLS catastrophe.




Re: How to call a function from a dll created with d ?

2022-07-07 Thread cc via Digitalmars-d-learn

On Sunday, 3 July 2022 at 09:43:20 UTC, frame wrote:

app.d:
```d
module app;
import dimedll;

import std.stdio;
import std.stdio : log = writeln;

pragma(lib, "dimedll.lib");

void main() {   
   log("Lets build our own ime");
   testFunc();  
}
```

You should be able to change contents in the DLL and run the 
executable wihtout re-compiling (the library file should be 
round ~2kB).


PS: ddemangle just waits for your input. You copy in the 
mangled symbol like `__D7dimedll12__ModuleInfoZ` and press 
enter ;-)


Does importing dimedll into app.d properly NOT link in the 
functions that are exported to the DLL?  When I tried something 
similar with dmd, I had to create a .di file containing just 
stubs, otherwise it looked like it was ignoring the DLL and 
compiling in an additional copy of each fuction.


getSymbolsByUDA in constructor/member functions

2022-06-15 Thread cc via Digitalmars-d-learn

```d
import std.traits;
class XML {}

class Def {
@XML {
int x;
int y;
}
int z;

this() {
static foreach (sym; getSymbolsByUDA!(Def, XML)) {
}
}
}

void main() {
auto def = new Def;
}
```
```
test.d(12): Error: value of `this` is not known at compile time
test.d(12): Error: value of `this` is not known at compile time
```

Why doesn't this work?  There is nothing in the foreach body.

```d
alias ALL = getSymbolsByUDA!(Def, XML);
pragma(msg, ALL.stringof);
```
reports `tuple(this.x, this.y)`.  Why is `this.` added?


Re: How to call destroy() in @nogc?

2022-05-24 Thread cc via Digitalmars-d-learn

On Tuesday, 24 May 2022 at 02:55:06 UTC, Tejas wrote:

On Tuesday, 24 May 2022 at 02:29:38 UTC, cc wrote:

```d
import core.memory;
import core.stdc.stdlib : malloc, free;
import core.lifetime : emplace;

[...]


FWIW your code will compile if you add `extern(C++)` to `Foo`


Interesting, thanks.  I noticed something similar when trying to 
call malloc in a pure function...


std.internal.memory:
```d
extern (C) @nogc nothrow pure private
{
pragma(mangle, "malloc") void* fakePureMalloc(size_t) @safe;
pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, 
size_t size) @safe;
pragma(mangle, "realloc") void* fakePureRealloc(return scope 
void* ptr, size_t size) @system;

}
```


How to call destroy() in @nogc?

2022-05-23 Thread cc via Digitalmars-d-learn

```d
import core.memory;
import core.stdc.stdlib : malloc, free;
import core.lifetime : emplace;

T NEW(T, Args...)(auto ref Args args) /*@nogc*/ if (is(T == 
class)) {

enum size = __traits(classInstanceSize, T);
void* mem = malloc(size);
scope(failure) free(mem);
return mem !is null ? emplace!T(mem[0..size], args) : null;
}
void FREE(T)(ref T obj) @nogc if (is(T == class)) {
auto mem = cast(void*) obj;
scope(exit) free(mem);
destroy(obj);
obj = null;
}

class Foo {
~this() @nogc {}
}

void main() {
auto foo = NEW!Foo;
FREE(foo);
}
```
```
Error: `@nogc` function `nogctest.FREE!(Foo).FREE` cannot call 
non-@nogc function `object.destroy!(true, Foo).destroy`

```

Is this not currently possible?  Found this thread:
https://forum.dlang.org/thread/zanuuhzmqxljadcex...@forum.dlang.org?page=1
is it still unresolved?


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

2022-05-17 Thread cc via Digitalmars-d-learn

On Monday, 16 May 2022 at 15:08:15 UTC, H. S. Teoh wrote:
If you find yourself having to cast to/from immutable, you're 
using it wrong.


I clearly was, which is why I'm not using it anymore.
The question was "What are you stuck at? What was the most 
difficult features to understand? etc.", so I listed the things 
that tripped me up in my early time with D.  I assumed the 
context of this was collecting useful information for, say, 
understanding what newcomers' sticking points are and maybe 
thinking how to make D more accessible to them.  Maybe this 
wasn't the intent, but this kind of comes across more as a 
lecture on how everything I was doing wrong is my own fault even 
when I've already stated I'm *not doing those things anymore*.


I write D programs that process input files all the time, 
including stuffing data into AAs and what-not, and it Just 
Works(tm).


Of course it just works, why wouldn't it?


But not once did I bother with immutable (why should I?).


Because the documentation crams it down your throat.  Or at least 
it did, along with the early blog/wiki posts that were the only 
source of D information I could find back at the time.  And yes, 
I pored over that page on the differences between const and 
immutable years ago, which sang immutable's praises at length, 
how it was D's greatest innovation to set it apart from C++, and 
implied it should be slapped on literally everything that never 
changes and how great this was for multithreading, hence why I 
(formerly) felt the need to try and define all my persistent 
definitions as immutable.  Now I slap __gshared on everything and 
just let it go.


For anything performance-related, I don't even look at dmd, I 
use LDC all the way. DMD is only useful for fast 
compile-run-debug cycle, I don't even look at performance 
numbers for DMD-produced executables, it doesn't mean anything 
to me.


According to the dlang.org wiki entry for LDC:

druntime/Phobos support is most likely lacking (and probably 
requires a new version predefined by the compiler).


So I'm not touching it for now.  Don't have time to investigate a 
completely new compiler and track down incompatibilities when DMD 
works and I've been invested in it.  The fact that LDC is more 
performant than DMD surely not does imply attempting to optimize 
DMD-compiled programs is futile.  My use of immutable was based 
in part on a (mistaken) assumption that this was a recommended 
best practice for multithreading safety and performance.


Just make things private and use getters/setters to control 
access. Like I said, if you find yourself writing lots of casts


Equally irritating.  Direct access is far less annoying to write. 
 Yes, I could use mixins to automate some of this but it still 
uglifies the code even more to no great advantage for my 
purposes.  Getters/setters have always felt relevant only to 
large team environments, when you can't count on another 
developer knowing certain things aren't meant to be touched.  For 
simple self-protection, I like C#'s "readonly" keyword, as I 
said.  Statement of opinion.  I wish D had something similarly 
painless to use, but it doesn't, so I'm out of luck.  I just 
direct access and try to not make mistakes instead.



Why would you want to force deterministic memory management onto
GC-allocated objects?  Just use malloc/free (or whatever else


Because when I first got into D this was *not made clear*.  The 
GC was sold so heavily and every single non-GC approach to memory 
management was made to look like, at best, a crude circumvention, 
and at worst a pariah.  In C++ I could new/delete, in ObjC I had 
alloc/autorelease, D had new, and also delete at the time, which 
was not adequately explained that it pretty much did nothing, and 
even then it (and its hacky replacement __delete) were bugged 
anyway.  Perhaps this was my own ignorance, fair enough.  NOW I 
already use malloc/free for everything important.  But is this 
helpful to future newcomers?  Wait till they screw up, don't 
understand why, then tell them after the fact they were doing it 
wrong, if they're still around by that point?  To this day, as 
your post demonstrates, the GC is still extolled as the correct 
solution to 99% of problems, with alternatives only grudgingly 
admitted to after a person reports running into problems.


On top of this, at the time I got into D, the GC just plain 
DIDN'T work for arbitrary chunks of data unless you carefully 
zeroed them out.  I could easily write trivial programs to read a 
binary file's raw data into an array of ubyte[], let it go out of 
scope without any escaped pointers, and crash with out of memory 
as the loop cheerfully ate up 8+ GB.  The move to 64-bit and 
whatever bugfixes may have happened in the past years helped and 
fortunately everything "Just Works" NOW.  But back then, it 
didn't.  So when on top of this my programs started having 
disastrous performance issues due to GC collections because the 

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

2022-05-15 Thread cc via Digitalmars-d-learn

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


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


Ali


Immutability.  Ended up having to do so many hundreds of casts to 
and from immutable(whatever) the amount of mental strain greatly 
exceeded whatever benefits the entire concept is supposed to 
offer.  Safety?  Performance, in a future compiler version?  I 
don't know where it's at right now.  But you'd think I could do 
something like load some data from disk, craft a few objects, 
mark them as immutable, and shove them in an array or associative 
array without it being a nightmare, but it isn't.  Or, having an 
otherwise mutable class with a member that references an 
immutable class, but can change which immutable instance it's 
referencing, without having to cast away the immutability of the 
thing I'm trying to protect in the first place.  So I just 
stopped doing it, and simply rely on the "just don't make 
mistakes" practice to avoid writing to things that shouldn't be 
written to now.


C#'s concept of marking a class member as "readonly" feels a lot 
more like what I was hoping to get.  It doesn't complain at me 
when I return something that's readonly and the receiving 
destination isn't expecting it to be readonly, and also I have 
more free reign over what I can do to it during the constructor 
phase before it becomes hands-off.  Things look a lot cleaner 
without another set of parentheses around every variable too.


On another topic, the lack of a good "delete" keyword doing what 
one would expect, when there's a perfectly good "new" without its 
matching existential companion.  This, and the ways around it, 
have already been discussed to death though, but banging my head 
over trying to force deterministic memory management into the 
GC-controlled D universe did take its toll on a good year or two 
of productivity.


Re: How to use destroy and free.

2022-05-04 Thread cc via Digitalmars-d-learn
The MemUtils package offers a `ScopedPool` utility that seems 
interesting.  It isn't well documented however so I have no idea 
if it actually works like I expect.  I presume this would work 
something akin to a VM memory snapshot/rollback for the GC?  It 
would be pretty handy for some scenarios, say a serialization 
library.  You specify a snapshot point (add a pool to the 
stack?), incur all your GC allocations necessary for generating 
the structure of your serialized data (which go into the pool 
instead of the GC proper?), then you write it to disk and pop the 
stack, effectively rolling back to the original memory state of 
your program's GC.  As long as you make sure not to leak anything 
allocated within that phase, seems like a good deal.


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


Re: How to use destroy and free.

2022-05-04 Thread cc via Digitalmars-d-learn

On Wednesday, 4 May 2022 at 05:37:49 UTC, forkit wrote:

inscope int[] i = new int[1];


You often see the "here's an array of ints that exists only in 
one scope to do one thing, should we leave it floating in memory 
or destroy it immediately?" as examples for these GC discussions. 
 Not to steal OP's thread and whatever particular needs he's 
trying to achive, but hopefully provide another use case: I write 
games, and performance is the number one priority, and I stumbled 
heavily with the GC when I first began writing them in D.  
Naively, I began writing the same types of engines I always did, 
and probably thinking with a C/C++ mentality of "just delete 
anything you create", with a game loop that involved potentially 
hundreds of entities coming into existence or being destroyed 
every frame, in >=60 frame per second applications.  The results 
were predictably disastrous, with collections running every 
couple seconds, causing noticeable stutters in the performance 
and disruptions of the game timing.  It might have been my fault, 
but it really, really turned me off from the GC completely for a 
good long while.


I don't know what types of programs the majority of the D 
community writes.  My perception, probably biased, was that D's 
documentation, tours, and blogs leaned heavily towards "run once, 
do a thing, and quit" applications that have no problem leaving 
every single thing up to the GC, and this wasn't necessarily a 
good fit for programs that run for hours at a time and are 
constantly changing state.  Notably, an early wiki post people 
with GC issues were directed to revolved heavily around tweaks 
and suggestions to work within the GC, with the malloc approach 
treated as a last-resort afterthought.


Pre-allocating lists wasn't a good option as I didn't want to set 
an upper limit on the number of potential entities.  The 
emergency fix at the time was inserting GC.free to forcibly 
deallocate things.  Ultimately, the obvious *correct* answer is 
just using the malloc/emplace/free combo, but I'm just 
disappointed with how ugly and hacky this looks, at least until 
they've been wrapped in some nice NEW()/DELETE() templates.

```d
auto foo = new Foo;
delete foo; // R.I.P.
```
```d
import core.stdc.stdlib : malloc, free;
import core.lifetime : emplace;
auto foo = cast(Foo) malloc(__traits(classInstanceSize, Foo));
emplace!Foo(foo);
destroy(foo);
free(cast(void*) foo);
```
Can you honestly say the second one looks as clean and proper as 
the first?  Maybe it's a purely cosmetic quibble, but one feels 
like I'm using the language correctly (I'm not!), and the other 
feels like I'm breaking it (I'm not!).


I still use the GC for simple niceties like computations and 
searches that don't occur every frame, though even then I've 
started leaning more towards std.container.array and similar 
solutions; additionally, if something IS going to stay in memory 
forever (once-loaded data files, etc), why put it in the GC at 
all, if that's just going to increase the area that needs to be 
scanned when a collection finally does occur?


I'd like to experiment more with reference counting in the 
future, but since it's just kind of a "cool trick" in D currently 
involving wrapping references in structs, there are some hangups. 
 Consider for example:

```d
import std.container.array;
struct RC(T : Object) {
T obj;
// insert postblit and refcounting magic here
}
class Farm {
Array!(RC!Animal) animals;
}
class Animal {
	RC!Farm myFarm; // Error: struct `test.RC(T : Object)` recursive 
template expansion

}
```
Logically, this can lead to leaked memory, as a Farm and Animal 
that both reference each other going out of scope simultaneously 
would never get deallocated.  But, something like this ought to 
at least *compile* (it doesn't), and leave it up to the 
programmer to handle logical leak problems, or so my thinking 
goes at least.  I also really hate having to prepend RC! or 
RefCounted! to *everything*, unless I wrap it all in prettier 
aliases.




Re: How to get compatible symbol names and runtime typeid names for templated classes?

2022-05-03 Thread cc via Digitalmars-d-learn

On Tuesday, 3 May 2022 at 17:05:09 UTC, H. S. Teoh wrote:
Oops, sorry, I made a mistake. The definition of Serializable 
should be:


class Serializable(Base, Derived = Object) : Base {}


There we go, works with this, now I get what it's trying to do:
```d
class Serializable(Base, Derived = Object) : Derived {
```

What's the purpose of the `static struct Proxy`?  The `static 
this()` seems to work without being enclosed in a structure.


Re: How to get compatible symbol names and runtime typeid names for templated classes?

2022-05-03 Thread cc via Digitalmars-d-learn

On Tuesday, 3 May 2022 at 16:51:33 UTC, H. S. Teoh wrote:
On Tue, May 03, 2022 at 04:38:23PM +, cc via 
Digitalmars-d-learn wrote:

On Tuesday, 3 May 2022 at 15:08:53 UTC, H. S. Teoh wrote:
>class Base : Serializable!(Base) { ... }
>class Derived : Serializable!(Base, Derived) { ... }

This is really interesting syntax, I'm surprised that works!


https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

It's a bit counterintuitive at first, but once you "get" how it 
works, it's an extremely powerful technique for leveraging D's 
compile-time introspection capabilities. And translating 
compile-time information into runtime using static this(). ;-)



T


Hm although I am having trouble with that particular 
implementation:

```d
class Base : Serializable!(Base) {}
class Derived : Serializable!(Base, Derived) {}
class Serializable(Base, Derived = Base) : Base {}
```
```
Error: class `test.Base` circular inheritance
Error: template instance `test.Serializable!(Base, Base)` error 
instantiating

```


Re: How to get compatible symbol names and runtime typeid names for templated classes?

2022-05-03 Thread cc via Digitalmars-d-learn

On Tuesday, 3 May 2022 at 15:08:53 UTC, H. S. Teoh wrote:

class Base : Serializable!(Base) { ... }
class Derived : Serializable!(Base, Derived) { ... }


This is really interesting syntax, I'm surprised that works!


Re: How to get compatible symbol names and runtime typeid names for templated classes?

2022-05-03 Thread cc via Digitalmars-d-learn

On Tuesday, 3 May 2022 at 10:48:53 UTC, bauss wrote:
Object.factory calls TypeInfo_Class.find which just loops 
through ModuleInfo and then looks if any of the entries in 
localClasses has a name that matches.


Afterwards it calls the create function on the TypeInfo_Class 
which of course isn't "generic" by any means.


This is where compile-time has its limits compared to runtime 
type creation, because templates only live during compile-time 
then it isn't really that easy to do something like this, where 
it would be trivial in other languages like C#.


On Tuesday, 3 May 2022 at 12:46:56 UTC, Adam D Ruppe wrote:

On Tuesday, 3 May 2022 at 09:42:45 UTC, cc wrote:

something I can pass to `Object.factory`.


Object.factory is useless and will hopefully be removed someday.

Instead, make your own factory registration function.

Put a static constructor in the class which appends a factory 
delegate to an array or something you can use later. Then you 
can use your own thing to construct registered objects.


Yeah, that's unfortunate.  Actually I was already doing something 
similar for serialization/encoding to get the true type of an 
object (making sure `Animal an = new Cat();` encodes a Cat and 
not an Animal), took me a second to put two and two together and 
realize I could just instantiate objects via new that way instead 
of calling Object.factory.


At the moment I try to register as many relevant symbols as I can 
automatically when encoding is called for a given object, such as:

```d
private mixin template RegisterModule(alias MOD) {
void RegisterModule() {
static foreach (SYM; getSymbolsByUDA!(MOD, Coder)) {
static if (is(SYM == class)) {
RegisterSerializer!SYM();
}
}
}
}
private static void[0][string] registeredModules;

private void registerModules(T)() {
enum string MODULENAME = moduleName!T;
if (MODULENAME !in registeredModules) {
registeredModules.require(MODULENAME);
mixin("import "~MODULENAME~";");
mixin("mixin RegisterModule!"~MODULENAME~";");
RegisterModule();
}
}
IPtr encode(T)(T obj) {
registerModules!T;
...
}
```

I'll have to get a little more creative for registering templated 
classes then, something like this works:

```d
static void RegisterSerializer(alias SYM)(string runtimeName = 
null) {

enum sym = fullyQualifiedName!SYM;
if (sym !in serialTypes) {
auto st = new SerialType!SYM;
serialTypes[sym] = st;
if (runtimeName.length && runtimeName !in serialTypes)
serialTypes[runtimeName] = st;
}
}
static void RegisterSerializer(T : Object)(T obj) {
RegisterSerializer!T(typeid(obj).name);
}
```
but I'd rather not have to instantiate an actual object just to 
get its typeid().name, I suppose I can just manually construct it 
from the fullyQualifiedName inserting the parenthesis and 
appended portion so it matches.




Re: How to get compatible symbol names and runtime typeid names for templated classes?

2022-05-03 Thread cc via Digitalmars-d-learn

On Tuesday, 3 May 2022 at 09:42:45 UTC, cc wrote:
Given a runtime typeid, how can I get the equivalent 
fullyQualifiedName without attempting to mangle the string 
myself manually?  e.g. something I can pass to `Object.factory`.


Actually, looking at this further, does Object.factory even 
support templates?  I'm getting null returned from any attempt to 
instantiate a templated classname.


How to get compatible symbol names and runtime typeid names for templated classes?

2022-05-03 Thread cc via Digitalmars-d-learn

This produces compatible strings between symbol and runtime type:
```d
class Foo {}
void main() {
alias Foo F;
writeln(fullyQualifiedName!F);
auto f = new F;
writeln(typeid(f).name);
}
```
```
test.Foo
test.Foo
```

But if the class is a template, the strings different:
```d
class Foo(bool b) {}
void main() {
alias Foo!true F;
writeln(fullyQualifiedName!F);
auto f = new F;
writeln(typeid(f).name);
}
```
```
test.Foo!(true)
test.Foo!true.Foo
```

Given a runtime typeid, how can I get the equivalent 
fullyQualifiedName without attempting to mangle the string myself 
manually?  e.g. something I can pass to `Object.factory`.


Re: Reference counting example

2022-04-26 Thread cc via Digitalmars-d-learn

On Tuesday, 26 April 2022 at 22:16:01 UTC, cc wrote:

Test application:


I should point out that all this stuff with saving refcounted 
things to arrays and so on is extremely untested and experimental


One problem I'm seeing is the inability for a refcounted class to 
pass itself to another function, since the class internals don't 
see the struct wrapper.. you can pass the naked object reference 
itself, and hope the reference doesn't get saved otherwise 
there's your dangling pointer, but then you also have the problem 
of inconsistent method declarations, with some things taking Foo 
and others taking RefCounted!Foo etc...


Every night I pray for a `refcounted` keyword.  Wouldn't 
something like `auto foo = new refcount Foo();` be nice?  Then 
every class that deals with the objects could continue to be 
allocator-agnostic... definitely not a trivial change though.


Re: A template construct like using()

2022-04-26 Thread cc via Digitalmars-d-learn

On Tuesday, 26 April 2022 at 21:33:43 UTC, Chris Katko wrote:
I swear I asked something like this before years ago but it 
doesn't show up in my previous forum posts.


I'm looking for a construct that mimics using(var)/with(var)


```d
void draw_with(bitmap* drawb, void delegate() dg) {
set_target_bitmap(drawb);
dg();
set_target_bitmap(original_target);
}

bitmap* b;
draw_with(b, {
draw_pixel(red, 16, 16);
});
```

If your draw code doesn't depend on any scoped state you can use 
`function()` instead of `delegate()` to save a GC call.


Re: Reference counting example

2022-04-26 Thread cc via Digitalmars-d-learn

On Tuesday, 26 April 2022 at 06:55:34 UTC, Alain De Vos wrote:
Can someone provide a simple/very simple reference counting or 
refcounted example i can understand. Thanks.


I've been playing around with the automem[1] library's RefCounted 
feature as we speak, it seems to fit my needs more than 
std.typecons which doesn't quite do what I want.  I did have to 
make some changes to the library though to allow for inheritance 
and manually releasing (below).  It's pretty fun so far so I'm 
looking forward to trying it in some other projects like a non-GC 
XML library.

[1] https://github.com/atilaneves/automem

Test application:
```d
import std.stdio;
import core.memory;
import util.array; // ARRAY Custom wrapper for std.container.array
// The vector/array library provided with automem does NOT 
properly destroy array elements

// so we'll use std.container.array instead

import std.experimental.allocator.mallocator;
import automem;

alias RC(T) = RefCounted!(T, Mallocator);
// Optional default constructor workaround
auto RCREATE(T, Args...)(auto ref Args args) {
return RC!T.create(args);
}

class Farm {
ARRAY!(RC!Cow) animals;
//this() {}
this(int) { writeln("[Farm]"); }
~this() {
writeln("[~Farm]");
animals.clear();
writeln("[/Farm]");
}

void pet(RC!Animal animal) {
writefln("Farm: The %s says...", animal);
animal.speak;
}

}
class Animal {
void speak() {
writeln("Animal: ???");
}
}
class Cow : Animal {
	ARRAY!(RC!Animal) friends; // Amazingly, this works, as long as 
the array elem type is NOT the same as RC!(this class)

// otherwise we 
get a forwarding error
int x;
this() { writefln("[Cow]"); }
this(int x) { this.x = x; writefln("[Cow %s]", x); }
~this() { writefln("[/Cow %s]", x); }
override void speak() {
writefln("Cow#%s: Moo.", x);
}
}


void main() {
auto used = GC.stats.usedSize;
	scope(exit) assert(GC.stats.usedSize == used); // GC is not 
touched!

{
assert(RCREATE!Cow.x == 0);
assert(RCREATE!Cow(99).x == 99);
}

RC!Animal other;

auto farm = RC!Farm(1);
{
auto cow = RC!Cow(1);
farm.animals ~= cow;
farm.animals ~= RC!Cow(2);
other = farm.animals[1];
auto cowGoesOutOfScope = RC!Cow(70);
}
writeln("out, should have seen Cow#70's dtor");

farm.animals[0] = farm.animals[1];
	writeln("animals[0] (Cow#1) just got overwritten so we should 
have seen its dtor");


farm.animals ~= RC!Cow(3);

farm.pet(other);
other = null;

farm = null;

writeln("done");
}
```

Output:
```
[Cow]
[/Cow 0]
[Cow 99]
[/Cow 99]
[Farm]
[Cow 1]
[Cow 2]
[Cow 70]
[/Cow 70]
out, should have seen Cow#70's dtor
[/Cow 1]
animals[0] (Cow#1) just got overwritten so we should have seen 
its dtor

[Cow 3]
Farm: The memtest.Cow says...
Cow#2: Moo.
[~Farm]
[/Cow 2]
[/Cow 3]
[/Farm]
done
```


I added the following functions to automem `ref_counted.d`:
```d
// static .create method to allow use of class's default 
constructor if desired
static if (isGlobal && is(Type == class) && 
__traits(compiles, new Type())) {

static auto create(Args...)(auto ref Args args) {
typeof(this) obj;
obj.makeObject!args();
return obj;
}
}

// allow instantiation or assignment from derived classes if 
the Allocator is the same
this(U)(ref RefCounted!(U,Allocator) rhs) if (is(U == class) 
&& !is(U == Type)) {

_impl = cast(typeof(_impl)) rhs._impl;
if(_impl !is null) inc;
}
void opAssign(U : Type)(ref RefCounted!(U,Allocator) other) 
if (is(U == class) && !is(U == Type)) {

//if (_impl == other._impl) return;
if (_impl._rawMemory.ptr == other._impl._rawMemory.ptr) 
return;

if(_impl !is null) release;
static if(!isGlobal)
_allocator = other._allocator;
_impl = cast(typeof(_impl)) other._impl;
if(_impl !is null) inc;
}

// Allow assigning null to manually release payload
void opAssign(typeof(null)) {
if(_impl !is null) release;
_impl = null;
}
```



Re: Assigning to array of structs with custom constructor

2022-04-25 Thread cc via Digitalmars-d-learn

On Monday, 25 April 2022 at 15:23:12 UTC, Ali Çehreli wrote:

  auto arr = iota(10).map!(i => Foo(i.text)).array;


On Monday, 25 April 2022 at 16:11:47 UTC, rassoc wrote:

Foo[] arr = ["abc", "def", "ghi"].map!Foo.array;


Ahh that'll do it alright, thanks


Get UDAs of self's declaration as a member?

2022-04-25 Thread cc via Digitalmars-d-learn
Hard to word this question right, but is it possible to get the 
UDAs assigned to a class/structure's member variable declaration, 
within that variable's definition?  e.g.


```d
import std.stdio;
import std.traits;
enum SPECIAL;
struct Foo {
void foo() {
static if (hasUDA!(typeof(this), SPECIAL))
writeln("special");
else
writeln("not special");
}
}
struct Bar {
@SPECIAL Foo foo;
}

void main() {
Foo foo;
foo.foo;
Bar bar;
bar.foo.foo;
}
```

This doesn't work of course, `@SPECIAL` isn't applied to `struct 
Foo` itself so no UDA is found by `hasUDA!Foo`.  Without 
iterating Bar directly, is there some way to detect *within* 
Foo's member functions, that the Foo being called is declared 
with `@SPECIAL` inside its parent structure?


Re: Linked list, printing looks destructive.

2022-04-25 Thread cc via Digitalmars-d-learn

On Monday, 25 April 2022 at 01:40:01 UTC, Alain De Vod wrote:

Following program is a single linked list.
We expect as output 1 2 3 1 2 3
But the output is only 1 2 3
```


If you don't need List to be treated as a true range, but just 
want to iterate, a simple way to do this is with opApply:

https://tour.dlang.org/tour/en/gems/opdispatch-opapply
```d
import std.stdio: write,writeln;
import std.range: empty,popFront,front;

struct Node {
int element;
Node * next;
}

class List {
Node * root=null;
this(int[] AR){foreach(i ; AR)pushfront(i);}
bool empty() const {return !root;}
/*void popFront() {root=root.next;}
float front() const {return root.element;}*/
void pushfront(int element) {
Node * newnode=new Node();
newnode.element=element;
newnode.next=root;
root=newnode;
}
int opApply(int delegate(typeof(Node.element)) dg) {
Node* current = root;
while (current) {
			if (dg(current.element)) return 1; // stop iteration if the 
foreach body asks to break

current = current.next;
}
return 0;
}
}//List

void main(){
List l=new List([3,2,1]);
foreach(element; l) writeln(element);
foreach(element; l) writeln(element);
}

// 1 2 3 1 2 3
```


Re: Assigning to array of structs with custom constructor

2022-04-25 Thread cc via Digitalmars-d-learn

On Monday, 25 April 2022 at 15:13:51 UTC, Stanislav Blinov wrote:

Make it explicit:

```d
Foo[] foos = [Foo("a")];
```


There's that too, but I still have to iterate manually. e.g.:

```d
string[] ss = loadABunchOfStringsFromSomewhere();
//Foo[] foos = ss; //error
Foo[] foos;
foos.reserve(ss.length);
foreach (s; ss)
foos ~= Foo(s);
```

Was just hoping there was a way to streamline it within the 
struct definition.


Re: Assigning to array of structs with custom constructor

2022-04-25 Thread cc via Digitalmars-d-learn

On Monday, 25 April 2022 at 15:00:13 UTC, Alain De Vos wrote:

Not really an answer but this works,
```
void main(){
Foo foo = "a";
Foo[] foos;
foos ~=foo;
}%
```


Right, I can append individual elements, but can't assign or 
append a slice of a type that can be individually cast to the 
struct.


Assigning to array of structs with custom constructor

2022-04-25 Thread cc via Digitalmars-d-learn

```d
struct Foo {
string s;
this(string s) { this.s = s; }
}
Foo foo = "a";
Foo[] foos = ["a"]; // Error: cannot implicitly convert 
expression `["a"]` of type `string[]` to `Foo[]`
Foo[] foos = cast(Foo[]) ["a"]; // Error: e2ir: cannot cast `"a"` 
of type `string` to type `Foo`

```

Was there a way to do this?  I thought I recalled seeing 
something like this before, but I can't seem to find it.


Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor

2022-04-18 Thread cc via Digitalmars-d-learn

On Monday, 18 April 2022 at 10:26:16 UTC, HuskyNator wrote:
On a sidenote, I'm surprised D did not choose 0 as the default 
floating value. Doesn't almost every language do this? I 
understand the thinking behind it, but when the type one uses 
in a template influences the behavior of the code, that seems 
like a pretty big red flag to me. (Any non-floating type 
defaults to 0, but using floats/doubles suddenly introduces 
NaN, surely I'm not the only one that sees a problem with this 
) Especially when it's basically a standard 0 is used for 
this. Sorry for the rant.


I agree, it's a hiccup.  I have at times intentionally 
initialized a float as NaN so that I can identify later whether 
an appropriate value has been assigned, but I've never seen the 
need to have this be the default behavior when integer types 
always init to 0 (more specifically, init to a MODIFYABLE value). 
 In game design I have tons upon tons of floats that all [should] 
start initialized to zero.  I can add 4 to a declared but 
not-assigned-to int and it'll be 4, a float remains NaN.  Having 
to manually declare appropriate init values to each one doesn't 
aid me in detecting "bugs".  If I had an int that was supposed to 
default to 10 instead of 0 it would still be a bug if I forgot to 
specify that, tripping me up for falsely assuming floats would 
start at 0 doesn't aid my workflow in any way.  The whole "you 
should pay more attention to what you're initializing, o buggy 
programmer you" philosophy seems like something that should be 
reserved for pointers and reference types, not basic numeric 
data.  It's probably set in stone by this point though and too 
late to change.


Ten years ago, almost to the day:
https://forum.dlang.org/thread/thsjtreegdwcgbazh...@forum.dlang.org

The reasoning still feels flimsy and stubborn.


Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor

2022-04-18 Thread cc via Digitalmars-d-learn

On Monday, 18 April 2022 at 03:21:30 UTC, H. S. Teoh wrote:
Structs in D ought to be treated like "glorified ints", as 
Andrei puts it. If you need complex ctors and complex methods, 
that's a sign you should be using a class instead.


Unless you're having a nice quiet get-together with friends, and 
you don't want to invite the GC, the biggest loudest party animal 
on the block.  Phobos's RefCounted seems to stretch the 
definition of "glorified ints"..


Re: Importing version identifiers from another file?

2022-04-17 Thread cc via Digitalmars-d-learn

Another option for this was suggested here:

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

On Wednesday, 12 February 2020 at 09:28:15 UTC, Simen Kjærås 
wrote:

So, you could have a file called 'versions' containing this:

# Setting 'Compress' version
-version=Compress
# Optionally set other versions
#-version=Foo
#-version=Bar

and feed it to dmd like so:

dmd -w -wi -g @versions -main foo.d





Re: Printing a quoted string

2022-03-22 Thread cc via Digitalmars-d-learn

On Tuesday, 22 March 2022 at 07:18:00 UTC, cc wrote:

On Sunday, 20 March 2022 at 09:42:44 UTC, Caten wrote:

Hi, I also need a function to "unquote" string, like this:
```d
assert(unquote(`\n`)=="\n");
```
Is there a way to do that?


I rolled my own for that recently:
```d
string dequote(string str) @safe pure {
if (str.length < 2)
return str;
	if ((str[0] == '"' || str[0] == '\'' || str[0] == '`') && 
str[$-1] == str[0]) {

return str[1 .. $-1];
}
return str;
}
```


Oops, I misread what you were asking for.  Was thinking quotes 
like quotation marks, not backslashes.


Re: Printing a quoted string

2022-03-22 Thread cc via Digitalmars-d-learn

On Sunday, 20 March 2022 at 09:42:44 UTC, Caten wrote:

Hi, I also need a function to "unquote" string, like this:
```d
assert(unquote(`\n`)=="\n");
```
Is there a way to do that?


I rolled my own for that recently:
```d
string dequote(string str) @safe pure {
if (str.length < 2)
return str;
	if ((str[0] == '"' || str[0] == '\'' || str[0] == '`') && 
str[$-1] == str[0]) {

return str[1 .. $-1];
}
return str;
}
```


Determining function template from runtime type: better ideas?

2022-03-22 Thread cc via Digitalmars-d-learn
Sorry for the fairly lengthy post.  I'm wondering if there are 
any suggested good practices in place for calling templated 
functions using the runtime type of an object, e.g. what 
`typeid(object)` returns.

Consider the following situation:
```d
class Person {
string name;
int age;
}
class Boss : Person {
int numEmployees;
}

string serialize(T)(T obj) {
// ... iterate over fields and serialize stuff
return join([FieldNameTuple!T], ",");
}

void main() {
writeln(serialize(new Person)); // name,age
writeln(serialize(new Boss)); // numEmployees
writeln(serialize(cast(Person) new Boss)); // name,age
}
```
Naturally, when an object is instantiated as a `Boss` but the 
variable holding it is type `Person`, the version of the template 
that gets called is `serialize!Person`.  It's especially common 
to run into this if, say, `Person` defined `Person[] friends` and 
that array was populated by various inherited subclasses that 
needed to be recognized (we also need to recursively serialize 
the members of the parent class, but that part's trivial so I'll 
skip it for now).


So, the first basic idea I came up with was using mixins in each 
serializable class:

```d
mixin template Serializable() {
	static if (hasMember!(BaseClassesTuple!(typeof(this))[0], 
"serializeMe")) {

override string serializeMe() {
return serializeTrue(this);
}
} else {
string serializeMe() {
return serializeTrue(this);
}
}
}

class Person {
string name;
int age;
mixin Serializable;
}
class Boss : Person {
int numEmployees;
mixin Serializable;
}

string serialize(T)(T obj) {
return obj.serializeMe();
}
private string serializeTrue(T)(T obj) {
// ...
return join([FieldNameTuple!T], ",");
}

void main() {
writeln(serialize(new Person)); // name,age
writeln(serialize(new Boss)); // numEmployees
writeln(serialize(cast(Person) new Boss)); // numEmployees
}
```
This works, but I kind of don't like using mixins for this for 
some reason.  It feels less obvious that the class itself has 
been identified as something serializable, and you never know 
what additional methods or fields the mixin might be declaring.


I'd prefer to use UDAs, so I came up with something like:
```d
enum Serializable;
@Serializable class Person {
string name;
int age;
}
@Serializable class Boss : Person {
int numEmployees;
}

string serialize(Object obj) {
string runtimeTypeName = typeid(obj).name;
	static foreach (sym; getSymbolsByUDA!(test_serialize, 
Serializable)) {

if (fullyQualifiedName!sym == runtimeTypeName)
return serializeTrue(cast(sym) obj);
}
assert(false, "Unable to serialize type: "~runtimeTypeName);
}
private string serializeTrue(T)(T obj) {
// ...
return join([FieldNameTuple!T], ",");
}

void main() {
writeln(serialize(new Person)); // name,age
writeln(serialize(new Boss)); // numEmployees
writeln(serialize(cast(Person) new Boss)); // numEmployees
}
```
This also works, but it has a problem.  We pass the current 
module directly to `getSymbolsByUDA` (`test_serialize.d`), but if 
we have classes spread across multiple modules, we need some way 
to iterate through those as well.  Unfortunately I couldn't find 
any trait related to iterating through all the modules compiled 
into a project.  Could an `allModules` or such thing be added?  
Or is this non-trivial to the compilation process?


So, I ultimately came up with the following.  It requires some 
instantiation at runtime to create lookup tables between real 
type templates and `typeid` values, and requires a mixin of a 
mixin since I couldn't find a way to get the module of a symbol 
as an alias (no `moduleOf!symbol` trait?), but it seems to get 
the job done (also, I finally went and added the recursive parent 
class serialization):

```d
enum Serializable;
@Serializable class Person {
string name;
int age;
}
@Serializable class Boss : Person {
int numEmployees;
}

mixin template RegisterSerializer(alias MODULE) {
void RegisterSerializer() {
static foreach (SYM; getSymbolsByUDA!(MODULE, Serializable))
static if (is(SYM == class))
serialTypes[fullyQualifiedName!SYM] = new 
SerialType!SYM;
}
}
abstract class SerialTypeBase {
string encodeObject(Object obj);
}
final class SerialType(T) : SerialTypeBase {
override string encodeObject(Object obj) {
return serializeTrue(cast(T) obj);
}
}

void[0][string] registeredModules;
SerialTypeBase[string] serialTypes;

string serialize(T)(T obj) {
enum string MODULENAME = moduleName!T;
if 

opCast in class prevents destroy

2022-02-28 Thread cc via Digitalmars-d-learn

```d
struct A {}
class B {
A opCast(T : A)() {
return A();
}
}
void main() {
auto b = new B();
destroy(b);
}
```
fails with
```
dmd2\windows\bin\..\..\src\druntime\import\object.d(4209): Error: 
template instance `opCast!(void*)` does not match template 
declaration `opCast(T : A)()`
main.d(9): Error: template instance `object.destroy!(true, B)` 
error instantiating

```

Looks like a similar bug has been reported: 
https://issues.dlang.org/show_bug.cgi?id=22635


As a workaround, adding an additional opCast:
```d
class B {
A opCast(T : A)() {
return A();
}
auto opCast(T)() {
return cast(T)super;
}
}
```
SEEMS to work.  Is that safe?  Or are consequences not what I'm 
intending?


Re: Can static variables in methods be local for each object?

2021-07-22 Thread cc via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
Is there a way to make myvar local to each instance of `X` 
without making it a variable of `X`? Just curious.


Sorry if I missed something obvious but is there a specific 
reason why it isn't just a class member variable?

```d
class X {
int myvar = 1234;

int x(int param) {
if (param == 0) return myvar;
else { myvar = param; return myvar; }
}
}
```
??

Why would you need a static variable inside a method but also 
have that static variable unique to each class instance, but not 
stored inside the class?  I could see maybe if the class 
definition were private and you can't change it, in which case 
you could extend it:


```d
class X {
// Someone else's module
}

class MyX : X {
int myvar = 1234;

int x(int param) {
return param ? myvar = param : myvar;
}
}

void main() {
auto x1 = new MyX();
auto x2 = new MyX();

x1.x(0).writeln;
x2.x(0).writeln;

x1.x(17).writeln;
x2.x(0).writeln;
}
```


Re: What exactly gets returned with extern(C) export string func() ?

2021-06-15 Thread cc via Digitalmars-d-learn

On Sunday, 13 June 2021 at 21:13:33 UTC, frame wrote:

On Sunday, 13 June 2021 at 10:02:45 UTC, cc wrote:

it seems to work as expected with the same C# code.  Does D 
explicitly disallow slices as an extern(C) export parameter 
type?


The spec says that there is no equivalent to type[]. You get a 
type* instead.


I can't seem to get it to work as a return type, but 
interestingly it does work as an out/pass by ref parameter.


D:
```d
export void D_testString(out string ret) {
ret = "hello".idup;
}
```

C#:
```c#
public struct DString {
public ulong length;
public IntPtr ptr;
public string str {
get {
byte[] b = new byte[length];
for (int i = 0; i < (int)length; i++) {
b[i] = Marshal.ReadByte(ptr, i);
}
return Encoding.UTF8.GetString(b);
}
}
}
[DllImport("test.dll")]
private static extern void D_testString(out DString dd);
public static string testString() {
DString d;
D_testString(out d);
return d.str;
}
```


What exactly gets returned with extern(C) export string func() ?

2021-06-13 Thread cc via Digitalmars-d-learn
D under dmd/Win10/64-bit currently seems to store strings 
(slices) internally like so:

```d
static struct DString {
size_t length;
immutable(char)* ptr;
}
static assert(DString.sizeof == string.sizeof);
string s = "abcde";
DString d;
memcpy(, , s.sizeof);
assert(d.length == s.length);
assert(d.ptr == s.ptr);
```

If I write a DLL export like:
```d
extern(C) export string someDLLFunc() {
return "hello";
}
```
and import it in C# (VS .NET):
```c#
struct DString {
public long length;
public IntPtr ptr;
}
[DllImport("mydll.dll")]
extern DString someDLLFunc();
...
DString d = someDLLFunc();
System.Console.WriteLine("dstr: {0} : {1}", d.length, d.ptr);
```
Though C# seems to properly be getting 16 bytes as the return 
value from `someDLLFunc()`, the length and ptr parameters are 
both 0.


If I explicitly pass a struct back from D instead like so:
```d
static struct DString {
size_t length;
immutable(char)* ptr;
this(string str) {
length = str.length;
ptr = str.ptr;
}
}
extern(C) export DString someDLLFunc() {
return DString("hello");
}
```
it seems to work as expected with the same C# code.  Does D 
explicitly disallow slices as an extern(C) export parameter type?


Re: cloning array

2021-06-03 Thread cc via Digitalmars-d-learn

On Wednesday, 2 June 2021 at 17:50:13 UTC, Sean wrote:

On Wednesday, 2 June 2021 at 15:32:38 UTC, Sean wrote:
if so, how can I get the behavior i am searching for? Thank 
you.


My current solution, if anyone wonders : 
https://github.com/patefacio/d-help/blob/master/d-help/opmix/dup.d


You may find the `hasIndirections` template from std.traits 
useful.


```d
import std.traits : hasIndirections, ValueType;
import std.range.primitives : ElementType;
int[] a;
int[][] b;
int[string] x;
int[][string] y;
struct S { int s; }
struct T { int[] t; }

assert(!hasIndirections!( ElementType!(typeof(a)) ));
assert( hasIndirections!( ElementType!(typeof(b)) ));
assert(!hasIndirections!( ValueType!(typeof(x)) ));
assert( hasIndirections!( ValueType!(typeof(y)) ));
assert(!hasIndirections!S);
assert( hasIndirections!T);
```


Re: wanting to try a GUI toolkit: needing some advice on which one to choose

2021-06-01 Thread cc via Digitalmars-d-learn
On Tuesday, 1 June 2021 at 20:20:34 UTC, Ola Fosheim Grøstad 
wrote:
Web components are becoming a reality, it essentially means 
that you have code and styling wrapped up as a component, so 
that you can use it by inserting a custom html-tag in your 
code. Given the massive amount of web developers... you'll 
eventually have a crazy amount of components to choose from. 
Just waiting for Safari:


https://caniuse.com/?search=components

I think?


It's 2021 and I'm still waiting for parent selectors.  Even 
:has() isn't implemented by anything yet.


Re: wanting to try a GUI toolkit: needing some advice on which one to choose

2021-05-30 Thread cc via Digitalmars-d-learn
This is overkill for any reasonable application, but I've always 
wanted to design a whole UI framework in OpenGL, just for the 
novelty of it.  I always end up having to reinvent the wheel for 
UI elements in my projects anyway.


https://streamable.com/2uvt4h


Re: How long does the context of a delegate exist?

2021-05-30 Thread cc via Digitalmars-d-learn

On Thursday, 27 May 2021 at 20:46:22 UTC, Adam D. Ruppe wrote:

On Thursday, 27 May 2021 at 20:44:21 UTC, frame wrote:

Did you mean to add the delegate as GC root or the data?


The delegate.ptr property.


Is there any way to enforce at compile time that we're not 
accidentally allocating when creating a delegate, other than 
being carefully aware of what variables are referenced inside the 
body?  Something like:

```d
auto dg = delegate {...}
assert(dg.ptr is null, "Oops, we unintentionally allocated on GC 
here, check delegate body!"); // can't static assert

```



Re: Format

2021-05-21 Thread cc via Digitalmars-d-learn

On Saturday, 22 May 2021 at 03:14:35 UTC, cc wrote:

Oops, disregard this.  I had an error in my imports.
It does in fact work in @safe.


I should add as an aside then that there is an issue of errors 
from the body of a toString template not being displayed, and 
instead the template being silently skipped, e.g.:


```d
@safe void toString(W)(ref W writer) if (isOutputRange!(W, char)) 
{

writer.formattedWrite("FOO:%s", x);
	syntactically correct; // Program will compile without error, 
but this function will now never be called

}
```

I ran into a similar challenge with opDispatch some time ago: 
https://forum.dlang.org/post/axgwhzzawncbpcvqq...@forum.dlang.org
In this case I assume it's some consequence of NOT wanting to 
emit a warning or error for every single class or struct that 
doesn't have a templated toString when the various output writers 
go looking for one.


Something like this can help reveal errors, not sure if there's 
an easier way:

```d
unittest {
struct DebugWriter {
void put(C)(C c) {}
}
DebugWriter wr;
Foo foo;
foo.toString(wr);
}
```
`Error: undefined identifier 'syntactically'`
`Error: template instance 
'amemfailuretest.Foo.toString!(DebugWriter)' error instantiating`


Re: Format

2021-05-21 Thread cc via Digitalmars-d-learn

On Saturday, 22 May 2021 at 03:07:10 UTC, cc wrote:
Ahh, in that case it would appear formattedWrite isn't @safe at 
all.  Looks like you have to stick with put()?

```d
@safe void toString(W)(ref W writer) if (isOutputRange!(W, 
char)) {

//writer.formattedWrite!("FOO:%s", x); // fails
import std.conv;
put(writer, "FOO:");
put(writer, x.to!string);
}
```


Oops, disregard this.  I had an error in my imports.
It does in fact work in @safe.


Re: Format

2021-05-21 Thread cc via Digitalmars-d-learn

On Friday, 21 May 2021 at 16:53:48 UTC, drug wrote:

21.05.2021 18:28, cc пишет:

On Friday, 21 May 2021 at 14:19:03 UTC, newbie wrote:

Thank you, and formatValue?


formattedWrite should handle this.

```d
@safe struct Foo {
 int x = 3;
 void toString(W)(ref W writer) if (isOutputRange!(W, 
char)) {

     writer.formattedWrite("Foo(%s)", x);
 }
}
Foo foo;
writeln(foo);
```

Oddly enough this form of toString works from @safe code even 
if it's not marked @safe, or even marked @system...


I guess that because it is a template so the compiler is able 
to deduce its attributes. What about the case when it is marked 
@system - in this case compiler ignore that method due to the 
fact that it is @system and generate the default one. Because 
your implementation of the method is equal to the default 
implementation you didn't see the difference but it exists. Try 
to make your implementation of `toString` different and you'll 
see.


Ahh, in that case it would appear formattedWrite isn't @safe at 
all.  Looks like you have to stick with put()?

```d
@safe void toString(W)(ref W writer) if (isOutputRange!(W, char)) 
{

//writer.formattedWrite!("FOO:%s", x); // fails
import std.conv;
put(writer, "FOO:");
put(writer, x.to!string);
}
```


Re: Format

2021-05-21 Thread cc via Digitalmars-d-learn

On Friday, 21 May 2021 at 14:19:03 UTC, newbie wrote:

Thank you, and formatValue?


formattedWrite should handle this.

```d
@safe struct Foo {
int x = 3;
void toString(W)(ref W writer) if (isOutputRange!(W, char)) {
writer.formattedWrite("Foo(%s)", x);
}
}
Foo foo;
writeln(foo);
```

Oddly enough this form of toString works from @safe code even if 
it's not marked @safe, or even marked @system...


Re: struct destructor

2021-05-16 Thread cc via Digitalmars-d-learn

On Saturday, 15 May 2021 at 18:24:19 UTC, Alain De Vos wrote:

Thanks, good idea but,
It does not initiate a GC cycle or free any GC memory.


Personally I wish D would re-implement "delete" and make it "just 
work" like one would assume, but from what I've seen there have 
been many many debates on that and it isn't going to happen.  If 
the goal is to absolutely squeeze the GC back down after using 
new or dynamic arrays, I find destroy + GC.free often fails to do 
the trick (e.g. GC.stats.usedSize remains high).  For whatever 
reason (I glanced at the code but haven't found the magic yet), 
the deprecated __delete does a more thorough job of making sure 
that memory actually gets "given up" on a collection cycle 
(particularly if you invoke it manually with `GC.collect(); 
GC.minimize();`.  Presumably this isn't a desirable coding 
behavior, though.  In my field (games), I do do something like 
this after initially loading the data to free up all the unused 
clutter and scaffolding, but it's very slow to call it every 
frame if you've been using the GC to create and delete game 
entities.  So like Adam says, standard C malloc/free are probably 
the best way to go in this case.

```d
import core.stdc.stdlib;
import core.lifetime;
class Foo {}
auto foo = cast(Foo) malloc(__traits(classInstanceSize, Foo));
emplace!Foo(foo, /*constructor args*/);
// ...
destroy(foo);
free(cast(void*)foo);
```

Another alternative is something like the memutils library:
https://code.dlang.org/packages/memutils
```d
class Foo {}
auto foo = ThreadMem.alloc!Foo(/*constructor args*/)
ThreadMem.free(foo); // calls destroy for you, but can still 
destroy manually

```
You'll still need to be very careful about any GC mem that gets 
allocated within a class like this as it can get lost into the 
ether and cause permanent bloat.


I've been doing a lot of iteration tests lately across a whole 
bunch of different memory management solutions and the state of 
discrete memory management in D for gaming applications is.. not 
great.  I love D, but for all that it's designed to help reduce 
programmer error, it goes the opposite way once you start 
breaking free of the GC and having to be extra careful tiptoeing 
around its edges.  Unfortunately I don't like doing the pure 
@nogc/betterC route either, the GC is still really handy to have 
when you need it (and are aware that it's being used!), but GC 
collections during high intensity gaming are unacceptable (and 
deferring them to some later point doesn't help much either).


Fair warning, I'm not one of the D elite with a deep guru-level 
knowledge of just precisely how everything is operating under the 
hood, so part of this may come down to learning better practices, 
but a problem I see IMO is a perceived lack of support or 
sympathy for coders who want to use the GC when it's nice, but 
not have it smack them in the face when it isn't.  Even with the 
various articles and forum threads explaining D's memory options, 
there's still a general air of "You really should just be using 
the GC, so enjoy your no-man's land, you're on your own."  
Whether this is only an unfair perception and matter of 
documentation, or something that actually needs to be addressed 
in the language, is beyond simply me to decide, but I think a lot 
of outsiders coming into D may run into the same situation.


What is the difference between these template declaration forms?

2021-05-15 Thread cc via Digitalmars-d-learn
Are these identical?  Or is there a different usage for the (T : 
something) form?

```d
auto opCast(T)() if (is(T == bool)) {
return _obj !is null;
}
```
```d
auto opCast(T : bool)() {
return _obj !is null;
}
```



Re: Learning D

2021-05-14 Thread cc via Digitalmars-d-learn

On Friday, 14 May 2021 at 15:30:06 UTC, Imperatorn wrote:

https://www.amazon.com/Programming-Language-Former-Python-Developers-ebook/dp/B08MD7ZB2X

Anyone read it?


Haven't read it, the title has me at the first five words though.


Re: String "dequote" in phobos?

2021-05-13 Thread cc via Digitalmars-d-learn

On Thursday, 13 May 2021 at 16:40:29 UTC, Imperatorn wrote:

Wouldn't this just this do that? 樂

```d
string dequote(string s)
{
return s[1..$-1];
}
```


The idea would be for situations where it isn't known in advance 
whether the string is quoted, if it is quoted properly, and 
whether there are escaped quotes within the string that need to 
be un-escaped.  Additionally some data sources may handle 
escaping quotes in strings differently (e.g. `\"` vs `""`)


String "dequote" in phobos?

2021-05-13 Thread cc via Digitalmars-d-learn
Does something to dequote (unquote? or what would you call it?) a 
string exist in the standard library?  I didn't see one in 
std.string, just wondering before reinventing the wheel.


Something like:
```d
assert(dequote(`"foo"`) == "foo");
assert(dequote(`'foo'`) == "foo");
assert(dequote(`"foo's"`) == "foo's");
assert(dequote(`'foo "bar"'`) == `foo "bar"`);
assert(dequote(`"fo\"o"`) == `fo"o`);
dequote(`"fo"o"`); // bad quoting, maybe throw an exception here 
or something?

```


Re: Question about property & method access scope.

2021-05-11 Thread cc via Digitalmars-d-learn

On Tuesday, 11 May 2021 at 09:10:02 UTC, Vinod K Chandran wrote:

Hi all,
I am practising D with a win api GUI hobby project.
I have a Window class and it resides in module window.d
My WndProc function resides in another module named 
wnd_proc_module.d

Inside my WndProc, I get the Window class like this.
```d
Window win = cast(Window) (cast(void*) GetWindowLongPtrW(hWnd, 
GWLP_USERDATA)) ;

```
So in many situations, I need to check some boolean properties 
of Window class and call some functions of Window class in 
WndProc.
But I don't want to expose those props and functions to the 
user. So if I make them private, I can't access them inside the 
WndProc function. How do solve this issue. Thanks in advance.


The `package` protection attribute should work here if the 
modules reside in the same package (directory)?


```d
module mywindow.window;
import mywindow.wnd_proc_module.d
class Window {
package int x, y;
}
```

```d
module mywindow.wnd_proc_module.d
import mywindow.window;
class Proc {
Window win;
void doStuff() {
win.x = 3;
}
}
```


Re: OutOfMemoryError in D DLL appending to module-level array

2021-05-02 Thread cc via Digitalmars-d-learn

On Sunday, 2 May 2021 at 02:42:46 UTC, Adam D. Ruppe wrote:

On Sunday, 2 May 2021 at 02:34:41 UTC, cc wrote:
which seems to fix it, but I'm not entirely sure what's going 
on, if this is expected behavior, if that's the correct way to 
handle it, and so on.


Oh I've been working on this the last couple weeks and having a 
hard time reproducing outside the work application. In the work 
app, the GC wasn't scanning the dll's TLS variables and freeing 
them prematurely.


In a sample test program, I used a thing kinda like yours, if a 
dll creates a thread and calls back into the exe you get a 
separate problem of partially initialize data.



D dlls on Windows work in simple cases right now but break down 
in more advanced cases. The good news is there's major fixes 
coming soon - my druntime hack might be coming, gdc is getting 
full dll support very soon from mingw, there's a good chance 
ldc is going to in a release or two as well outside mingw.


But the bad news is none of that is actually out right now, so 
dll + tls variables (which includes the top-level things on 
modules) are potentially buggy among other things like 
duplicated symbols.


You might find some improvement making your variable __gshared 
there.


But if you can do any reduced test case I'd really appreciate 
it. More tests that we can do in public is better!


Cool, thanks for the update.  Setting it as __gshared does seem 
to work.  I put together some test cases here:


https://gitlab.com/-/snippets/2114152

It's got the DLL written in D, and test programs for loading it 
in D, C#, and C++.  I haven't done much .NET interop stuff but it 
seems to work.  I'd welcome any recommendations on how to improve 
the interfaces if there are any, I made a little mixin to create 
C wrappers for the member functions since that seems to be the 
suggested solution for calling class methods.


Re: OutOfMemoryError in D DLL appending to module-level array

2021-05-01 Thread cc via Digitalmars-d-learn

On Sunday, 2 May 2021 at 02:34:41 UTC, cc wrote:

[...]


Just to add, only appending to the array seems to give 
OutOfMemoryErrors.  I can idup strings, call stdc malloc, etc 
just fine.


OutOfMemoryError in D DLL appending to module-level array

2021-05-01 Thread cc via Digitalmars-d-learn
Ordinarily, it seems legal to append to an array that has been 
declared at module level (or as a static class member) that 
hasn't been otherwise initialized, for example:

```d
class Foo {}
private Foo[] cache;
void main() {
auto foo = new Foo();
cache ~= foo;
}
```

However, when building code like this as a DLL, such as:
```d
class Foo {}
private Foo[] cache;
extern(C) export Foo createFoo() {
auto foo = new Foo();
cache ~= foo;
return foo;
}
```
and then calling it from another application (in this case, C#), 
I get `core.exception.OutOfMemoryError@src\core\exception.d(647): 
Memory allocation failed` at the `cache ~= foo;` line.


I was able to get around this by adding:
```d
static this() {
cache.length = 0;
}
```
which seems to fix it, but I'm not entirely sure what's going on, 
if this is expected behavior, if that's the correct way to handle 
it, and so on.  Does it have something to do with the D runtime 
being initialized differently in a DLL versus a statically linked 
program?  I am calling Runtime.initialize() as expected when the 
DLL is attached.


Re: win64 DLL stdout printing after main process completes

2021-04-26 Thread cc via Digitalmars-d-learn

On Monday, 26 April 2021 at 13:44:19 UTC, frame wrote:

On Sunday, 25 April 2021 at 15:01:25 UTC, cc wrote:

Adding a note in case anyone stumbles across this with a 
similar problem:
Adding `stdout.setvbuf(0, _IONBF);` to both the main and DLL 
will cause D to autoflush after every write call without 
requiring a manual flush (which seems to happen quite often 
when running under anything other than a basic Windows command 
prompt).


I cannot reproduce this on Windows 10. It would be just 
interesting to know your compiler version and OS and if you 
have installed any Visual Studio tools or Visual C runtimes, 
thanks.


Win10 64-bit
DMD32 D Compiler v2.096.0-dirty
Sublime Text 3.1.1 Build 3176
Visual Studio 2019 is installed, as well as... quite a few 
runtimes, multiple for  Visual C++ 2005, 2008, 2010, 2012, 2013, 
2015-2019.


The buffering also happens under cygwin shells (I'm not building 
with cygwin, I just like using their bash shell).  If I run a D 
program through the basic cmd.exe, it runs with no stdout 
buffering.  However any other situation (shell, sublime 
build+output capture, etc) buffering somehow gets enabled, unless 
I explicitly disable it in code or wrap the write* functions with 
stdout.flush() wrappers.  This has happened for me for many 
versions of the dmd compiler stretching back years, building both 
32-bit and 64-bit executables.


Re: win64 DLL stdout printing after main process completes

2021-04-25 Thread cc via Digitalmars-d-learn

On Monday, 19 April 2021 at 18:32:15 UTC, Adam D. Ruppe wrote:

On Monday, 19 April 2021 at 18:05:46 UTC, cc wrote:
This seems to work if I flush after every printf or write in 
both main and the dll.  I was under the impression they were 
supposed to share the same IO buffers though, is this not the 
case?


Very little in D dlls right now are shared, so there's 
duplicate buffers and functions in the dll do not necessarily 
affect the exe's copies. It basically works in most cases but 
this can cause some quirks and bugs in some situations.


That makes sense, thanks.

Adding a note in case anyone stumbles across this with a similar 
problem:
Adding `stdout.setvbuf(0, _IONBF);` to both the main and DLL will 
cause D to autoflush after every write call without requiring a 
manual flush (which seems to happen quite often when running 
under anything other than a basic Windows command prompt).


Re: win64 DLL stdout printing after main process completes

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

On Monday, 19 April 2021 at 16:04:28 UTC, Mike Parker wrote:

On Monday, 19 April 2021 at 14:55:03 UTC, cc wrote:



And upon running, the output I receive is:
```
[Main] Start
[Main] x: 5
[Main] Finished
[Main] END
[dll] DLL_PROCESS_ATTACH
[dll] static this for mydll
[dll] MyDLL_Test
[dll] DLL_PROCESS_DETACH
[dll] static ~this for mydll
```

I would expect the first three lines of dll output to precede 
the "[Main] x:" line at least.  Is there something I'm doing 
wrong?  Do I need to somehow pass a reference to the main 
stdio to the DLL's D runtime similar to how the GC can be 
shared?


It's probably just due to buffering. Insert a fflush(stdout) 
after the calls to printf in your DLL and see what happens.


This seems to work if I flush after every printf or write in both 
main and the dll.  I was under the impression they were supposed 
to share the same IO buffers though, is this not the case?


Re: win64 DLL stdout printing after main process completes

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

On Monday, 19 April 2021 at 16:00:25 UTC, frame wrote:

You miss a core.stdc.stdio import in main().
I also omit the def-File, maybe you have an error in it? It 
shouldn't be necessary to include. It just did:

```
dmd -m64 -ofmydll.dll -L/DLL mydll.d
```


Sorry, here's the def file, taken from the wiki example.
```
LIBRARY "mydll.dll"
EXETYPE NT
SUBSYSTEM WINDOWS
CODE SHARED EXECUTE
DATA WRITE
```
Incidentally I get some warnings regarding it when I compile:
```
mydll.def(2) : warning LNK4017: EXETYPE statement not supported 
for the target platform; ignored
mydll.def(3) : warning LNK4017: SUBSYSTEM statement not supported 
for the target platform; ignored
mydll.def(4) : warning LNK4017: CODE statement not supported for 
the target platform; ignored
mydll.def(5) : warning LNK4017: DATA statement not supported for 
the target platform; ignored

```
Are all those lines were intended for win32 dlls and whatever the 
x64 equivalents are are different?
Also, the example at the D wiki URL had a -L/IMPLIB in the 
command line but I get `LINK : fatal error LNK1146: no argument 
specified with option '/IMPLIB'` with that so I removed it.


win64 DLL stdout printing after main process completes

2021-04-19 Thread cc via Digitalmars-d-learn
I'm not sure if this is something unique to D or not, but I've 
having a minor issue where stdout output from a DLL (either via 
printf or phobos std.stdio write) is not displayed until after 
the main process has completed.  I'm making a project based 
around the example at https://wiki.dlang.org/Win32_DLLs_in_D 
which I've heard is a little out of date but I've gotten it 
working nonetheless.  I have the following project files:


```d
// mydll.d
module mydll;
import core.runtime;
import core.stdc.stdio;
import core.stdc.stdlib;
import core.sys.windows.windows;
extern(Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, 
LPVOID pvReserved) {

switch (ulReason) {
case DLL_PROCESS_ATTACH:
printf("[dll] DLL_PROCESS_ATTACH\n");
Runtime.initialize();
break;
case DLL_PROCESS_DETACH:
printf("[dll] DLL_PROCESS_DETACH\n");
Runtime.terminate();
break;
case DLL_THREAD_ATTACH:
printf("[dll] DLL_THREAD_ATTACH\n");
return false;
case DLL_THREAD_DETACH:
printf("[dll] DLL_THREAD_DETACH\n");
return false;
default:
}
return true;
}
export int MyDLL_Test() {
printf("[dll] MyDLL_Test\n");
return 5;
}
static this() {
printf("[dll] static this for mydll\n");
}
static ~this() {
printf("[dll] static ~this for mydll\n");
}
```

```d
// mydll.di
module mydll;
export int MyDLL_Test();
```

```d
// main.d
import mydll;
pragma(lib, "mydll.lib");
import core.sys.windows.windows;
void main() {
printf("[Main] Start\n");
scope(exit) printf("[Main] END\n");
int x = MyDLL_Test();
printf("[Main] x: %d\n", x);
printf("[Main] Finished\n");
}
```

DLL compilation command line: `dmd -m64 -ofmydll.dll -L/DLL 
mydll.d mydll.def`

Main command line: `rdmd -m64 main.d`

And upon running, the output I receive is:
```
[Main] Start
[Main] x: 5
[Main] Finished
[Main] END
[dll] DLL_PROCESS_ATTACH
[dll] static this for mydll
[dll] MyDLL_Test
[dll] DLL_PROCESS_DETACH
[dll] static ~this for mydll
```

I would expect the first three lines of dll output to precede the 
"[Main] x:" line at least.  Is there something I'm doing wrong?  
Do I need to somehow pass a reference to the main stdio to the 
DLL's D runtime similar to how the GC can be shared?


Package import order with extern(C++) classes and std.container.array failure

2021-04-06 Thread cc via Digitalmars-d-learn
Just encountered this compilation failure in DMD winx64 2.096, 
which previously worked in 2.095 and prior versions.  Just 
wondering if it's a bug, or a new issue to keep in mind when 
importing modules?  Sorry for the complex nature of this scenario 
but I'll try to keep it as simple as possible.


Given the following 4-file setup:

// main.d
import cream;
void main() {}

// cream/package.d
module cream;
public import cream.dcream;
public import cream.callbacks;

// cream/callbacks.d
module cream.callbacks;
import cream;
extern(C++) class CallbackBase {}

// cream/dcream.d
module cream.dcream;
import cream;
import std.container.array;
Array!CallbackBase callbackTracker;


Compilation fails with the following error:
C:\D\dmd2\windows\bin\..\..\src\phobos\std\container\array.d(519): Error: 
incompatible types for array comparison: `const(CallbackBase[])` and 
`const(CallbackBase[])`
C:\D\dmd2\windows\bin\..\..\src\phobos\std\container\array.d(189): Error: 
template instance `std.container.array.RangeT!(const(Array!(CallbackBase)))` 
error instantiating
C:\D\dmd2\windows\bin\..\..\src\phobos\std\container\array.d(528):
instantiated from here: `RangeT!(Array!(CallbackBase))`
cream\dcream.d(4):instantiated from here: 
`Array!(CallbackBase)`


It seems I can fix this by changing the order the other modules 
are imported in package.d like so:

// cream/package.d
module cream;
public import cream.callbacks;
public import cream.dcream;

I'm curious why this worked in prior dmd versions, and if it's 
something I'll need to worry about going forward when creating 
complex multi-file modules.


Re: Problem with templated alias as delegate parameter type

2021-01-12 Thread cc via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 21:32:14 UTC, Ali Çehreli wrote:

On 1/12/21 12:58 PM, cc wrote:

>  void send(T query, void delegate(T.RESPONSE) callback) {

That wants a delegate that takes a T.RESPONSE (PingResponse in 
this case). However, the following lambda is in fact a template:


>  send(PingQuery("helo"), (resp) {

You specify the type there and it works:

send(PingQuery("helo"), (PingResponse resp) {

Ali


That seems to work, thanks.  I ended up having to define a second 
template parameter:


template send(T,TR) if (is(TR == T.RESPONSE)) {
void send(T query, void delegate(TR) callback) {
...




Problem with templated alias as delegate parameter type

2021-01-12 Thread cc via Digitalmars-d-learn

Given the following program:

struct PingQuery {
string msg;
}
struct PingResponse {
string msg;
}
template send(T) {
void send(T query, void delegate(PingResponse) callback) {
writefln("Sending: %s", query);
if (callback) {
PingResponse resp;
resp.msg = query.msg;
callback(resp);
}
}
}
void main() {
send(PingQuery("helo"), (resp) {
writefln("Got response: %s", resp);
});
}

This works, but as you can see the PingResponse struct is 
hardcoded in the send function.  If I try to make it a part of 
the template in a way such as this:


struct PingQuery {
alias RESPONSE = PingResponse;
string msg;
}
struct PingResponse {
string msg;
}
template send(T) {
	static assert(is(T.RESPONSE == PingQuery.RESPONSE)); // this 
succeeds at least


void send(T query, void delegate(T.RESPONSE) callback) {
writefln("Sending: %s", query);
if (callback) {
T.RESPONSE resp;
resp.msg = query.msg;
callback(resp);
}
}
}
void main() {
send(PingQuery("helo"), (resp) {
writefln("Got response: %s", resp);
});
}
I get:
delegatetest.d(48): Error: template `delegatetest.send` cannot 
deduce function from argument types `!()(PingQuery, void)`, 
candidates are:
delegatetest.d(35):`send(T)(T query, void 
delegate(T.RESPONSE) callback)`


Same error if I use a nested struct (e.g. struct PingQuery { 
struct RESPONSE {} }) instead of an alias.  Currently using DMD32 
D Compiler v2.095.0-dirty (win64).





Re: Renamed but non-selective import?

2021-01-12 Thread cc via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 20:19:20 UTC, ag0aep6g wrote:

On 12.01.21 21:09, cc wrote:

import core.sys.windows.windows;
import mymodule; // contains a struct named MSG
Error: `core.sys.windows.winuser.MSG` ... conflicts with 
`mymodule.MSG`


vs

import core.sys.windows.windows : winMSG = MSG; // this leaves 
out other symbols

Error: undefined identifier `HWND`
Error: undefined identifier `LPCSTR`


import core.sys.windows.windows;
import mymodule;
alias MSG = mymodule.MSG;
alias winMSG = core.sys.windows.windows.MSG;


Ahh simple enough, thanks.


Renamed but non-selective import?

2021-01-12 Thread cc via Digitalmars-d-learn
Is it possible to import all symbols of a module, while renaming 
just one of them?  It seems like doing an import with renaming 
automatically makes it selective.
In the example below, I'd prefer not to have to use the fully 
qualified name for mymodule.MSG every time e.g.:


import core.sys.windows.windows;
import mymodule; // contains a struct named MSG
Error: `core.sys.windows.winuser.MSG` ... conflicts with 
`mymodule.MSG`


vs

import core.sys.windows.windows : winMSG = MSG; // this leaves 
out other symbols

Error: undefined identifier `HWND`
Error: undefined identifier `LPCSTR`



Re: constructing labels for static foreach inside switch inside foreach

2020-07-08 Thread cc via Digitalmars-d-learn
On Wednesday, 8 July 2020 at 02:06:01 UTC, Steven Schveighoffer 
wrote:
OK, so I have a situation where I'm foreaching over a 
compile-time list of types. Inside the loop, I'm using a second 
loop over a set of input.


Inside that loop, I'm using a switch on the input, and inside 
the switch, I'm foreaching over the type's members, to 
construct a switch that can handle member names (this is for 
serialization).


If I encounter a certain name, then I want to break out of the 
inner loop (it's a while loop)


So naturally, I have to use break statements with labels like:

innerloop:
while(haveMoreData)
   switchstmt:
   switch(nextDataElement) {
  static foreach(name; __traits(allMembers, T)) {
  case name:
 ... // handle it
 break switchstmt;
  }
  case "STOP":
 break innerloop;
   }

Seems simple enough, except that this inner portion is 
unrolled, and if I have more than one type to run this on, I 
already have an "innerloop" label defined.


Is there a way to define a label using a mixin or something? or 
do I have to wrap this in a function?


Is there another way to approach this?

-Steve


I think I ran into similar problems due to the requirement to use 
a labeled break inside static foreach.  I got around it by 
defining enums when my target was found and checking if it 
existed via __traits(compiles) to "ignore" the rest of the loop.
Sorry if I got what you're trying to accomplish wrong or this is 
too ugly:


class Foo {
@(RPC) bar(int x, float f, string s) {
// ...
}
}

class Remoter(T) {
void opDispatch(string s, SA...)(SA sargs) {
alias A = getSymbolsByUDA!(T, RPC);
static foreach (idx, FUNC; A) {
			static if (!__traits(compiles, FOUND) && hasUDA!(FUNC, RPC) && 
FUNCNAME!FUNC == s && SA.length == (Parameters!FUNC).length) {

version(CheckImplicitlyConvertibleArgs) {
static foreach (argi; 0 .. SA.length) {
		static if (!__traits(compiles, mixin(format("MISMATCH_%d", 
idx {
			static if (isImplicitlyConvertible!(SA[argi], 
(Parameters!FUNC)[argi])) {
//pragma(msg, format("implc ok: %s => %s", 
SA[argi].stringof, (Parameters!FUNC)[argi].stringof));

// Parameter Ok
} else {
pragma(msg, format("RPC argument[%s] of %s is not 
implicitly convertible: %s => %s", argi, FUNCNAME!FUNC, 
SA[argi].stringof, (Parameters!FUNC)[argi].stringof));

mixin(`enum bool 
`~format("MISMATCH_%d", idx)~` = true;`);
}
}
}
	static if (!__traits(compiles, mixin(format("MISMATCH_%d", 
idx {

enum FOUND = idx;
//pragma(msg, format("and we found: 
%s", FOUND));
}
} else {
enum FOUND = idx;
}
}
}
static if (__traits(compiles, FOUND)) {
alias FUNC = A[FOUND];

			// generate a packet to transmit that corresponds to RPC 
function call


} else {
			static assert(0, format("No matching function found for %s%s", 
s, SA.stringof));

}
}
}

Remoter!foo remote;
remote.bar(4, 3.14f, "hello"); // succeeds
remote.bar("hi", 12); // static assert fail



Should getSymbolsByUDA work with member variables?

2020-02-28 Thread cc via Digitalmars-d-learn

This compiles:

class Foo {
int x;
@(1) void y() {}
this() {
static foreach (idx, field; getSymbolsByUDA!(Foo, 1)) {
}
}
}

This does not:

class Foo {
@(1) int x;
void y() {}
this() {
static foreach (idx, field; getSymbolsByUDA!(Foo, 1)) {
}
}
}

Error: value of `this` is not known at compile time

Is there an equivalent for getSymbolsByUDA for member variables, 
or is this a bug?


Re: Get compilation errors within opDispatch?

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

On Monday, 17 February 2020 at 17:01:12 UTC, Adam D. Ruppe wrote:

It sometimes helps to write it out log-form

foo.opDispatch!"hello"(5);

should give the full error.

this btw is one of the most annoying missing errors in d...


This worked, thank you!


On Monday, 17 February 2020 at 16:45:53 UTC, Ali Çehreli wrote:

Try dmd command line switch  -verrors=spec.

Ali


This technically also worked, but the error was buried on line 
5431 of the 9857-line result.


Get compilation errors within opDispatch?

2020-02-17 Thread cc via Digitalmars-d-learn
Is there any way to see the compilation errors that occurred 
within an opDispatch template?


struct Foo {
void opDispatch(string s, SA...)(SA sargs) {
literally anything;
}
}
Foo foo;
foo.hello(5);

Result:  Error: no property `hello` for type `Foo`

Desired result:  Error: undefined identifier `literally`



Re: How to use labeled break in static foreach?

2020-02-13 Thread cc via Digitalmars-d-learn
Here's a more involved example of what I'm trying to accomplish.  
Is there an easier/cleaner way to do this?  (This is still a bit 
reduced, what I'm actually trying to do is compare whether a 
given variadic typetuple passed to opDispatch is implicitly 
convertible to one of the parameter definitions of overloaded 
functions with the same name on another object).


import std.meta;
struct Test { int[3] x; }
enum A = Test([1, 3, 3]);
enum B = Test([5, 6, 7]);
enum C = Test([5, 6, 7]);
enum D = Test([8, 9, 0]);
enum ARRS = AliasSeq!(A, B, C, D);

enum TESTER = Test([5, 6, 7]);

static foreach (ai, af; ARRS) {
static if (!__traits(compiles, FOUND)) {
static foreach (idx, field; af.x) {
			// Have to declare a different MISMATCH enum for each inner 
loop iteration
			//   unless we enclose it in its own {} scope, but if we do 
that then FOUND

//   is not visible to the outer loop
			static if (!__traits(compiles, mixin(format("MISMATCH_%d", 
ai {

static if (TESTER.x[idx] != af.x[idx]) {
mixin(`enum bool 
`~format("MISMATCH_%d", ai)~` = true;`);
}
}
			static if (idx == af.x.length - 1 && !__traits(compiles, 
mixin(format("MISMATCH_%d", ai {

enum FOUND = ai;
}
}
}
}
static if (__traits(compiles, FOUND)) {
pragma(msg, format("entry #%d matches: %s", FOUND, ARRS[FOUND]));
} else {
static assert(0, "Got no match...");
}



How to use labeled break in static foreach?

2020-02-13 Thread cc via Digitalmars-d-learn

import std.meta;
enum A = AliasSeq!(1, 2, 3, 4);
THREELOOP: static foreach (idx, field; A) {
static if (field == 3) {
pragma(msg, "Got a 3!");
break THREELOOP;
}
static if (idx == A.length - 1) {
static assert(0, "Got no 3...");
}
}

What I'd like to achieve in this example is for compilation to 
fail if the given tuple doesn't contain a matching item.  Is 
there an easy way to do this?  Trying to break out of the static 
foreach gives me

Error:enclosing label `THREELOOP` for `break` not found

In this reduced example, I was able to accomplish this by setting 
some enum within the successful comparison body and then checking 
e.g. static if (!__traits(compiles, FOUND)) but this breaks down 
once I start dealing with multiple levels of scope.


Re: Global version/debug statements in file?

2020-02-12 Thread cc via Digitalmars-d-learn
On Wednesday, 12 February 2020 at 09:28:15 UTC, Simen Kjærås 
wrote:

https://dlang.org/dmd-windows.html#switches

specifies that DMD may be passed a file on the command line 
that contains compiler arguments and switches. This may be 
freely combined with regular command line arguments if you so 
wish.


So, you could have a file called 'versions' containing this:

# Setting 'Compress' version
-version=Compress
# Optionally set other versions
#-version=Foo
#-version=Bar

and feed it to dmd like so:

dmd -w -wi -g @versions -main foo.d

--
  Simen


Ahh missed that, that should do it, thanks!


Re: Is there a std.zip.ZipArchive isDir or isFile method?

2020-02-12 Thread cc via Digitalmars-d-learn
It looks like 004 (octal) is the flag for directories on 
linux, but it does seem that std.zip is explicitly returning 0 if 
the file was created on the opposite platform re: Posix vs 
Windows, which is... odd.


@property @nogc nothrow uint fileAttributes() const
{
version (Posix)
{
if ((_madeVersion & 0xFF00) == 0x0300)
return _externalAttributes >> 16;
return 0;
}
else version (Windows)
{
if ((_madeVersion & 0xFF00) == 0x)
return _externalAttributes;
return 0;
}
else
{
static assert(0, "Unimplemented platform");
}
}

Looks like the only way around it is modifying std.zip?  Adding 
something like:


@property bool isDir() const {
enum uint FILE_ATTRIBUTE_DIRECTORY = 0x10; // WINNT.h
enum uint S_IFDIR = 0x4000; // sys/stat.h
version(Windows) {
if ((_madeVersion & 0xFF00) == 0x0300) // Archive made on Posix
return cast(bool) (_externalAttributes & (S_IFDIR << 
16));
		return cast(bool) (_externalAttributes & 
FILE_ATTRIBUTE_DIRECTORY);

} else version(Posix) {
if ((_madeVersion & 0xFF00) == 0x0300) // Archive made on Posix
return cast(bool) (_externalAttributes & (S_IFDIR << 
16));
		return cast(bool) ((_externalAttributes) & 
FILE_ATTRIBUTE_DIRECTORY);

} else {
static assert(0, "Unimplemented platform");
}
}

will let me do this:

void main() {
foreach (zipfile; ["windowstest.zip", "linuxtest.zip"]) {
writeln(zipfile);
auto zip = new ZipArchive(std.file.read(zipfile));
foreach (fn, am; zip.directory) {
writefln("%24s  %5s  %s", fn, am.isDir, 
am.fileAttributes);
}
}
}

Results on Windows:
windowstest.zip
   a.txt  false  32
testdir/   true  16
   testdir/b.txt  false  32
linuxtest.zip
   a.txt  false  0
testdir/   true  0
   testdir/b.txt  false  0

Results on Linux:
windowstest.zip
testdir/   true  0
   testdir/b.txt  false  0
   a.txt  false  0
linuxtest.zip
testdir/   true  16893
   testdir/b.txt  false  33204
   a.txt  false  33204



Global version/debug statements in file?

2020-02-12 Thread cc via Digitalmars-d-learn
Is there some way to globally declare version= or debug= 
statements in a file and have them apply to the entire project 
being compiled?  As the documentation says these only apply to 
the module scope they exist in, and need to be added to the 
command line otherwise.  It would be a bit easier for me to 
maintain a separate .d source file when I want to add/comment out 
statements for testing than to keep updating the build command 
line.  I tried using a mixin, such as:


// constants.d
module constants;
enum VERSIONS = q{
version=Compress;
};

// main.d
import constants;
mixin(VERSIONS);
void main() {
version(Compress)
writeln("Compress it!");
version(Decompress)
writeln("Decompress it!");
}

This does seem to work inside function bodies, but not at module 
scope in the importing file.  e.g.:


// main.d
import constants;
mixin(VERSIONS)
version(Compress) {
...
}

Gives: Error: version `Compress` defined after use



Re: Is there a std.zip.ZipArchive isDir or isFile method?

2020-02-11 Thread cc via Digitalmars-d-learn

On Monday, 3 February 2020 at 13:26:38 UTC, mark wrote:

I'm using std.zip.ZipArchive to read zip files, e.g.:

auto zip = new ZipArchive(read(filename));
// ...
foreach (name, member; zip.directory) {
if (name.endsWith('/')) // skip dirs
continue;
mkdirRecurse(dirName(name));
zip.expand(member);
write(name, member.expandedData());
}

As you can see, I am detecting directories with a crude test.

I really wish there was a method for this: and if there is, 
could you give me the link 'cos I can't see one in the docs?


(BTW The code above is slightly simplified: the real code won't 
unzip if there's an absolute path or .. present and also 
ensures that all members are unzipped into a subdir even if the 
zip has top-level names.)


I couldn't find one either, I had to do this:

version(Windows) {
enum uint FILE_ATTRIBUTE_DIRECTORY = 0x10;
}
auto zip = new ZipArchive(buffer);
foreach (fn, am; zip.directory) {
if (am.fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
... is directory
else
... is file
}

As I'm looking at my code for this I'm also reminded that 
different zip files can internally store path separators as 
either \ or / depending on the platform that created them so you 
may need to be careful about that too.  I have a bit for this 
that simply does:

version(StandardizePathSeparators) {
string filename = fn.replace("\\", "/");
} else {
string filename = fn;
}




  1   2   >