Re: Show dialog box for uncaught exception (Windows, lld-link)

2024-05-05 Thread SimonN via Digitalmars-d-learn

On Sunday, 5 May 2024 at 18:28:29 UTC, SimonN wrote:

My implementation for the message box is now:


According to [UTF-8 
Everywhere](https://utf8everywhere.org/#windows), I shouldn't use 
`MessageBoxA` at all. The `A` means ANSI codepages, _not_ UTF-8. 
My above code _will_ show garbage output when there is some 
non-ASCII in the exception message.


Better: Convert to UTF-16 yourself and call `MessageBoxW`:

version (Windows) {
import core.sys.windows.windows;
import std.conv;
const wstring messageBody = wtext(/* ... */, "\0");
MessageBoxW(null, messageBody.ptr, null, MB_ICONERROR);
throw /* ... */;
}

-- Simon


Re: Show dialog box for uncaught exception (Windows, lld-link)

2024-05-05 Thread SimonN via Digitalmars-d-learn

On Sunday, 5 May 2024 at 17:15:10 UTC, Steven Schveighoffer wrote:

} catch(Exception e) {
visualDisplayOfException(e);
throw e;
}


Thanks! That's practically the same pattern that I already use 
for logging: Try-catch near the entry point, show the message, 
re-throw. My implementation for the message box is now:


catch (Throwable t) {
import core.sys.windows.windows;
const string errText = /* ... parse t ... */
MessageBoxA(null, errText.ptr, null, MB_ICONERROR);
}

That solves my problem. Even though I don't pass my game's window 
as the parent of the message box (first argument, where I pass 
`null`), the graphical game halts before exiting, shows the 
error, and users can screenshot both together. That's good.


From your answer, I'll assume: There is no standardized way in 
the D ecosystem (e.g., by calling a DRuntime function from my 
usercode) to opt into displaying such a message box for uncaught 
exceptions. I have to call third-party APIs myself.


Or is there something after all? From reading the 2019 thread 
[Deactivate windows MessageBox dialog on 
exception](https://forum.dlang.org/post/tlhjypvsaxzymccfc...@forum.dlang.org), it sounds like we should get an error box when we link with `-subsystem:windows`, and no box otherwise.


-- Simon


Show dialog box for uncaught exception (Windows, lld-link)

2024-05-05 Thread SimonN via Digitalmars-d-learn

Hi,

for Windows, I link my executables with `lld-link`, whether for 
32-bit and 64-bit and whether I've built with LDC or DMD.


How can I generate a dialog box for uncaught exceptions that fly 
out of my executable's `main()`?


When I linked with Optlink years ago for Windows 32-bit, it 
generated an error dialog box for an uncaught exception. But with 
`lld-link`, the exception's message lands only on stderr. I 
didn't see anything related in `lld-link -help`. Can I configure 
DRuntime in a special way at runtime?


My application is a graphical game. I close stdout and stderr by 
passing `-subsystem:windows` to `lld-link` to suppress the extra 
console window. For a few fatal errors (missing required 
resources, can't open display, ...), I throw exceptions, log them 
to logfile, then re-throw them to crash. I can tell Windows users 
to look in the logfile, but it would be more fitting on Windows 
to show an error dialog box in addition to the logging.


-- Simon


Re: Annotating SortedRange.empty const: Best way to auto-deduce annotations?

2020-09-02 Thread SimonN via Digitalmars-d-learn
On Wednesday, 2 September 2020 at 21:40:59 UTC, Steven 
Schveighoffer wrote:
What they can do is template the `this` parameter. Then if the 
underlying range supports calling that way, it will work, 
otherwise it won't.


using `template this` should be compatible with the existing 
code I would think.


Thanks! I've never looked much into template this -- at first 
glance, it offers what inout already offers -- but it sounds like 
the right tool for the job. (inout would straightaway disallow 
calls to mutable methods.)


https://dlang.org/spec/template.html#template_this_parameter

I'll experiment with it!

-- Simon


Annotating SortedRange.empty const: Best way to auto-deduce annotations?

2020-09-02 Thread SimonN via Digitalmars-d-learn

Hi,

About this issue in Phobos:
https://issues.dlang.org/show_bug.cgi?id=21216
SortedRange.empty should be const, .front should be inout

Just adding const/inout to SortedRange's methods won't be enough; 
if we add const/inout here, then many other Phobos ranges need to 
become const/inout-correct to keep the tests passing. Before I 
dive deeper into annotating their methods, I would like to verify 
my assumptions on how template function attribute deduction works:


1) I know that templated functions deduce their own attributes on 
instantiation. But front()/empty() are non-templated methods 
within the templated struct SortedRange. Will attribute deduction 
happen here?


2) Is it sensible/possible to force attribute deduction by 
declaring empty() in SortedRange as a zero-argument template? 
I.e.:

@property bool empty()() { return this._input.empty; }

3) Should I rather annotate the non-templated 
SortedRange.empty/.front manually? But with what, then? empty() 
should probably be const, but it's never @nogc if annotated 
manually, even if the wrapped range offers empty() @nogc.


-- Simon


Re: Mergesort not working

2019-12-29 Thread SimonN via Digitalmars-d-learn

On Sunday, 29 December 2019 at 11:02:34 UTC, Adnan wrote:

while (arr1_idx < arr1.length && arr2_idx < arr2.length)
result ~= arr1[arr1_idx] < arr2[arr2_idx] ? 
arr1[arr1_idx++] : arr2[arr2_idx++];


Given an array, it just returns a 1 length array. What's 
causing this?


This loop stops as soon as arr1 _or_ arr2 are exhausted. Then, 
merge() will wrongly discard the remainder of the array that is 
not yet exhausted.


The templating is good!

-- Simon


Re: How does Rebindable suppress the compiler's optimizations for immutable?

2019-02-15 Thread SimonN via Digitalmars-d-learn

Thanks for the detailed answers!

Yes, I accept that immutable guarantees should be implemented 
only during @safe that doesn't call into @trusted.


On Friday, 15 February 2019 at 18:59:36 UTC, H. S. Teoh wrote:
At the very least, such [union] code should be automatically 
@system.


Sensible.


Honestly, I'm pretty sure that Rebindable technically
violates the type system to do what it does.


Hmm, I remember we discussed this, and I feel the same now about 
Rebindable. Either the spec gets extra rules for @trusted or 
unions, or Rebindable generates latent bugs.


Think of immutable as hint for the programmer, not for the 
compiler.


Right, if the compilers don't use it yet, I'm fine with that 
interpretation. It's merely strange that we have this very 
restrictive const/immutable that is advertized to help 
optimization, but then the compiler won't take advantage. Let's 
see how this develops in the long term, whether the spec gets 
clearer on the allowed optimization.


How does Rebindable suppress the compiler's optimizations for immutable?

2019-02-14 Thread SimonN via Digitalmars-d-learn

std.typecons.Rebindable!(immutable A) is implemented as:

private union {
immutable(A) original;
A stripped;
}

...@trusted assignment operators...

@property inout(immutable(A)) get() @trusted pure nothrow 
@nogc inout

{
return original;
}

alias get this;

This conforms with the D safety spec: All access to the unsafe 
union goes through the @trusted get() and the trusted assignment 
operators.


Rebindable!(immutable A) r = a1;
// r.original is a1
r = a2;
// r.original is a2

But the compiler may assume that immutable variables -- such as 
the immutable(A) original -- never change and thus may optimize 
code. Since immutable(A) original is assignable in the union, 
such optimization would produce wrong behavior: In the final 
line, the compiler could think that r.original is a1 without 
examining r.original.


How does Rebindable prevent the compiler from optimizing 
according to immutable's rules?


Re: Why does nobody seem to think that `null` is a serious problem in D?

2018-11-29 Thread SimonN via Digitalmars-d-learn
On Monday, 19 November 2018 at 21:23:31 UTC, Jordi Gutiérrez 
Hermoso wrote:

When I was first playing with D, I managed to create a segfault



What's the reasoning for allowing this?


100 % agree that there should be non-nullable class references, 
they're my main missing feature in D. Likewise, I'm astonished 
that only few D users wish for them.


I understand that it's very hard to get @safely right, without 
code-flow analysis that Walter prefers to keep at minimum 
throughout D.


I'm concerned about the clarity of usercode. I would like to 
ensure in my function signatures that only non-null class 
references are accepted as input, or that only non-null class 
references will be returned. All possibilities in current D have 
drawbacks:


a) Add in/out contracts for over 90 % of the class variables?
This is nasty boilerplate.

b) Check all arguments for null, check all returned values for 
null?
This is against the philosophy that null should be cost-free. 
Also boilerplate.


c) Declare the function as if it accepts null, but segfault on 
receiving null?
This looks like a bug in the program. Even if c) becomes a 
convention in the codebase, then when the function segfaults in 
the future, it's not clear to maintainers whether the function or 
the caller has the bug.


I discussed some ideas in 2018-03:
https://forum.dlang.org/post/epjwwtstyphqknavy...@forum.dlang.org

-- Simon


