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: 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: 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: 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: 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: 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: 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