Re: Range non-emptyness assertions and opIndex

2016-07-01 Thread Nordlöw via Digitalmars-d-learn

On Friday, 1 July 2016 at 11:35:40 UTC, ag0aep6g wrote:
Huh? Asserts are ignored with -release. The only exception is 
assert(false) which terminates the program immediately, even 
with -release.


Aha, that's what I was testing against so therefore the confusion.


Re: Range non-emptyness assertions and opIndex

2016-07-01 Thread Rene Zwanenburg via Digitalmars-d-learn

On Friday, 1 July 2016 at 10:35:04 UTC, Nordlöw wrote:
I think this is a important issue since asserts are not 
optimized away in release mode and D is very much about 
performance.


Asserts are removed in release mode, enforce isn't. Here's an 
example:


=
void main(string[] args)
{
assert(args.length >= 1);
}
=

dmd testfile.d

This calls the assert function as expected:
=
_Dmain:
  : 55 pushrbp
  0001: 48 8B EC   mov rbp,rsp
  0004: 48 83 39 01cmp qword ptr 
[rcx],1
  0008: 73 0E  jae 
0018

  000A: B9 03 00 00 00 mov ecx,3
  000F: 48 83 EC 20sub rsp,20h
  0013: E8 00 00 00 00 call
_D5test28__assertFiZv

  0018: 31 C0  xor eax,eax
  001A: 5D pop rbp
  001B: C3 ret
=

Now compiling in release mode:
dmd -release testfile.d

No assert in sight:
=
_Dmain:
  : 55 pushrbp
  0001: 48 8B EC   mov rbp,rsp
  0004: 31 C0  xor eax,eax
  0006: 5D pop rbp
  0007: C3 ret
=


Re: Range non-emptyness assertions and opIndex

2016-07-01 Thread ag0aep6g via Digitalmars-d-learn

On 07/01/2016 12:35 PM, Nordlöw wrote:

What's the preferred way of reacting to emptyness in the members front,
back, popFront, popBack --- using assert, enforce, throw, or simply
relying on range-checking in the _store?


I think assert is the most common way of checking. Simply ignoring the 
possibility is also common, as it's considered a programming error to 
call front/popFront/etc on an empty range.


For the same reason, throwing an exception (via throw or via enforce) is 
less common. Exceptions are more for input/environment errors, not so 
much for programming errors.



And what about using

 debug assert()

instead of

 assert()

typically when `_store`s `opIndex` already performs range-checking?

I think this is a important issue since asserts are not optimized away
in release mode and D is very much about performance.


Huh? Asserts are ignored with -release. The only exception is 
assert(false) which terminates the program immediately, even with -release.


A little example program:


void main()
{
import std.stdio;
int x = 1;
assert(x != 1);
writeln("hi");
}


When compiled without -release, the program throws an AssertError. With 
-release it prints "hi".


Range non-emptyness assertions and opIndex

2016-07-01 Thread Nordlöw via Digitalmars-d-learn

If I have a typical range definition like the following

struct Range
{
@safe pure @nogc:

bool empty() const nothrow
{
return _i == _j;
}

size_t length() const nothrow
{
return _j - _i;
}

bool front() const
{
assert(!empty); // TODO use enforce when it's 
@nogc

return _store[_i];
}

bool back() const
{
assert(!empty); // TODO use enforce when it's 
@nogc

return _store[_j - 1];
}

void popFront()
{
assert(!empty);
++_i;
}

void popBack()
{
assert(!empty);
++_i;
}

private:
BitSet _store;  // copy of store
size_t _i = 0; // iterator into _store
size_t _j = _store.length;
}

What's the preferred way of reacting to emptyness in the members 
front, back, popFront, popBack --- using assert, enforce, throw, 
or simply relying on range-checking in the _store?


And what about using

debug assert()

instead of

assert()

typically when `_store`s `opIndex` already performs 
range-checking?


I think this is a important issue since asserts are not optimized 
away in release mode and D is very much about performance.