Re: LDC 1.13.0-beta1

2018-11-07 Thread SimonN via Digitalmars-d-announce

On Friday, 2 November 2018 at 21:04:13 UTC, kinke wrote:

Glad to announce the first beta for LDC 1.13:
* Based on D 2.083.0.
* The Windows packages are now fully self-sufficient


I'm late to the thank-you party, but yes, this is huge for me, 
too.


I develop on Linux. For Windows binaries, I've run the DMD 32-bit 
toolchain in Wine because I've shied away from installing MSVS to 
create 64-bit Windows binaries. The LDC Win64 beta was a breeze 
to get working in Wine, looking forward to use it!


-- Simon


Re: Things I found great about TypeScript that D could benefit from

2018-04-28 Thread SimonN via Digitalmars-d

On Friday, 27 April 2018 at 19:17:14 UTC, w0rp wrote:
The first feature I found really useful is the 
--strictNullChecks option that TypeScript has. I hate null 
dereferencing errors with a passion, and they have been the 
number one source of bugs that I've seen.


* Strict null checking is a winner, and you can use ordinary 
syntax to handle this.

That's it, let me know your thoughts.


Non-null class references are my #1 missing D feature. :-) When 
we don't have to worry about null-or-not, we have our mind free 
for the interesting problems. I love to peek around other 
languages and see how they tackle this problem. Thanks for the TS 
overview!


You advocate automatic narrowing inside if (x != null) even over 
Optional types. Is it because you find automatic narrowing 
cleaner than Optional? Or do you simply consider automatic 
narrowing a worthwhile addition whether or not a language has 
non-null + Optional?


```
void f(Optional!T x) { if (x !is null) g(x); }
void g(T x) { h(x); }
void h(T x) { writeln(x.myField); }
```

With a strictly non-nullable T, you can write `g` and `h` cleanly 
and null-safely. Without non-nullable types, even with implicit 
narrowing, both `g` and `h` would need an if/get or optional 
dispatch, complicating their definition.


-- Simon


Re: Pre-DConf Meetup on May 1

2018-04-25 Thread SimonN via Digitalmars-d-announce

On Wednesday, 25 April 2018 at 14:13:55 UTC, Seb wrote:
Our next D Munich Meetup will coincide with DConf to give our 
For those of you who stay at the hotel, we will be at the NH 
München Messe hotel at 18:00 and lead you towards the venue.


Awesome, I'll attend! I'm posting here for lack of a meetup 
account.


-- Simon


Re: Is there a strong reason for Nullable's alias get this?

2018-04-16 Thread SimonN via Digitalmars-d

On Monday, 16 April 2018 at 10:10:56 UTC, FeepingCreature wrote:
Nullable!T to T is a narrowing conversion, since T cannot 
express the null case. Therefor, it must not be implicit.


I agree with this. To even reach for a Nullable type in one's 
codebase incurs a cost -- the need is substantial to oughtweigh 
this complexity. In this situation, one will design internal 
interfaces both with and without Nullable. The strict typechecks 
(prevent assignment of Nullable!A to A) make large codebases of 
this kind safe to refactor.


If the checks must get more verbose because Nullable isn't part 
of the language, but rather a library feature, that's certainly a 
cost to pay for reliability. But it's still better than these 
runtime crashes. It's sad every time code crashes at runtime with 
errors that other type systems easily find at compiletime.


An alternative to Phobos's Nullable might be aliak's Optional? 
It's in the dub registry as "optional", or on github: 
https://github.com/aliak00/optional


import optional;
struct S { int i; }
void main()
{
Optional!S s = some(S(5));
S t = s;
}

This produces the desired error at compiletime: 
source/app.d(6,11): Error: cannot implicitly convert expression s 
of type Optional!(S) to S.


-- Simon


Re: merkle reverse

2018-04-05 Thread SimonN via Digitalmars-d-learn

On Thursday, 5 April 2018 at 09:49:58 UTC, Seb wrote:
Strings are bi-directional ranges, but they aren't 
random-access nor have a length

chunks requires hasSlicing + hasLength:


Okay, thanks for the great references. chunks/slide certainly 
need the length to decide which, and how many, elements to serve 
in the final chunk. The crucial part is now that an autodecoded 
string's final element can be determined in O(1) by looking at up 
to 4 code units from its un-decoded end, whereas its autodecoded 
length cannot be found in O(1).


-- Simon


Re: merkle reverse

2018-04-05 Thread SimonN via Digitalmars-d-learn

On Thursday, 5 April 2018 at 09:07:52 UTC, Seb wrote:
FYI: The problem isn't chunks, but that strings aren't 
bi-directional ranges (hello ugly auto-decoding!).

"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".byCodeUnit


Thanks! Very appropriate because it's all hex digits anyway.

Instead of std.experimental.all, one can also import std.utf.

Initially, I wondered whether autodecoding was the issue here, 
but I dismissed it because the OP's example calls retro 
immediately on a string, which is supposedly not autodecodable as 
bi-directional. But I should examine retro's implementation 
because I remember several Phobos functions having special cases 
for strings (which is exactly the issue of auto-decoding).


-- Simon


Re: merkle reverse

2018-04-05 Thread SimonN via Digitalmars-d-learn

On Thursday, 5 April 2018 at 08:12:38 UTC, aerto wrote:
This is the bitcoin genesis block merkle root 
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b how i can get it at this format 3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a ??


i try it using

string merkle = 
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b";


writeln(merkle.retro.text); and it gives me

b33adedfa7b7212ba77cc2e37667f816f78cb13c88a81523a3f98baab4e1e5a4


Here's one solution with std.range.chunks. A small downside is 
that it needs the array allocation in the middle because chunks 
cannot offer the bi-directional range necessary for retro.


import std.range;
import std.algorithm;

void main()
{
string merkle =

"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b";

assert (merkle.retro.equal(

"b33adedfa7b7212ba77cc2e37667f816f78cb13c88a81523a3f98baab4e1e5a4"));

assert (merkle.chunks(2).array.retro.joiner.equal(

"3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"));

}

-- Simon


Re: DIP in making: ProtoObject

2018-04-04 Thread SimonN via Digitalmars-d
On Wednesday, 4 April 2018 at 04:49:10 UTC, Andrei Alexandrescu 
wrote:
This is not officially reviewable yet, but conveys the gist and 
could use some early feedback. Any insight will be appreciated.


I'm delighted to see this DIP! Best of luck.

If there is a root class, I agree that it should be empty. What 
are some good reasons to keep the root class?


Associative arrays with immutable key classes rely on opEquals, 
opCmp, toHash. When a class derives from ProtoObject and an AA is 
declared, the compiler should statically check whether opEquals, 
opCmp, toHash are implemented, most likely via 
template/duck-typing, or maybe by interface. I feel there is no 
need to tailor ProtoObject towards AAs; that's good.


It's popular to wrap class references in templated structs that 
then masquerade as class references: std.typecons.Rebindable, or 
aliak's Optional, or maybe something to enforce a custom 
restriction at runtime (reference is not null!). These templated 
structs rely on is(T == class), and it takes a lot of 
implementation code to make these structs blend in with raw class 
references. const, inout, opEquals, ..., many things can subtly 
get in the way. Covariant return types become impossible.


It feels correct to disallow `a == b` entirely for a, b 
ProtoObjects, even though is(T == class)-templated structs will 
break when they forward opEquals explicitly. It would be nice to 
find a catch-all resolution that makes all existing is(T == 
class)-templates work with ProtoObject, but I doubt there will be 
one.


-- Simon


Re: Fixing 18615, how to handle @safe/pure/nothrow test breakage due to object.opEquals?

2018-03-28 Thread SimonN via Digitalmars-d-learn

On Wednesday, 28 March 2018 at 15:04:27 UTC, Kagamin wrote:

See line 1957, attributes are not inferred.


Wow, that hit my blind spot. :-O Thanks. I've moved the 
RebindableCommon.opEquals outside of the attributes and all tests 
pass, as expected.


-- Simon


Fixing 18615, how to handle @safe/pure/nothrow test breakage due to object.opEquals?

2018-03-28 Thread SimonN via Digitalmars-d-learn

Hi,

I'm trying to fix Bugzilla 18615, Rebindable!A doesn't use class 
A's opEquals (returns a is b instead) [1]. The fix looks 
reasonably obvious, my code is at [2]. Most of the added lines is 
the unittest; the essence of the fix is:


struct RebindableCommon(/* ... */)
{
// ...
bool opEquals(ref const(typeof(this)) rhs) const
{
return this.original == rhs.original;
}
}

But this breaks several existing unittests throughout Phobos 
because the comparison in object.d lacks @safe, @nogc, nothrow 
and pure. For example, unittests in systime.d fail:


pure function [...]RebindableCommon[...].opEquals cannot call 
impure function object.opEquals

nothrow function [...]RebindableCommon[...].opEquals may throw
std/datetime/systime.d(9006): Error: template instance 
`std.typecons.Rebindable!(immutable(TimeZone))` error 
instantiating


I'd rather not add attributes to the Rebindable.opEquals because 
this function sits in a templated struct RebindableCommon, where 
the compiler should deduce attributes automatically.


But I don't want to remove correct attributes from unittests in 
systime.d either.


Can I reasonably continue here to fix 18615?

-- Simon

[1] https://issues.dlang.org/show_bug.cgi?id=18615
[2] 
https://github.com/SimonN/phobos/commit/5a6fc6fd905b02e5ff93f2aaeaee2487fe8b38d0


Re: Optional type - how to correctly reset a wrapped immutable T

2018-03-27 Thread SimonN via Digitalmars-d-learn

On Tuesday, 27 March 2018 at 15:28:40 UTC, jmh530 wrote:

static if (isMutable!T)
bag[0] = rhs;
else
bag = [rhs];


I like this idea. I'd even take it a step futher:

When T is a pointer or class reference, then we can put the 
reference on the stack (instead of into the array) and handle 
assignments like Rebindable handles assignments -- provided that 
Rebindable really is 100 % safe to the outside, see my concerns 
from 2 posts above. In this case (static if), we won't even 
declare the array T[] bag, and instead implement as T value, bool 
isPresent.


When T is a mutable value type, it goes on the stack, too. Again 
no array.


When T is a const/immutable/inout value type, we declare the 
array as before and rebind on assignment with bag = [rhs], as you 
proposed here.


-- Simon


Re: Optional type - how to correctly reset a wrapped immutable T

2018-03-27 Thread SimonN via Digitalmars-d-learn

On Monday, 26 March 2018 at 14:17:03 UTC, Jonathan M Davis wrote:
Rebindable does is pretty questionable as far as the type 
system goes, but it does what it does by forcing pointer 
semantics on a class reference, so the point is arguable.


Yeah, I've always assumed that Rebindable cannot be implemented 
without internally breaking the type system, then exposing a safe 
interface.


But this sparked my interest, I've dug out the Rebindable code:

private mixin template RebindableCommon(T, U, alias This)
if (is(T == class) || is(T == interface) || 
isAssociativeArray!T)

{
private union
{
T original; // e.g., immutable(A) for classs A
U stripped; // the unqualified type, e.g., A
}
// ...
}

Does Rebindable-using code, oblivious of the hacks inside 
Rebindable, remain 100 % safe even with aggressive compiler 
optimizations? For class A, inside Rebindable!(immutable A), 
there is a union of (immutable A) and A. I suspect that the D 
compiler is allowed to treat this reference to (immutable A) as 
immutable itself. Have there never been bugs here when, later, 
stripped = another.stripped;?


-- Simon


Re: #dbugfix 17592

2018-03-21 Thread SimonN via Digitalmars-d

On Wednesday, 21 March 2018 at 13:55:16 UTC, Adam D. Ruppe wrote:
`emplace` is ALREADY `@nogc`

Interesting -- I checked the phobos source, and none of the 
`emplace` or `emplaceRef` are declared `@nogc`, yet the unittests 
marked as `@nogc` pass.


Does the compiler infer nogc-ness of `emplace` at instantiation?


class A { @nogc ~this() {} }
class B : A { ~this() {} }


My first hunch was that B's yes-gc-destructor should be illegal 
when A's descructor is `@nogc`, but it can be legal because 
destructors in a hierarchy are chained, not overridden. Seems 
like there is no way to ensure at child-class-compile-time that 
all child classes of A must be designed `@nogc`.


-- Simon


Re: Opt-in non-null class references?

2018-03-14 Thread SimonN via Digitalmars-d

On Sunday, 11 March 2018 at 09:28:39 UTC, aliak wrote:
Does this maybe boil down to if two templates should be 
covariant on their parameter types?


I'm not sure if this is always good. I haven't thought about it 
deeply, but I assume that some templated functions should be 
contravariant, and that there is no catch-all rule.


inference, in theory Rebindable!(const Derived) can be 
completely different than Rebindable(const Base). So are 
covariant return types even possible I wonder?


I don't think covariant return types will work here with the 
2018-03 language spec. We're returning structs 
(Rebindable!Something) and covariant return types is specifically 
for classes. :-)


It's one of the reasons why I shun wrapping types unless the 
benefit is really big.


If D had implicit conversions then types can specifically say 
that they explicitly allow behavior like this where it made 
sense though.


Yeah -- it shifts another burden of implementation to library 
type authors, I'm not sure if this path should be followed, 
especially since implicit constructor calls are shunned in D. (I 
have no opinion whether C++'s implicit constructor calls are 
handy enough for the obscured program flow.)


* * *

Here's another example where wrapped class references fail: You 
can override opEquals in the class, and the struct's opEquals 
need not necessarily call that.


import std.stdio;
import std.typecons;

class C {
int x;
override bool opEquals(Object rhsObj)
{
const(C) rhs = cast(const(C)) rhsObj;
return this.x == rhs.x;
}
}

void main()
{
C a = new C();
C b = new C();
assert (a == b); // OK: Even though a !is b, we overrode 
opEquals
 // and compare a.x == b.x, which is true 
(0 == 0).


Rebindable!(const(C)) ca = a;
Rebindable!(const(C)) cb = b;
assert (ca == cb); // Fails! struct Rebindable doesn't 
forward its

   // opEquals to the class's opEquals!
}

If this is by design, then it's very surprising. I've reported 
this as a bug to get a judgement from the Phobos authors: 
https://issues.dlang.org/show_bug.cgi?id=18615


-- Simon


Re: Article: Why Const Sucks

2018-03-05 Thread SimonN via Digitalmars-d-announce

On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:

Here's something I wrote up on const:


Excellent read! I enjoyed the history of proposed solutions.

I've run into the trouble with annotated opEquals in classes 
several times. I believe an empty/nonexistant Object class is the 
correct solution, together with templates. If it breaks tricky 
opEquals-overriding usercode, then so be it. The const trouble is 
merely a symptom here, the real problem is Object.


In structs, all const members feel alien, they preventing all 
copying. This seems far harder to solve.


-- Simon


Re: Opt-in non-null class references?

2018-03-04 Thread SimonN via Digitalmars-d

On Sunday, 4 March 2018 at 12:03:32 UTC, aliak wrote:

Maybe this part can be fixed with:
struct NonNull(T) if (isPointer!T || is(T == class))
{
@disable opAssign(V)(V v) {} // no no no
void opAssign(V)(NonNull!V other) { // only this allowed.


Interesting approach -- I'll keep it on the backburner for 
testing. Converting a class-heavy codebase to this would be 
daunting, but I don't want to rule it out yet.



Wrapping class references in structs is costly, we lose a lot

Can you provide an example case here?


Automatic subtype detection will fail, and, thus, e.g., covariant 
return types.


To make it clearer that this isn't a bug in Optional, but rather 
an artifact of D's subtype detection, I will give examples with 
std.typecons.Rebindable instead of with Optional. For a class A, 
Rebindable!(const(A)) is designed as a reference to const(A) that 
can be rebound to point to a different const(A). I believe 
Rebindable!A aliases itself away and thus Rebindable!A will not 
be discussed, only Rebindable!(const(A)).


import std.typecons;
class Base { }
class Derived : Base { }
static assert(is(const(Derived) : const(Base))); // OK
static assert(is(Rebindable!(const(Derived)) : 
Rebindable!(const(Base; // fails


Covariant return types will also fail. The following example 
doesn't compile, but would if we stripped all `rebindable' and 
all `Rebindable!':


import std.typecons;
class Base {
Rebindable!(const(Base)) create()
{
return rebindable(new Base());
}
}
class Derived : Base {
override Rebindable!(const(Derived)) create()
{
return rebindable(new Derived());
}
}

Speculation: There may be problems once we try to wrap class 
references in two different structs. We might want Optional or 
NonNull, and then another wrapper (e.g., Rebindable) for some 
other benefit. When these wrappers are written with 
if-constraints to take only raw D class references, we may pick 
only one wrapper. But I haven't investigated this yet.


-- Simon


Re: Opt-in non-null class references?

2018-03-03 Thread SimonN via Digitalmars-d

On Saturday, 3 March 2018 at 18:28:42 UTC, aliak wrote:

struct NonNull(T) if (isPointer!T || is(T == class))
{
  T value;
  alias value this;
  this(Args...)(Args args) { this.value = new T(args); } // 
always force creation

}


The pitfall here is that all structs must be 
default-constructible, and then all of the fields have the static 
init value:


class A { this(int) { } }
void main()
{
NonNull!A a;
assert (a.value is null);
}

...compiles and passes.

Wrapping class references in structs is costly, we lose a lot of 
automatic conversions across subclasses, const/immutable, ... For 
the over 90 % of references where null is a bug (sign of 
forgotten assignment), it will be convenient to keep D's 
references. A library solution must be super-convenient to be 
worthwhile here. For weeks, I've put off re-discussing non-null 
refs directly in D because a language change is a last resort.



I'm going to experiment with moving Optional's methods out
If you know of other ways though I'm all ears :)


No ideas for now, but I'll certainly follow this development 
closely, and will be happy to test things!


-- Simon


Re: Opt-in non-null class references?

2018-03-02 Thread SimonN via Digitalmars-d

On Thursday, 1 March 2018 at 16:37:02 UTC, aliak wrote:

I've put up a little experiment
If you're interested: https://github.com/aliak00/optional


Nice! Optional is like std's Nullable with extra bells and 
whistles to make it as painless as you can offer it. I've read 
all of Optional's source, skimming the dispatching introspection 
magic, and it's a concise wrapper that is as transparent as it 
can get.


I can envision using this Optional type whenever I want nullable 
class reference, and use normal D class references as 
non-nullable references together with a codebase-wide rule that 
assigning null to normal D references is always a bug.


Even the generated compiler error messages are good: Optional!C x 
= some(new C()); int y = x; // Error: Cannot implicitly convert 
from Optional!C to C.



a.dispatch.i; // not ideal, but is at least safe no op.


Hah, I've toyed with some examples, and this stuck out as verbose 
because everything else was really smooth. Optional!int 
dispatches wonderfully without extra syntax, whereas class C {}; 
Optional!C needs the extra dispatch before calling methods.


-- Simon


Re: Opt-in non-null class references?

2018-02-28 Thread SimonN via Digitalmars-d
On Wednesday, 28 February 2018 at 15:29:17 UTC, Mike Franklin 
wrote:
You might be interested in this little experiment:  
https://github.com/dlang/dmd/pull/7375


Indeed, this looks extremely useful, at the very least in a 
linter. I probably rely on ints getting initialized to 0 
throughout the program, and only rarely make that explicit.


With null references, the problem is not forgetting the 
initialization; it's expressing the intent of the variable. 
Usually, I want the non-null, but sometimes, I want a nullable 
reference and would like to require the using code to test the 
reference for null. Merely verifying for initialization doesn't 
help here; it may well be intended that null will be assigned 
later to the reference.


-- Simon


Re: Opt-in non-null class references?

2018-02-28 Thread SimonN via Digitalmars-d
On Wednesday, 28 February 2018 at 14:05:19 UTC, Jonathan M Davis 
wrote:
I expect that pretty much anything you propose that requires 
code flow analysis is DOA.
Walter was arguing against precisely because code-flow analysis 
is so hard to get right,


Thanks, that's an important judgement. I've read the 3 threads 
that I found around this issue, but didn't notice this sentiment 
before that code-flow analysis is so problematic.


Yeah, non-null class fields hinge on code-flow analysis. And I'll 
accept that pushing non-null refs won't lead to anything if the 
necessary code-flow analysis is too tricky for the benefit.


I've never understood why some folks have so many problems with 
null pointers.


My gripe is that the necessarily-nullable class reference doesn't 
express the intent.
Either a codebase must rely on silent conventions or every 
function with asserts.


and that blows up quite quickly such that it's fixed quite 
quickly.


Yeah, I admit that most null crashes surface adequately quickly 
even when you have to run the program first.


It's merely sad to see D, with all its powerful static 
inspection, rely on runtime tests for nulls while other languages 
(Kotlin, Zig, and 2017 C#) rule null out at compile-time, as if 
it's the most natural thing in the world.


-- Simon


Opt-in non-null class references?

2018-02-28 Thread SimonN via Digitalmars-d

Hi,

Andrei said in 2014 that not-null-references should be the 
priority of 2014's language design, with consideration to make 
not-null the default. In case the code breakage is too high, this 
can be an opt-in compiler flag.


Discussion here: 
https://forum.dlang.org/post/lcq2il$2emp$1...@digitalmars.com


Everybody in the 2014 thread was hyped, but has anything ever 
happened in the language? In November 2017, the D forum discussed 
C#'s non-null warnings. Has anybody thought about this again 
since?


In D, to prevent immense breakage, non-nullable class references 
need to be opt-in. I would love to see them and don't mind 
adapting my 25,000-line D-using project during a weekend.


Are there any counter-arguments to why non-nullable 
references/pointers haven't made it into D yet? Feel free to 
attack my answers below.


* * *

Argument: If A denotes non-null reference to class A, it can't 
have an init value.
Answer: Both A?.init and A.init shall be null, then use code-flow 
analysis.


This would match D's immutable: In a class constructor, you may 
assign the value 5 to a field of type immutable(int) that has 
init value 0. The compiler is happy as long as it can prove that 
we never write a second time during this constructor, and that we 
never read before the first assignment.


Likewise, it should be legal to assign from A to another A 
expression such as new A(), and the compiler is happy as long as 
the reference is assigned eventually, and if the reference is 
never read before assignment. (I haven't contributed to the 
compiler, I can't testify it's that easy.)


To allow hacks, it should remain legal to cast A? (nullable 
reference) to A (non-nullable). This should pass compilation 
(because casting takes all responsibility from the compiler) and 
then segfault at runtime, like any null dereference today.


* * *

Argument: I shall express non-null with contracts.
Answer: That's indeed the best solution without any language 
change. But it's bloaty and doesn't check anything at 
compile-time.


class A { }
void f1(A a) in { assert(a); } do { f2(a); }
void f2(A a) in { assert(a); } do { f3(a); }
void f3(A a) in { assert(a); } do { ...; }
void g(A a) { if (a) ...; else ...; }

Sturdy D code must look like this today. Some functions handle 
the nulls, others request non-null refs from their callers. The 
function signature should express this, and a contract is part of 
the signature.


But several maintenance problems arise from non-null via contract.

First issue: We now rely on unit-testing to ensure our types are 
correct. You would do that in dynamic languages where the type 
system can't give you meaningful diagonstic errors otherwise. I'd 
rather not fall back to this in D. It's easy to forget such 
tests, coverage analysis doesn't help here.


Second issue: Introducing new fields requires updating all 
methods that uses the fields. This isn't necessarily only the 
methods in the class. If you have this code:


class B {
A a1;
void f1() in { assert(a1); } do { ... }
void f2() in { assert(a1); } do { ... }
}

When you introduce more fields, you must update every method. 
This is bug-prone; we have final-switch (a full-blown language 
feature) just to solve similar issues:


class B {
A a1;
A a2;
void f1() in { assert(a1); assert(a2); } do { ... }
void f2() in { assert(a1); /+ forgot +/ } do { ... }
}

Third issue: Most references in a program aren't null. Especially 
class references that are fields of another class are often 
initialized in the constructor once, and never re-set. This is 
the predominant use of references. In D, the default, implicit 
case should do the Right Thing; it's fine when nonstandard 
features (allowing null) are explicit.


Assuming that A means non-null A, I would love this instead:

class A { }
void f1(A a) { f2(a); }
void f2(A a) { f3(a); }
void f3(A a) { ...; }
void g(A? a) { if (a) ...; else ...; }
Or:
void g(A @nullable a) { if (a) ...; else ...; }

Code-flow analysis can already statically check that we 
initialize immutable values only once. Likewise, it should check 
that we only pass A? to f1 after we have tested it for non-null, 
and that we only call methods on A? after checking for its 
non-null-ness (and the type of `a' inside the `if' block should 
probably still be A?, not A.)


* * *

Argument: null refs aren't a problem, they're memory-safe.
Answer: Memory-safety is not the concern here. Readability of 
code is, and preventing at compiletime what safely explodes at 
runtime.


* * *

Argument: Roll your own non-null type as a wrapper around D's 
nullable class reference.
Answer: That will look ugly, is an abstraction inversion, and 
checks at runtime only.


class A { }

struct NotNull(T)
if (is(T == class))
{
T payload;
@disable this();
this(T t) {
assert(t !is 

Re: String Type Usage. String vs DString vs WString

2018-01-15 Thread SimonN via Digitalmars-d-learn

On Monday, 15 January 2018 at 14:44:46 UTC, Adam D. Ruppe wrote:

On Monday, 15 January 2018 at 06:18:27 UTC, SimonN wrote:
D's foreach [...] will autodecode and silently iterate over 
dchar, not char, even when the input is string


That's not true. foreach will only decode on demand:
foreach(c; s) { /* c is a char here, it goes over bytes */ }


Thanks for the correction! Surprised I got foreach(c, s) wrong, 
its non-decoding iteration is even the prominent example in TDPL.


Even `each`, the template function that implements a foreach, 
still infers as char:


"aä".each!writeln; // prints a plus two broken characters

Only `map`



When I wrote "D's ranges", I meant Phobos's range-producing 
templates; a range itself is again encoding-agnostic.


Re: String Type Usage. String vs DString vs WString

2018-01-14 Thread SimonN via Digitalmars-d-learn

On Monday, 15 January 2018 at 02:05:32 UTC, Chris P wrote:

Is usage of one type over the others encouraged?


I would use string (UTF-8) throughout the program, but there 
seems to be no style guideline for this. Keep in mind two gotchas:


D's foreach and D's ranges will autodecode and silently iterate 
over dchar, not char, even when the input is string, not dstring. 
(It's also possible to explicitly decode strings, see std.utf and 
std.uni.)


If you call into the Windows API, some functions require extra 
care if everything in your program is UTF-8. But I still agree 
with the approach to keep everything as string in your program, 
and then wrap the Windows API calls, as the UTF-8 Everywhere 
manifesto suggests:

http://utf8everywhere.org/

-- Simon


Re: Dscanner: intentionally unused variable

2018-01-06 Thread SimonN via Digitalmars-d

On Sunday, 7 January 2018 at 00:18:27 UTC, Ivan Trombley wrote:
While working with SDL, I found that I kept using the same 
pattern over and over:

- Get the current clip rectangle.
- Set a new clip rectangle.
- restore the old clip rectangle on scope (exit).

Instead of writing that code again and again, I wrote a simple 
function that returns a struct which restores the old clip 
rectangle in it's destructor. This works great but now dscanner 
complains about the variable being unused.


Is there a way tell dscanner that a variable is intentionally 
unused?


Another way would be to have the RAII wrapper in a with 
statement, but it produces extra indentation, which you might not 
like:


with (MyStruct(100, 200)) {
// code that uses the new clip rectangle
}

-- Simon


Re: Pass D const pointer to opaque C library: Guarantees? Optimization-safe?

2017-12-16 Thread SimonN via Digitalmars-d-learn

On Saturday, 16 December 2017 at 11:19:36 UTC, Mike Parker wrote:

that's a binding, not a wrapper.


Right!


Not sure what you mean by "safe"
you only want to prevent changes on the D side and don't care
if they happen on the C side, then that's fine.


This, yes. I'd like const-annotated D code because of the static 
checks, without risking bugs from aggressive compiler 
assumptions. It's fine it the C side mutates privately.


I am ready to take responsibility in case I misjudge whether one 
of the C functions mutates  detectable state or not.


Question 2. If yes, can the wrapper sanely declare foo(const 
A*) instead of foo(A*)?

if you pass immutable variables to the function -- if the
parameter is const even when the function modifies the
variable, D will allow immutable to be passed and you're
looking at unexpected behavior.


This is the heart of the problem, I've overlooked this.

None of my A are immutable, but declaring the bindings as 
foo(const A*) would take immutables.



I would expect SiegeLord to reject such a PR.
Only add const to parameters in C function declarations if
the C API actually declares those parameters as const.


That was my hunch, too. I've asked upstream on the Allegro 
forums. It would be a drastic change, I'd wager there won't be 
any const in the API anytime soon. But I'll give them the due 
time to decide.


If no const C API, I'd stick to private wrappers around 
DAllegro5, with a codebase-wide rule to not pass immutable.



In principle, I disagree with him
how much weight should be assigned to "probably".


Hmm, SiegeLord is a core Allegro 5 developer, he could judge 
overriding the C API's promises. But I share your sentiment that 
the public C API should have the final word.


Many thanks for the high-quality answer!

-- Simon


Pass D const pointer to opaque C library: Guarantees? Optimization-safe?

2017-12-16 Thread SimonN via Digitalmars-d-learn

Hi,

I'm calling a C library through a D wrapper. The situation is 
like this:


C library has:
struct A  { ... };
A* create_a() { ... }
void foo(A*)  { ... }

D wrapper declares:
extern (C) {
struct A {}
A* create_a();
void foo(A*);
}

My D usercode:
const A* a = create_a();
foo(cast(A*) a);

We know that const is transitive in D and the compiler may 
optimize around it. If we cast away const, it's our 
responsibility that, e.g., the optimized caching from const will 
not cause bugs.


The memory of the A is allocated by the C library. All the D code 
ever sees is a pointer, an opaque handle to the resource. How 
will the compiler optimizations behave around this:


Question 1. Is that cast still safe in usercode if foo(a) changes 
some internal values in *a that are undetectable through the C 
API?


Question 2. If yes, can the wrapper sanely declare foo(const A*) 
instead of foo(A*)?


My use case: My const-heavy D usercode calls Allegro 5, a C 
game/multimedia library without any const in its API, through the 
D bindings DAllegro5. I'm considering to make a PR implementing 
question 2. Github issue: 
https://github.com/SiegeLord/DAllegro5/issues/42


-- Simon


Re: Sort in return statement

2017-12-08 Thread SimonN via Digitalmars-d-learn

On Saturday, 9 December 2017 at 03:24:52 UTC, codephantom wrote:

On Saturday, 9 December 2017 at 02:45:35 UTC, rjframe wrote:


`sort` returns a SortedRange of ushorts, not an array of 
ushorts. Make it:


```
import std.array : array;
return sort(numbers.take(8)).array;
```

--Ryan


That's it!

Thanks Ryan.


Yes, this works, and your algorithm would even accept arbitary 
random-access ranges, not merely arrays.


But since we start explicitly with a ushort[] that this function 
has allocated just for this algorithm, we could save the extra 
allocation by the final call to array().


// ushort[] numbers = ...
randomShuffle(numbers);

import std.algorithm.sorting : sort;
numbers = numbers[0 .. 8];
sort(numbers);
return numbers;

sort(numbers) does two things: (1) affect the underlying data, 
(2) return an input range with extra information that this 
returned range is sorted. But in our example, we don't need to 
allocate a fresh array from (2). We can return the sorted data 
from (1), this is already in array-form.


-- Simon


Re: Always std.utf.validate, or rely on exceptions?

2017-03-02 Thread SimonN via Digitalmars-d-learn

ketmar wrote:

i'd say: "ALWAYS validate before ANY further processing".


On Thursday, 2 March 2017 at 17:03:01 UTC, Kagamin wrote:
If you expect file with malformed utf that can cause you 
trouble and want to handle it gracefully, pass its content 
through validator and catch exception from validator.


Thanks. Now, I still call std.stdio.byLine or std.stdio.lines on 
the raw data, this seems robust with random binary blobs. Then, I 
validate each line before calling anything else.


-- Simon


Always std.utf.validate, or rely on exceptions?

2017-03-02 Thread SimonN via Digitalmars-d-learn
Many functions in std.utf throw UTFException when we pass them 
malformed UTF, and many functions in std.string throw 
StringException. From this, I developed a habit of reading user 
files like so, hoping that it traps all malformed UTF:


try {
// call D standard lib on string from file
}
catch (Exception e) {
// treat file as bogus
// log e.msg
}

But std.string.stripRight!string calls std.utf.codeLength, which 
doesn't ever throw on malformed UTF, but asserts false on errors:


ubyte codeLength(C)(dchar c) @safe pure nothrow @nogc
if (isSomeChar!C)
{
static if (C.sizeof == 1)
{
if (c <= 0x7F) return 1;
if (c <= 0x7FF) return 2;
if (c <= 0x) return 3;
if (c <= 0x10) return 4;
assert(false);
}
// ...
}

Apparently, once my code calls stripRight, I should be sure that 
this string contains only well-formed UTF. Right now, my code 
doesn't guarantee that.


Should I always validate text from files manually with 
std.utf.validate?


Or should I memorize which functions throw, then validate 
manually whenever I call the non-throwing UTF functions? What is 
the pattern behind what throws and what asserts false?


-- Simon


Re: A public domain game written in D

2017-02-04 Thread SimonN via Digitalmars-d

On Saturday, 4 February 2017 at 16:29:05 UTC, Dukc wrote:

On Saturday, 4 February 2017 at 04:03:08 UTC, SimonN wrote:
I've deferred my announcement to the D community because 
multiplayer is still WIP.


I hope I didn't spoil the surprise. I thought that because it's 
public on GH you don't mind someone mention it.


Anyway, interesting. My favorite language being used to remake 
one of my favorite games.


No hard feelings! It's deliberately public, I want Lix 
discoverable by explicit searches for Lemmings-related projects. 
I'm glad you found it mature enough for a posting here.


-- Simon


Re: A public domain game written in D

2017-02-04 Thread SimonN via Digitalmars-d

On Saturday, 4 February 2017 at 08:50:42 UTC, Stefan Koch wrote:

you need to make enums into static immmutable.

If you ever worked for you when using enums you were living 
dangerously.


I've pushed a fix by moved the code to runtime, the static 
asserts to unittested asserts. Thanks for your hint still; will 
keep in mind for the future.


The problematic code was like this:

class A { /* ... */ }
struct B { A a; /* ... */ }

enum B errorsNowDuringCTFE = /* ... */;

I wrote this over a year ago, trying to find out just how much 
can be forced into CTFE. The compiler accepted it, and yeah, it 
worked cross-platform. I imagined that 'enum' and 'static 
immutable' were equivalent, even though that looked like a 
stretch.


Keep up the good, aggressive compiler development that finds such 
latent bugs!


-- Simon


Re: A public domain game written in D

2017-02-03 Thread SimonN via Digitalmars-d

On Friday, 3 February 2017 at 21:14:48 UTC, Dukc wrote:

http://lixgame.com/

A public domain game very much like Lemmings. I'm almost sure 
some of you here have played Lemmings.


NOTE: I have not made or even contributed to that project. I 
just stumbled upon it when surfing the net and thought you may 
be interested to hear.


Hi, I'm the author, ask me anything. :-)

Lix is a Lemmings-like game with working singleplayer, but I'm 
still porting the networked multiplayer. I've deferred my 
announcement to the D community because multiplayer is still WIP.


With dmd 2.073, Lix doesn't compile because CTFE can't initialize 
classes/struct pointers anymore. I'm working on this. Lix builds 
with 2.072 and earlier.


-- Simon


Re: Bug after update to 2.072?

2016-11-06 Thread SimonN via Digitalmars-d-learn
I'm not sure how to pass arbitrary dustmite arguments through dub 
to dustmite. `dub dustmite -h' lists arguments.


When dustmite reduces your project to the empty project, maybe 
try this from the dustmite website: "You can also surround code 
that is not to be removed around the magic words 
DustMiteNoRemoveStart and DustMiteNoRemoveStop. Note that if you 
place them in comments, you won't be able to use 
--strip-comments."


On Sunday, 6 November 2016 at 06:28:32 UTC, Alex wrote:
object.Exception@DustMite/dustmite.d(270): Initial test fails 
(try using --no-redirect for details)


This means that dustmite doesn't recognize the unreduced source 
as buggy. As a sanity test, dustmite runs the given test on the 
unreduced project, and requires this test to succeed.


-- Simon


Re: immutable class can't override opEquals, workaround?

2016-02-21 Thread SimonN via Digitalmars-d-learn
On Sunday, 21 February 2016 at 07:58:42 UTC, Jonathan M Davis 
wrote:

opEquals still works with const and immutable
if it's legal to use a class as the key in an AA, it's a bug



have a working version of the PR
hasn't even been looked at yet from what I can tell,
and it's the simplest of the bits that need to be done


Thanks for the detailed overview.

Judging from the source comment at hack-casting const to mutable, 
naive improvements affect much more code than I have imagined.


The problem and possible solutions are on the radar still, that's 
satisfying. I understand if it takes more time, even if I too 
deem it important.


-- Simon


immutable class can't override opEquals, workaround?

2016-02-20 Thread SimonN via Digitalmars-d-learn

Hi,

immutable class A {
int i;
this(int arg) { i = arg; }
override bool opEquals(Object rhsObj)
{
auto rhs = cast (immutable(A)) rhsObj;
return rhs && i == rhs.i;
}
}

Error by dmd 2.070:

./immutclass.d(4): Error: function immutclass.A.opEquals
does not override any function, did you mean to override
'object.Object.opEquals'?

My understandings:

1.  immutable class A means: All methods have immutable tacked
on them implicitly.
2.  Object.opEquals doesn't have immutable tacked on it. If I
want to override Object.opEquals, I should override without
'immutable'.
3.  Overriding opEquals and toHash are necessary to make A
behave properly as AA key type. This is incompatible with
(2) in an immutable class.
4.  I found this thread:
How to turn an inout(Object) into a string

http://forum.dlang.org/thread/dcobmtogyrmnaqnqy...@forum.dlang.org

that I interpret as: The need for the currently-impossible
override is acknowledged, but the implementation would bring
significant changes to the language, therefore the solution
is postponed. The above thread was from mid-2015, but I guess
it's still relevant.

My workaround is: Make class _A private, and declare every method
immutable, except for what Object decrees to be mutable/const/...
Then make a public alias A = immutable(_A).

Is there something better than this?

Has there been any new development on Object method removal?
Jonathan M Davis has been pushing this hard 2 years ago, I'd
love to see the efforts make it into the language. :-)

-- Simon


Re: chain(const(array of class)) fails

2016-02-02 Thread SimonN via Digitalmars-d-learn

On Tuesday, 2 February 2016 at 10:58:35 UTC, Marc Schütz wrote:

The constraint that fails is the one with `CommonType`:
`CommonType` uses the `?:` operator to derive the common type:

I filed a bug report:
https://issues.dlang.org/show_bug.cgi?id=15638


Interesting reduced case, so it wasn't chain after all. Thanks 
for filing the issue already; also thanks to Nic for good test 
cases.


I think Adam D. Ruppe wanted to push more informative template 
errors -- they'd come in handy. :-)


-- Simon


Re: chain(const(array of class)) fails

2016-02-01 Thread SimonN via Digitalmars-d-learn
Sorry for late reply -- but I got around to test a couple more 
cases!


On Monday, 1 February 2016 at 00:19:44 UTC, Nicholas Wilson wrote:

Unqaul means remove any const or immutable torn the type


Okay, that sounds like our 'const' shouldn't matter. 'const' is 
the outermost qualifier, and stripping that leaves us with B[] 
and C[], which were chainable earlier.



StaticMap is like a compile time map
What this error message says is that there is one candidate 
function that matches what you are attempting to do. and that 
chain takes a variadic argument and each of those arguments must
1) when unqualified be an input range (Basically you can 
foreach over it)


Yep, const(B[]) and const(C[]) can be foreached. My workaround 
has been to replace chain() with several foreaches.


2) that the common type of the element type of the unqualified 
variadic argument types is not void (in this case not arrays of 
void)
Have you tried changing The declaration of a and b to 
const(A[])?


Surprisingly, this compiles and gives the desired output:

const(B[]) b = [ new B(), new B() ];
const(A[]) c = [ new C(), new C() ]; // A instead of C

chain(b, c).each!(a => a.val.writeln);

With two arguments, const(array) has worked iff at least one 
range is of the base type. Only if none were of the base type, I 
got the error.


Apparently, the template is smart enough to infer the common base 
type without 'const', but needs to be fed the basetype in case of 
'const'.


My gut feeling is that I should report this as a bug against 
phobos...


Also have you tried with other reference type (e.g. assoc 
arrays pointers)?


immutable(B[int]) b;
immutable(C[int]) c;

chain(b.byValue, c.byValue).each!(a => a.val.writeln);

Error is the same as for the classes:

template std.range.chain cannot deduce function
from argument types !()(Result, Result), candidates are: /* 
snip */


To get this error, again, if at least one range is 
'immutable(A[int]).byValue', i.e., using the base class A, the 
template instantiates with no problems.


-- Simon


chain(const(array of class)) fails

2016-01-31 Thread SimonN via Digitalmars-d-learn

Hi,

we start with the following code snippet, which works.

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

class A { int val; }
class B : A { this() { val = 3; } }
class C : A { this() { val = 4; } }

B[] b = [new B(), new B()];
C[] c = [new C(), new C()];

void main()
{
chain(b, c).each!(a => a.val.writeln);
}

The output, as expected, is:

3
3
4
4

Now I change the declarations of B[] b and C[] c to the 
following, keeping

everything else in the code snippet the same:

const(B[]) b = [new B(), new B()];
const(C[]) c = [new C(), new C()];

This makes dmd 2.070 choke: ( http://dpaste.dzfl.pl/eee69fd03dd9 )

Error: template std.range.chain cannot deduce function from 
argument

types !()(const(B[]), const(C[])),
candidates are: 
/opt/compilers/dmd2/include/std/range/package.d(804):

std.range.chain(Ranges...)(Ranges rs) if (Ranges.length > 0 &&
allSatisfy!(iseputRange, staticMap!(Unqual, Ranges)) && 
!is(CommonType!(

staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void))

What's stumping me -- constness doesn't make dmd choke on ranges 
of
numbers. If I replace the classes B and C with simple 'int' and 
'double',

this compiles again:

const(int[])b = [1, 2];
const(double[]) c = [3.3, 4.4];
void main() { chain(b, c).each!(a => a.writeln); }

Why does it fail for const(array of class)?
Is any template magic about Unqual or staticMap relevant here?

-- Simon


Re: @property not available for classes?

2016-01-01 Thread SimonN via Digitalmars-d-learn
On Friday, 1 January 2016 at 10:14:58 UTC, Shriramana Sharma 
wrote:

auto p = TimeSpan(1, 2);
Error: no property 'opCall' for type '.TimeSpan'


The error should be in 'auto p = ...', not in the line using the 
property.


Instantiate with 'new TimeSpan(1, 2)' instead of 'TimeSpan(1, 
2)'. The latter would be the constructor call for a struct. 
Classes go on the GC'ed heap by default.


The property syntax should work. :-)

-- Simon


Re: Variable below zero but if statement doesn't grab?

2015-12-27 Thread SimonN via Digitalmars-d-learn

On Sunday, 27 December 2015 at 16:41:10 UTC, TheDGuy wrote:
It looks like the debugger is not working correctly because i 
changed the code to this:

[...]
and the same problem appears.


I can't watch youtube here. What numbers does your input 
generate? Which 'if' doesn't fire? What results would you like 
instead?


-- Simon


Re: Variable below zero but if statement doesn't grab?

2015-12-27 Thread SimonN via Digitalmars-d-learn

On Sunday, 27 December 2015 at 16:01:37 UTC, TheDGuy wrote:

Sry:
if((x1 < 0) & (x2 >= 0)){


This looks like a bug, with & instead of &&.

-- Simon


Re: Variable below zero but if statement doesn't grab?

2015-12-27 Thread SimonN via Digitalmars-d-learn

On Sunday, 27 December 2015 at 16:52:39 UTC, TheDGuy wrote:
I don't understand why my program goes into the if statement if 
the debugger shows, that the variable "discriminant" is below 
zero even though:


"if(discriminant > 0)"?


I have a hard time believing this. Does the problem persist if 
you swap out the entire control flow, beginning with that line, 
with the following?


if (discriminant > 0)
writeln("bigger than zero");
else
writeln("not entering the 'if'");


Re: segfault in invariant { assert(super); }

2015-12-22 Thread SimonN via Digitalmars-d-learn
On Monday, 21 December 2015 at 20:29:14 UTC, Steven Schveighoffer 
wrote:

1) Is this recursion expected?
Yes. assert calls the virtual invariant function, which in the 
case of super is equivalent to this. So you are essentially 
calling assert(this).



2) The example is a dustmite'd version of this:
It seems like something you shouldn't do. AFAIK, invariant 
should not call any public functions on your existing class.


Thanks for the reply! Yeah, this helps for a clearer picture of 
what's happening.


In particular, even though all invariants of a class hierarchy 
are tested instead of only the most-subclassed-one, triggering 
the invariant check remains virtual. I didn't know that.


Even if Base.f() is const, it's not allowed inside 
Derived.invariant(). This is again understandable: By OOP 
principles, Derived shouldn't impose further restrictions on Base 
than what Base imposes on itself already.



(good idea to file an enhancement report).


For that, I was trying earlier today to find the exact instances 
of when there is a warning, and when there is not. I didn't get 
warnings to come up consistently. (Even the case I described in 
question 2 doens't always give a warning.) I'd have to take a 
look at this some time again.


-- Simon


segfault in invariant { assert(super); }

2015-12-19 Thread SimonN via Digitalmars-d-learn

Hi,

the following code compiles fine, then segfaults upon running.

class Base {
this(int) { }
}

class Derived : Base {
this(int a) { super(a); }
invariant() { assert (super); }
}

void main()
{
new Derived(5);
}

Tested both with dmd 2.069.2 on Linux 64-bit, and on dpaste's dmd 
2.069.1:


http://dpaste.dzfl.pl/4b9475c668f1

Backtrace on my home machine:

Program received signal SIGSEGV, Segmentation fault.
0x004246a5 in _D9invariant12_d_invariantFC6ObjectZv ()
(gdb) bt
#0  0x004246a5 in 
_D9invariant12_d_invariantFC6ObjectZv ()

#1  0x00647bf0 in _D3app7Derived6__initZ ()
#2  0x7f7ff030 in ?? ()
#3  0x0042301f in _D3app7Derived12__invariant1MxFZv 
(this=0x0)

at source/app.d:7
Backtrace stopped: previous frame inner to this frame 
(corrupt stack?)


So, looks like endless recursion inside the invairant.

Questions:

1) Is this recursion expected?

2) The example is a dustmite'd version of this: I have a public 
final method Base.f(), and the compiler won't let me call f() in 
Derived's invariant. This is understandable, because f() is also 
a public method of Derived. However, I can call super.f() 
explicitly in Derived's invariant, with no compiler error. Is 
that expected to work, or should it lead to a similar segfault? 
(I get the segfault.)


-- Simon


alias butAtLeast = max; 5.butAtLeast(6);

2015-12-12 Thread SimonN via Digitalmars-d-learn

DMD v2.069.2-b1 on Linux.

import std.algorithm;

int a = max(5, 6);// works, a == 6
int b = max!(int, int)(5, 6); // works, manual instantiation
int c = 5.max(6); // works, UFCS call

I would like to use the last syntax, but with an alias.

alias butAtLeast = max;   // works
int d = butAtLeast(5, 6); // works
int e = 5.butAtLeast(6);  // error: no property 'butAtLeast' 
for type 'int'


Aliasing the instantiated function 'max!(int, int)' instead of 
aliasing 'max' doesn't help: The 'int e' line will fail with the 
exact same error.


Can I get the alias to work somehow in an UFCS chain?

-- Simon


Re: alias butAtLeast = max; 5.butAtLeast(6);

2015-12-12 Thread SimonN via Digitalmars-d-learn
By putting it in the top level. I believe this is intentional 
but I don't remember the reasoning.


On Saturday, 12 December 2015 at 13:34:09 UTC, ZombineDev wrote:
This is due to limitation of function-local aliases. If you put 
the alias outside it will work: 
http://dpaste.dzfl.pl/4fb06cbbfad2.


Thanks for both of these quick replies -- doing it similar to 
that example, it works for me too now. Good to know this little 
workaround.


I'd love to see the design reason for the limitation. Right now, 
the error message (property doesn't exist at all) seems to be 
misleading. But getting all corner cases right is always tricky. 
:-)



Perhaps a simpler way achieve this is to use renamed imports:



The Identity template can also helpful in some situations:


Thanks, will read for inspiration!

-- Simon


Range violation instead of empty slice on a[3 .. 2]

2015-11-21 Thread SimonN via Digitalmars-d-learn

string a = "hello";
string b = a[3 .. 2];

I expect b to become an empty slice, because 3 is >= 2 already 
after 0 increments, making the slice length 0. Instead, the code 
throws a range violation.


Expressions of this kind come up, e.g., when taking slices near 
the end of arrays, like "slice = a[b.length .. $];". To make this 
robust, I need an extra check for b.length > a.length, returning 
null in this case, otherwise a[b.length .. $].


What's the design reason to prefer throwing over returning an 
empty slice?


-- Simon


Re: Range violation instead of empty slice on a[3 .. 2]

2015-11-21 Thread SimonN via Digitalmars-d-learn

On Saturday, 21 November 2015 at 18:28:51 UTC, BBaz wrote:
this is only an error if bounds checking is not turned on. If 
you compile your example with DMD option "-boundscheck=off", 
nothing happens, and the slice will be equal (here) to a[3..$];


Thanks for the hint, I tested this with -boundscheck=off. Then, 
a[3..2] generates a slice length of (size_t.max), again different 
from what I might want.


If the reason for this behavior (huge slice length instead of 
null slice) is performance during disabled bounds checking, then 
I'm fine with having to make the extra check.


-- Simon


Re: Range violation instead of empty slice on a[3 .. 2]

2015-11-21 Thread SimonN via Digitalmars-d-learn
On Sunday, 22 November 2015 at 00:24:43 UTC, Jonathan M Davis 
wrote:

this is only an error if bounds checking is not turned on.

It's a logic error regardless.



you're going to have to create a wrapper.


Right, I am using a wrapper, and I'm not relying on any behavior 
of a[3..2] during -boundscheck=off.



How does the runtime know that you're not just
providing it garbage values?


The runtime flags an empty slice as an error here, seemingly 
without reason, because the slice can't access any element 
outside of bounds.


However, considering (2U - 3U) > 0, I understand that there is no 
way to catch this problem without comparing the two bounds. And 
the comparison is designed to be skippable for speed. Therefore, 
3..2 is reasonably flagged as an error.


So, thanks for pointing it it out again!

-- Simon


Mixin template, "no identifier for declarator"

2015-10-27 Thread SimonN via Digitalmars-d-learn

Hi,

I'd like to generate several very similar class methods with a 
mixin template.
The mixin template shall take alias parameters, so that different 
methods can

bind it to different fields. Reduced problem case:

class A {
int myField;

mixin template fieldSetter(alias whatField)
{
whatField = newVal;
}

int setMyField(in int newVal)
{
mixin fieldSetter!myField;
}
}

Compiler error message, DMD64 v2.068.2, line 6 is "whatField = 
newVal;":


(6): Error: no identifier for declarator whatField
(6): Error: declaration expected, not '='

I believe I'm following as closely as appropriate what's 
described at
http://dlang.org/template-mixin.html under "Mixins can 
parameterize symbols

using alias parameters".

Why does it error out on whatField, apparently deeming it to be a 
type?


Can I get this done with mixin templates? (I'd like to avoid 
string mixins,

the workaround with them got a little ugly.)

-- Simon


Re: Mixin template, "no identifier for declarator"

2015-10-27 Thread SimonN via Digitalmars-d-learn

On Tuesday, 27 October 2015 at 08:41:24 UTC, Andrea Fontana wrote:

Template mixins can be used only for declaration.


Thanks for the quick reply! I didn't know that. Now the error 
message makes sense.



Probably what you need is a (non-template) mixin.


Yes, it's gonna be a string mixin, or a private method with lots 
of ref parameters.


-- Simon


Re: Enumap -- a lightweight AA alternative when your keys are enums

2015-09-15 Thread SimonN via Digitalmars-d-announce

On Sunday, 13 September 2015 at 03:33:15 UTC, rcorre wrote:
I've released v0.4.0, which implements foreach with ref, and 
(hopefully) atones for my crimes against const-correctness. You 
should be able to modify values in a loop and work with 
const/immutable Enumaps.


Thanks for the feedback!


Yes, the 0.4.x version works with my examples perfectly. Thanks 
for adding const support!


(I haven't tested yet every combination of const/mutable Enumap, 
const/mutable foraech-value, and direct/ref foreach-value. My 
examples are exactly what I'd do in normal projects anyway, 
mapping enum-values to ints.)


-- Simon


Re: Enumap -- a lightweight AA alternative when your keys are enums

2015-09-10 Thread SimonN via Digitalmars-d-announce

On Friday, 11 September 2015 at 04:02:17 UTC, rcorre wrote:

On Friday, 11 September 2015 at 03:25:58 UTC, SimonN wrote:

Hi,
I've ran into a compilation error when iterating over a const 
Enumap. In the following code:


Interesting, thanks for pointing that out.
I don't think I did a great job with const-correctness here, 
I'll take a look tomorrow.
It should definitely be possible to iterate over (and index, 
etc...) a const/immutable Enumset, though you're right that it 
doesn't work right now.


No worries, take your time! Thanks for the quick clarification.

I've also tested a couple ways of assigning in a foreach. 
Continuing from my code above (struct A { Enumap!(MyEnum, int) 
map; /* ... */ }), I've tried this in the main function:


int some_value = 100;
A a;

foreach (MyEnum e, ref val; a.map)
val = ++some_value;
a.mutable_output();

foreach (MyEnum e, ref val; a.map)
a.map[e] = ++some_value;
a.mutable_output();

Output:

e1: 0
e2: 0
e3: 0
e1: 104
e2: 105
e3: 106

Since I have been using "ref val" in the first loop, I expected 
the output to be instead:


e1: 101
e2: 102
e3: 103
e1: 104
e2: 105
e3: 106

-- Simon


Re: Enumap -- a lightweight AA alternative when your keys are enums

2015-09-10 Thread SimonN via Digitalmars-d-announce

On Friday, 11 September 2015 at 02:17:25 UTC, rcorre wrote:
I frequently find myself needing a data structure that maps 
each member of an enum to a value;
something similar what Java calls an EnumMap 
(http://docs.oracle.com/javase/7/docs/api/java/util/EnumMap.html).


I couldn't find any D implementation out there, so I wrote a 
little module for it.

Enumap is available on Github (https://github.com/rcorre/enumap)
and via dub (http://code.dlang.org/packages/enumap).
Docs are hosted at http://rcorre.github.io/enumap/.


Hi,

this looks excellent! I've been playing around with it, and am 
looking forward to using it regularly.


I've ran into a compilation error when iterating over a const 
Enumap. In the following code:


import std.stdio;
import std.conv;
import enumap;

enum MyEnum { e1, e2, e3 }

struct A
{
Enumap!(MyEnum, int) map;

void mutable_output()
{
foreach (MyEnum e, int i; map)
writefln("%s: %d", e.to!string, i);
}

void const_output() const
{
foreach (MyEnum e, const int i; map)
writefln("%s: %d", e.to!string, i);
}
}

...the first method (mutable_output) compiles and works with no 
errors. The const method, however, gives:


source/app.d(19,13): Error: invalid foreach aggregate 
this.map,

define opApply(), range primitives, or use .tupleof".

It doesn't seem to matter whether I put const int, or int, in the 
foreach statement.


What's the idiomatic way to loop over a const Enumap? :-)

-- Simon


Re: Arrays of structs

2015-08-27 Thread SimonN via Digitalmars-d-learn

Hi,

On Thursday, 27 August 2015 at 10:05:31 UTC, John Burton wrote:
understanding is that structs have deterministic destructors - 
they are called when the struct goes out of scope


Yes, when they are declared right at the scope, and not contained 
in something that might live past the current scope.



However if I add them to a dynamic array...
Then the destructor appears to be called at some random time 
later. So it looks like it's the garbage collection that is 
doing this.


Yeah.

That seems to go against the specification of how struct 
works... I'm not creating the item with new and as far as I 
can tell the array is storing instances of objects, not 
pointers to objects?


The array is storing the full structs, yes. The array is GC-ably 
allocated and will therefore not go out of scope at end of scope. 
Because the array doesn't vanish here, the structs inside will 
not go out of scope either; they treat the array as their scope.


(I'm sure others could explain this more formally.)

There is no reference left to the array, so the GC may at a 
random later time deallocate the array, and thereby call ~this() 
on each struct.



Is my understanding correct?


Explicit new is not the only way to put objects on the GC'ed 
heap. Putting them in a GC-ed array like this is another way. Or 
having them as a component in a class, then instantiating that 
class.



Is it documented anywhere how memory allocation works for this?


I'll leave this for others, too.

Is a dynamic array in fact storing an array of GC'd pointers to 
the structs?


No, it's the full struct.

-- Simon


Re: Empty struct, any runtime cost?

2015-08-19 Thread SimonN via Digitalmars-d-learn

On Wednesday, 19 August 2015 at 09:54:33 UTC, SimonN wrote:

Hi,


I've found this thread (Theoretical best practises):
http://forum.dlang.org/thread/codmadrwuyqxbklmu...@forum.dlang.org

My goal is the same; I'm only more wary of putting debug/version
everywhere. If the empty struct isn't optimized away fully,
I'd still be up for what's recommended in that thread.

-- Simon


Empty struct, any runtime cost?

2015-08-19 Thread SimonN via Digitalmars-d-learn

Hi,

in a release-like build, I'm using the tharsis profiler, which is 
a
frame-based profiler. Zone is a RAII struct that measures how 
long its own

lifetime is.

with (Zone(my_profiler, zone name to appear in output)) {
do_expensive_work();
do_some_more_work();
}
// Zone goes out of scope here

I would like to use this code without modification in a release 
build
without profiling. I would rather not put version statements 
everywhere.
I have only one version statement in a single file that's 
included by

all files doing profiling:

version (release_with_profiling) {
public import tharsis.prof;
}
else {
class Profiler { }
struct Zone { this(Profiler, string) { } }
}

Using that, the first code sample compiles in the non-profiling 
build,

where Zone is an empty struct.

*   Will the empty struct get optimized away completely by the 
compiler,

at least if we pass -O -inline? I'd really like that, I have
profiling code in several inner loops.

*   If not, what other approach could be usable to keep 
boilerplate in

most source files to a minimum?

-- Simon


Re: Template mixin can not introduce overloads

2015-06-30 Thread SimonN via Digitalmars-d-learn

On Thursday, 25 June 2015 at 03:49:04 UTC, Tofu Ninja wrote:
 Is this intended or is it a bug?


On Thursday, 25 June 2015 at 03:53:58 UTC, Adam D. Ruppe wrote:
Intended, the mixin template works on the basis of names. This 
The extra step is easy though: alias the name in:


I would like to to this with constructors instead of normal 
methods. I have tried to mix in a constructor as follows:


#!/usr/bin/rdmd

import std.stdio;

mixin template MyConstructor() {
this(int x, float y) { writefln(%d, %f, x, y); }
}

class Base {
mixin MyConstructor my_ctor;
this(string s) { writefln(s); }
alias my_ctor this;
}

void main()
{
Base b = new Base(3, 4.5);
}

$ ./mixinctor.d
./mixinctor.d(17): Error: constructor mixinctor.Base.this (string 
s) is not callable using argument types (int, double)

Failed: [dmd, -v, -o-, ./mixinctor.d, -I.]

Doing it with
alias this = my_ctor;
errors out too, and demands me to use alias my_ctor this; as in 
the original code.


Can I get this to work at all? Or does alias this (for multiple 
subtyping) fundamentally clash here with alias my_ctor this?


-- Simon


Re: How to realize copyable/postblit class

2015-06-13 Thread SimonN via Digitalmars-d-learn

On Saturday, 13 June 2015 at 08:52:59 UTC, John Colvin wrote:

perhaps:

class A
{
struct S
{
// ...
}
S s;
alias s this;
this(A rhs)
{
s = rhs.s;
}
}


I'm using this now, and it doesn't feel like a workaround too 
much.


For something with 5 value fields, it's already shorter than the 
original solution.


Thanks! :-)

-- Simon


How to realize copyable/postblit class

2015-06-12 Thread SimonN via Digitalmars-d-learn

Hi,

I have a few classes with need for deeper copying. I don't want a 
bitwise copy necessarily. Ideally, I'd implement this(this).


I've thought about changing them to struct. However, the type 
feels much more like a D class than a D struct. It's often passed 
by reference, and it's not plain old data. Changing it to struct 
for the sole benefit of this(this) seems to be a bad tradeoff.


(Use case: Backing up game states in a for 
savestating/networking.)


I've resorted to a C++-style copy constructor:

this(T rhs) {
myvalue = rhs.myvalue;
myarray = rhs.myarray.dup;
// ...
}

Downside: Boilerplate, each member appears once in the 
declarations, a second time in the copy constructor.


Alternative approaches seem to implement T T.dup() or T 
T.clone(). Apparently, one has to pick one of these equally good 
approaches, and stick with it throughout a codebase. It seems 
good to implement it only for the classes that need it, to 
minimize boilerplate.


Is that the state of the art?

-- Simon