Re: Compile-time variables

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

On Friday, 6 April 2018 at 02:18:28 UTC, Kayomn wrote:

On Friday, 6 April 2018 at 01:22:42 UTC, Kayomn wrote:

On Friday, 6 April 2018 at 01:14:37 UTC, ketmar wrote:

Kayomn wrote:


[...]


it is already done for you, free of charge.

class Node {}
class RootNode : Node {}
class SpriteNode : Node {}

void main () {
auto nodeId1 = typeid(Node);
auto nodeId2 = typeid(SpriteNode);
auto comparison = typeid(Node);

Node n = new SpriteNode();

assert(typeid(Node) is typeid(Node)); // obviously
assert(typeid(SpriteNode) !is typeid(Node)); // sure
assert(typeid(Node) is nodeId1);
assert(typeid(n) is nodeId2);
}


Oh neat, thanks. I've been really scraping my head over this, 
and was worried I wouldn't be able to keep supporting my D 
version of the project.


Hmm... doesn't seem to operate at compile-time, which is an 
issue if I want to use it in case switch table like I was going 
to:



switch (queryInteger(childJson,"type")) {
case NodeType.Sprite:
child = this.addChild!(Sprite)(childName);

break;

default:
child = this.addChild!(Node)(childName);

break;
}



Wrong example code, here's the correct example:

switch (queryString(childJson,"type")) {
case (typeof (Sprite).name):
child = this.addChild!(Sprite)(childName);

break;

case (typeof (Camera).name):
child = this.addChild!(Camera)(childName);

break;

default:
child = this.addChild!(Node)(childName);

break;
}



Re: Compile-time variables

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

On Friday, 6 April 2018 at 01:22:42 UTC, Kayomn wrote:

On Friday, 6 April 2018 at 01:14:37 UTC, ketmar wrote:

Kayomn wrote:


[...]


it is already done for you, free of charge.

class Node {}
class RootNode : Node {}
class SpriteNode : Node {}

void main () {
auto nodeId1 = typeid(Node);
auto nodeId2 = typeid(SpriteNode);
auto comparison = typeid(Node);

Node n = new SpriteNode();

assert(typeid(Node) is typeid(Node)); // obviously
assert(typeid(SpriteNode) !is typeid(Node)); // sure
assert(typeid(Node) is nodeId1);
assert(typeid(n) is nodeId2);
}


Oh neat, thanks. I've been really scraping my head over this, 
and was worried I wouldn't be able to keep supporting my D 
version of the project.


Hmm... doesn't seem to operate at compile-time, which is an issue 
if I want to use it in case switch table like I was going to:



switch (queryInteger(childJson,"type")) {
case NodeType.Sprite:
child = this.addChild!(Sprite)(childName);

break;

default:
child = this.addChild!(Node)(childName);

break;
}



Re: Game and GC

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

On Friday, 23 February 2018 at 03:25:33 UTC, Norm wrote:

On Friday, 23 February 2018 at 01:54:07 UTC, Leonardo wrote:

Hi, I'm new to language and games.
Many people say that GC is bad and can slow down your project 
in some moments.
What can happen if I create a game using D without worrying 
with memory management?

(using full GC)


Have a look at https://github.com/gecko0307/atrium and see how 
memory is handled there.


TBH though every game I've written I have not worried about the 
GC and just code it up. This works fine for 2d games, 
platformers etc. If it ever does bite you can always schedule 
the pauses (they are deterministic in the sense a collect will 
occur on allocation) or do pretty much what every game does in 
C++/C and allocate in pools.


Cheers,
Norm


Atrium game use Dlib, more specific this module to manually 
manage memory.

Appears to be very easy to use. Thanks.
https://github.com/gecko0307/dlib/wiki/dlib.core.memory


Re: Compile-time variables

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

On Friday, 6 April 2018 at 01:14:37 UTC, ketmar wrote:

Kayomn wrote:


[...]


it is already done for you, free of charge.

class Node {}
class RootNode : Node {}
class SpriteNode : Node {}

void main () {
auto nodeId1 = typeid(Node);
auto nodeId2 = typeid(SpriteNode);
auto comparison = typeid(Node);

Node n = new SpriteNode();

assert(typeid(Node) is typeid(Node)); // obviously
assert(typeid(SpriteNode) !is typeid(Node)); // sure
assert(typeid(Node) is nodeId1);
assert(typeid(n) is nodeId2);
}


Oh neat, thanks. I've been really scraping my head over this, and 
was worried I wouldn't be able to keep supporting my D version of 
the project.


Re: Compile-time variables

2018-04-05 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, April 06, 2018 00:35:39 Kayomn via Digitalmars-d-learn wrote:
> On Friday, 6 April 2018 at 00:21:54 UTC, H. S. Teoh wrote:
> > On Thu, Apr 05, 2018 at 11:53:00PM +, Kayomn via
> > Digitalmars-d-learn wrote: [...]
> >
> >> [...]
> >
> > [...]
> >
> >> [...]
> >
> > `lastID`, as declared above, are runtime variables. The
> > 'static' in this case just means it's thread-local, rather than
> > allocated on the stack. You cannot modify these variables at
> > compile-time.
> >
> >> [...]
> >
> > You appear to be wanting to increment a global variable during
> > compile-time. Unfortunately, there is no such thing as a
> > compile-time global variable.  You will have to find some other
> > way to implement what you want.
> >
> > One way to do this would be to use compile-time introspection
> > to construct a list of nodes, and then use a CTFE function or
> >
> > static foreach to generate node IDs all at once.  For example:
> > string generateEnum(T...)()
> > {
> >
> > if (__ctfe) { // only run at compile-time
> >
> > string code = "enum NodeIds {";
> > foreach (ident; T) {
> >
> > code ~= ident ~ ", ";
> >
> > }
> > code ~= "}";
> > return code;
> >
> > }
> > else assert(0);
> >
> > }
> >
> > alias MyNodes = List!(
> >
> > // Just an example; you probably want to generate this
> > // list via introspection, e.g. via __traits(getMembers)
> > // or something like that.
> > identifier1,
> > identifier2,
> > ...
> >
> > );
> >
> > mixin(generateEnum!MyNodes); // defines `enum NodeIds`
> >
> > static assert(NodeIds.identifier1 == 0);
> > static assert(NodeIds.identifier2 == 1);
> > ...
> >
> > There are probably other ways to do it too, but I chose enum
> > because it naturally assigns incrementing IDs to its members,
> > so it's a convenient construct for this purpose.
> >
> >
> > T
>
> I think I didn't explain well enough, I'm not trying to generate
> an enum from a list of pre-defined known quantities. The idea is
> that a compile-time generic function exists and it generates a
> unique identifier for that node.
>
> My reasons for doing this is to remove the need to keep a master
> enum that holds an identifying value for each node. I've
> implemented this same thing in C++ before and it was extremely
> straightforward.

If you want to generate a value using CTFE, then you can use a normal
function that simply takes arguments and returns a value, and you can use
enums that already have a value. So, you can do something like

enum foo = "string";
enum bar = baz("2");

string baz(string str)
{
return foo ~ str;
}

void main()
{
assert(foo == "string");
assert(bar == "string2");
}

but you can't use any variables other than local variables unless they're
const or immutable. So, you can't do something like increment a global
variable. It's is absolutely impossible to do something like

enum id = getID();

and have getID return a different value on each call. So, if you're looking
to do something like

enum value1 = getID();
enum value2 = getID();
enum value3 = getID();
enum value4 = getID();

and have each of those enums have a unique ID, then you are completely out
of luck. You'll need go about solving the problem in a different way, be it
by passing different values to the function being used so that it can
generate different values on each call:

enum value1 = getID(1);
enum value2 = getID(2);
enum value3 = getID(3);
enum value4 = getID(4);

or by generating a string to mix in as code as H. S. Teoh suggested.
Eponymous templates or template mixins could also be used, but they don't
really do anything more, just differently, and usually less efficiently.

Basically, even though functions used during CTFE don't have to be marked
with pure, they effectively have to be pure in order to work. So, if you try
to initialize an enum with the result of a function call, the only way you
have to alter the output is to pass in different arguments. If you need any
kind of state to be maintained in order to initialize multiple enums with
values that relate to one another (e.g. an incrementing ID), then a mixin is
your only choice.

If you can initialize what you need to initialize at runtime (meaning that
it can't be an enum), then you have more options, but at compile time,
initializations have to be pure.

- Jonathan M Davis



Re: Compile-time variables

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

Kayomn wrote:


I'll give a better example of what it is I'm trying to do.

These are node types. Their contents are not important in this 
explanation, only that they operate as a tree structure.


class Node;

class RootNode : Node;

class SpriteNode : Node;

The result of getNodeID on a specific type is always the same. A value 
representing it that is applied during compilation. The value does not 
matter to the programmer, only that it is unique and gets applied.


--
uint nodeId1 = getNodeID!(Node)(); // 0.

uint nodeId2 = getNodeID!(SpriteNode)(); // 1.

uint comparison = getNodeID!(Node)(); // 0.

// True.
if (getNodeID!(Node)() == getNodeID!(Node)()) {

}

// False.
if (getNodeID!(SpriteNode)() == getNodeID!(Node)()) {

}
--


it is already done for you, free of charge.

class Node {}
class RootNode : Node {}
class SpriteNode : Node {}

void main () {
auto nodeId1 = typeid(Node);
auto nodeId2 = typeid(SpriteNode);
auto comparison = typeid(Node);

Node n = new SpriteNode();

assert(typeid(Node) is typeid(Node)); // obviously
assert(typeid(SpriteNode) !is typeid(Node)); // sure
assert(typeid(Node) is nodeId1);
assert(typeid(n) is nodeId2);
}


Re: Compile-time variables

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

I'll give a better example of what it is I'm trying to do.

These are node types. Their contents are not important in this 
explanation, only that they operate as a tree structure.


class Node;

class RootNode : Node;

class SpriteNode : Node;

The result of getNodeID on a specific type is always the same. A 
value representing it that is applied during compilation. The 
value does not matter to the programmer, only that it is unique 
and gets applied.


--
uint nodeId1 = getNodeID!(Node)(); // 0.

uint nodeId2 = getNodeID!(SpriteNode)(); // 1.

uint comparison = getNodeID!(Node)(); // 0.

// True.
if (getNodeID!(Node)() == getNodeID!(Node)()) {

}

// False.
if (getNodeID!(SpriteNode)() == getNodeID!(Node)()) {

}
--


Re: Compile-time variables

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

On Friday, 6 April 2018 at 00:21:54 UTC, H. S. Teoh wrote:
On Thu, Apr 05, 2018 at 11:53:00PM +, Kayomn via 
Digitalmars-d-learn wrote: [...]

[...]

[...]

[...]


`lastID`, as declared above, are runtime variables. The 
'static' in this case just means it's thread-local, rather than 
allocated on the stack. You cannot modify these variables at 
compile-time.




[...]


You appear to be wanting to increment a global variable during 
compile-time. Unfortunately, there is no such thing as a 
compile-time global variable.  You will have to find some other 
way to implement what you want.


One way to do this would be to use compile-time introspection 
to construct a list of nodes, and then use a CTFE function or 
static foreach to generate node IDs all at once.  For example:


string generateEnum(T...)()
{
if (__ctfe) { // only run at compile-time
string code = "enum NodeIds {";
foreach (ident; T) {
code ~= ident ~ ", ";
}
code ~= "}";
return code;
}
else assert(0);
}

alias MyNodes = List!(
// Just an example; you probably want to generate this
// list via introspection, e.g. via __traits(getMembers)
// or something like that.
identifier1,
identifier2,
...
);

mixin(generateEnum!MyNodes); // defines `enum NodeIds`

static assert(NodeIds.identifier1 == 0);
static assert(NodeIds.identifier2 == 1);
...

There are probably other ways to do it too, but I chose enum 
because it naturally assigns incrementing IDs to its members, 
so it's a convenient construct for this purpose.



T


I think I didn't explain well enough, I'm not trying to generate 
an enum from a list of pre-defined known quantities. The idea is 
that a compile-time generic function exists and it generates a 
unique identifier for that node.


My reasons for doing this is to remove the need to keep a master 
enum that holds an identifying value for each node. I've 
implemented this same thing in C++ before and it was extremely 
straightforward.


Re: Compile-time variables

2018-04-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Apr 05, 2018 at 11:53:00PM +, Kayomn via Digitalmars-d-learn wrote:
[...]
> ---
> alias NodeTypeID = uint;
> 
> enum NodeTypeID getNodeID() {
>   static NodeTypeID lastID = 0;
> 
>   return lastID++;
> }
> 
> enum NodeTypeID getNodeID(T)() {
>   static NodeTypeID typeID = getNodeID();
> 
>   return typeID;
> }
> ---
> 
> The expectation is that this is executed at compile time,
[...]
> However, I've been struggling with an error pertaining to getNodeType.
> The return statement of lastID++ is flagging the error "Static
> variable cannot be read at compile time."

`lastID`, as declared above, are runtime variables. The 'static' in this
case just means it's thread-local, rather than allocated on the stack.
You cannot modify these variables at compile-time.


> I may just be taking too much of a C++ lens to this, but to me this
> seems like it should work? Am I missing a qualifier or something here?

You appear to be wanting to increment a global variable during
compile-time. Unfortunately, there is no such thing as a compile-time
global variable.  You will have to find some other way to implement what
you want.

One way to do this would be to use compile-time introspection to
construct a list of nodes, and then use a CTFE function or static
foreach to generate node IDs all at once.  For example:

string generateEnum(T...)()
{
if (__ctfe) { // only run at compile-time
string code = "enum NodeIds {";
foreach (ident; T) {
code ~= ident ~ ", ";
}
code ~= "}";
return code;
}
else assert(0);
}

alias MyNodes = List!(
// Just an example; you probably want to generate this
// list via introspection, e.g. via __traits(getMembers)
// or something like that.
identifier1,
identifier2,
...
);

mixin(generateEnum!MyNodes); // defines `enum NodeIds`

static assert(NodeIds.identifier1 == 0);
static assert(NodeIds.identifier2 == 1);
...

There are probably other ways to do it too, but I chose enum because it
naturally assigns incrementing IDs to its members, so it's a convenient
construct for this purpose.


T

-- 
Having a smoking section in a restaurant is like having a peeing section in a 
swimming pool. -- Edward Burr 


Compile-time variables

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

Hi,

I've got a scene graph which contains multiple inheriting types. 
As such, I've been tagging them with a type enum for whenever I 
need to do things such as loading a structure from binary.


Up until now I've been using an enum that looks like this:

---
enum NodeType : uint {
None,
Root,
Sprite,
Camera
}
---

I'm trying to implement a dynamic type ID assignment system that 
utilizes D generics to generate an incremental, unique identifier 
for each node without needing to continuously update a master 
list. This is what I have so far:


---
alias NodeTypeID = uint;

enum NodeTypeID getNodeID() {
static NodeTypeID lastID = 0;

return lastID++;
}

enum NodeTypeID getNodeID(T)() {
static NodeTypeID typeID = getNodeID();

return typeID;
}
---

The expectation is that this is executed at compile time, 
generating a specific function for the given generic parameter 
each time the generic is used, incrementing the static variable 
by 1 and having the compiled generic functions essentially 
contain magic number unique to its type. So, I would be able to 
employ this like so:


---
switch (someNodeTypeID) {
case getNodeID!(Sprite)(): // Sprite node-specific behavior.
break;

case getNodeID!(Camera)(): // Camera node-specific behavior.
break;

default: // Default behavior.
break;
}
---

However, I've been struggling with an error pertaining to 
getNodeType. The return statement of lastID++ is flagging the 
error

"Static variable cannot be read at compile time."

I may just be taking too much of a C++ lens to this, but to me 
this seems like it should work? Am I missing a qualifier or 
something here?


Re: Construct immutable member in derived class

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

On Thursday, 5 April 2018 at 19:31:39 UTC, Jonathan M Davis wrote:
And you can't abstract whether a member variable is marked with 
immutable or not. That's part of the variable. Declaring an 
immutable instance of an object would then treat the member 
variable in immutable for that instance, so it's possible to 
have an immutable member variable when the member variable is 
not itself marked with immutable, but class inheritance has 
nothing to do with controlling which type qualifiers were used 
on the member variable of a base class. Derived classes 
override member functions. They don't override member variables 
or anything about them. They override the behavior of the base 
class, not the structure.


That beats my argumentation. Fully agree with that.

For them to do otherwise would become quite problematic if you 
ever use a derived class through a base class reference. They 
can add onto the structure of a base class, but the derived 
class must be usuable via a base class reference, and trying to 
do something like have the derived class alter the qualifiers 
on base class member variable simply would not work with that. 
That sort of thing could only ever work if the base class were 
just a way to add functionality to a derived class rather than 
having anything to do with references, and that's simply not 
how classes work in D. If that's the sort of thing that you 
want, it would make more sense to add the functionality via 
composition rather than inheritance.


Yeah... little bit of mixing things up in my head, maybe... Did 
exactly this stuff during the last couple of months.


Thanks a lot!


Re: Issues using the in-line assembler

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

Seems I found a better solution hidden in the docs:

@nogc protected int[2] transformFunc(int[2] xy){
version(X86){
asm @nogc{
naked;
mov EBX, this;
movdXMM1, sX[EBX];
pslldq  XMM1, 4;
movss   XMM1, sY[EBX];
movqXMM0, xy;
paddd   XMM0, XMM1; // [x,y] + [sX,sY]
movqXMM3, xy0[EBX];
psubd   XMM0, XMM3; // ([x,y] + [sX,sY] - [x_0,y_0])
movqXMM1, ac[EBX];
movqXMM2, bd[EBX];
pmuludq XMM1, XMM0; // [A,0,C,0] * ([x,y] + [sX,sY] - 
[x_0,y_0])
	psrlq		XMM1, 16;	// ([A,0,C,0] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16

movups  XMM4, XMM0;
psrldq  XMM4, 4;
pslldq  XMM0, 4;
por XMM4, XMM0;
pmuludq XMM2, XMM4; // [0,B,0,D] * ([x,y] + [sX,sY] - [x_0,y_0])
	psrlq		XMM2, 16;	// ([0,B,0,D] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16
	paddq		XMM1, XMM2; // ([A,B,C,D] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16

punpckldq   XMM3, XMM7;
	paddq		XMM1, XMM3;	// ([A,B,C,D] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16 + [x_0,y_0]

movups  XMM0, XMM1; // Convert 64 bit vectors into 32 bit 
ones
psrldq  XMM0, 4;
por XMM0, XMM1; 
ret ;
}
}(...)
}


Re: Issues using the in-line assembler

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

On Thursday, 5 April 2018 at 04:48:02 UTC, Basile B. wrote:
The "this" seems to be in R11, so you have to apply the asm 
syntax for accessing the members using 
.offsetof.[R11], example:


```
class Foo
{
double a = 123456;
extern(D) double foo()
{
asm
{
naked;
movqXMM0, Foo.a.offsetof[R11];
ret;
}
}
}

void main()
{
import std.stdio;
(new Foo).foo(0,0).writeln;
}
```

However i cant find any specification saying that R11 is "this".
With a free function just pass the instance as param and 
replace R11 by the register where the instance is passed.


It seems that the compiler lets it through if I change it like 
this:


asm @nogc{
naked;
movdXMM1, dword ptr sX[EBP];
pslldq  XMM1, 4;
movss   XMM1, dword ptr sY[EBP];
movqXMM0, xy;
paddd   XMM0, XMM1; // [x,y] + [sX,sY]
movqXMM3, qword ptr xy0[EBP];
psubd   XMM0, XMM3; // ([x,y] + [sX,sY] - [x_0,y_0])
movqXMM1, qword ptr ac[EBP];
movqXMM2, qword ptr bd[EBP];
pmuludq XMM1, XMM0; // [A,0,C,0] * ([x,y] + [sX,sY] - 
[x_0,y_0])
	psrlq		XMM1, 16;	// ([A,0,C,0] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16

movups  XMM4, XMM0;
psrldq  XMM4, 4;
pslldq  XMM0, 4;
por XMM4, XMM0;
pmuludq XMM2, XMM4; // [0,B,0,D] * ([x,y] + [sX,sY] - [x_0,y_0])
	psrlq		XMM2, 16;	// ([0,B,0,D] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16
	paddq		XMM1, XMM2; // ([A,B,C,D] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16

punpckldq   XMM3, XMM7;
	paddq		XMM1, XMM3;	// ([A,B,C,D] * ([x,y] + [sX,sY] - 
[x_0,y_0]))>>16 + [x_0,y_0]

movups  XMM0, XMM1; // Convert 64 bit vectors into 32 bit 
ones
psrldq  XMM0, 4;
por XMM0, XMM1; 
ret ;
}
I wonder if I can return an int[2] in XMM0. I can do some 
modifications to either move the result to the stack first, or 
add an import to core.simd (which needs to be refactored 
completely) and instead make the return type int4 on SIMD enabled 
CPUs.


Re: Idiomatic error handling for ranges

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

On Thursday, 5 April 2018 at 17:36:56 UTC, Seb wrote:

On Thursday, 5 April 2018 at 17:06:04 UTC, rumbu wrote:
Is there a standard way to handle errors in a chain of range 
transformations?


[...]


Are you aware of ifThrown?

https://dlang.org/phobos/std_exception.html#ifThrown

It's not perfect, but imho a nice start and one of the places 
where lazy really shines.


Thanks, ifThrown is perfect.


Re: Construct immutable member in derived class

2018-04-05 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, April 05, 2018 13:36:07 Alex via Digitalmars-d-learn wrote:
> On Wednesday, 4 April 2018 at 21:49:08 UTC, Timoses wrote:
> > "[...] the construction of the base class can be independent
> > from the derived one."
> >
> > Hm, the points 7 and 8 don't clearly state what you wrote.
>
> Yes :)
>
> > But it somehow does make sense.. Still I wonder why that is so.
> >
> > Let's say you have an abstract class with immutable members.
> > Why shouldn't derived class constructors be allowed to
> > initialize these immutable members?
>
> My reason is a semantic one, so it's rather how I'm explaining
> this to me, then a formal one.
>
> Let's assume, we abstract away a member from different derived
> classes to an abstract class, which cannot be handled by this
> abstract class.
> Ok, this can happen, so it would be ok, if the base class does
> not handle the var.
>
> But then, we add a qualifier. How can this be? As the abstract
> class cannot handle the abstraction, it also can not add any
> qualifiers.
> As the qualifier is there, then, the base class at least has
> knowledge about the immutability. And due this fact, its own
> constructor has to handle this variable in some way.
>
> However, this a minor problem, isn't it? If you argue, that you
> can also abstract the immutability qualifier, then, I would say,
> that a derived class always has a better knowledge how to handle
> its members, and therefore how to call the base class
> constructor, as it knows which class it is derived from.
>
> So, for short:
> Either: the immutability belongs to the base class and therefore
> it has to manage the var
> Or: it doesn't and the derived classes have the knowledge how to
> serve their base class.

The reality of the matter is that a member variable is a member of the class
that it's in and _must_ be handled by that class. If it's not directly
initialized in its declaration or initialized in that class' constructor,
then it gets a default value. Derived classes have _zero_ control over that.
They can mutate a public or protected mutable member of a base class, but
that member variable still has to be initialized by the base class, not the
derived class.

And you can't abstract whether a member variable is marked with immutable or
not. That's part of the variable. Declaring an immutable instance of an
object would then treat the member variable in immutable for that instance,
so it's possible to have an immutable member variable when the member
variable is not itself marked with immutable, but class inheritance has
nothing to do with controlling which type qualifiers were used on the member
variable of a base class. Derived classes override member functions. They
don't override member variables or anything about them. They override the
behavior of the base class, not the structure. For them to do otherwise
would become quite problematic if you ever use a derived class through a
base class reference. They can add onto the structure of a base class, but
the derived class must be usuable via a base class reference, and trying to
do something like have the derived class alter the qualifiers on base class
member variable simply would not work with that. That sort of thing could
only ever work if the base class were just a way to add functionality to a
derived class rather than having anything to do with references, and that's
simply not how classes work in D. If that's the sort of thing that you want,
it would make more sense to add the functionality via composition rather
than inheritance.

- Jonathan M Davis



Re: [OT] Re: merkle reverse

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

On Thursday, 5 April 2018 at 14:58:21 UTC, Andy Smith wrote:

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


Yeah. Angela did some messing around with Shadow Volume 
algorithms before she got into politics...


:-)

Cheers,

A.


Is not merkel is merkle, :P




Re: Construct immutable member in derived class

2018-04-05 Thread Timoses via Digitalmars-d-learn
On Wednesday, 4 April 2018 at 22:47:07 UTC, Jonathan M Davis 
wrote:
Because doing that basically makes it impossible to guarantee 
that the type system isn't violated. Once an immutable variable 
has been initialized, its value must _never_ change. It must be 
initalized exactly once, and the compiler doesn't necessarily 
have any clue what the base class constructors did or didn't 
do. There's no guarantee that it even has access to the 
function bodies for the base class when compiling the derived 
class. So, there is no way for it to safely put off the 
initialization of any base class members for the derived class 
to do.


- Jonathan M Davis


Ah, makes sense. I was looking for a somewhat technical answer. 
Thanks for that : ).


Re: Idiomatic error handling for ranges

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

On Thursday, 5 April 2018 at 17:06:04 UTC, rumbu wrote:
Is there a standard way to handle errors in a chain of range 
transformations?


[...]


Are you aware of ifThrown?

https://dlang.org/phobos/std_exception.html#ifThrown

It's not perfect, but imho a nice start and one of the places 
where lazy really shines.


Re: Idiomatic error handling for ranges

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

On Thursday, 5 April 2018 at 17:06:04 UTC, rumbu wrote:
Is there a standard way to handle errors in a chain of range 
transformations?


Let's say I want to read some comma separated numbers from a 
file.


auto myArray = file.byLine().splitter().map!(to!int).array();

Now, besides fatal errors (like I/O), let's suppose I want to 
handle some errors in a silent way:

- skip unicode decoding errors;
- assume blank records with 0;
- skip the line entirely if the conversion to int is not 
possible;


I can catch UTFException, ConvException or 
ConvOverflowException for the entire syntax chain but there are 
some disadvantages:
- I don't know exactly which of the chain members thrown the 
exception;

- I cannot skip/handle the error and continue;

The only solution I thought about is to break the nice chain 
syntax and handle errors on each of the chain members, but I 
wonder if there is probably another way.


Thanks.


You could use predicates:

```
string list = "3, 5, 1, , not a number, 100";

int[] numbers = list.split(",").filter!((entry) {
if (!isNumeric(entry.strip))
return false;
else // ... even more cases?
return true;
})
.map!((e) => e.strip.to!int).array;

assert(numbers == [3, 5, 1, 100]);
```
https://run.dlang.io/gist/413282d9726dbac137bf5f35033a8eea


Idiomatic error handling for ranges

2018-04-05 Thread rumbu via Digitalmars-d-learn
Is there a standard way to handle errors in a chain of range 
transformations?


Let's say I want to read some comma separated numbers from a file.

auto myArray = file.byLine().splitter().map!(to!int).array();

Now, besides fatal errors (like I/O), let's suppose I want to 
handle some errors in a silent way:

- skip unicode decoding errors;
- assume blank records with 0;
- skip the line entirely if the conversion to int is not possible;

I can catch UTFException, ConvException or ConvOverflowException 
for the entire syntax chain but there are some disadvantages:
- I don't know exactly which of the chain members thrown the 
exception;

- I cannot skip/handle the error and continue;

The only solution I thought about is to break the nice chain 
syntax and handle errors on each of the chain members, but I 
wonder if there is probably another way.


Thanks.







[OT] Re: merkle reverse

2018-04-05 Thread Andy Smith 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


Yeah. Angela did some messing around with Shadow Volume 
algorithms before she got into politics...


:-)

Cheers,

A.



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: Construct immutable member in derived class

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

On Wednesday, 4 April 2018 at 21:49:08 UTC, Timoses wrote:
"[...] the construction of the base class can be independent 
from the derived one."


Hm, the points 7 and 8 don't clearly state what you wrote.


Yes :)


But it somehow does make sense.. Still I wonder why that is so.

Let's say you have an abstract class with immutable members. 
Why shouldn't derived class constructors be allowed to 
initialize these immutable members?


My reason is a semantic one, so it's rather how I'm explaining 
this to me, then a formal one.


Let's assume, we abstract away a member from different derived 
classes to an abstract class, which cannot be handled by this 
abstract class.
Ok, this can happen, so it would be ok, if the base class does 
not handle the var.


But then, we add a qualifier. How can this be? As the abstract 
class cannot handle the abstraction, it also can not add any 
qualifiers.
As the qualifier is there, then, the base class at least has 
knowledge about the immutability. And due this fact, its own 
constructor has to handle this variable in some way.


However, this a minor problem, isn't it? If you argue, that you 
can also abstract the immutability qualifier, then, I would say, 
that a derived class always has a better knowledge how to handle 
its members, and therefore how to call the base class 
constructor, as it knows which class it is derived from.


So, for short:
Either: the immutability belongs to the base class and therefore 
it has to manage the var
Or: it doesn't and the derived classes have the knowledge how to 
serve their base class.


Re: merkle reverse

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

On Thursday, 5 April 2018 at 09:24:31 UTC, SimonN wrote:

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).


Well sorry for my poor words.
Strings are bi-directional ranges, but they aren't random-access 
nor have a length which is typically required by other ranges to 
forward bidirectionality.


chunks requires hasSlicing + hasLength:

https://github.com/dlang/phobos/blob/193c61d985a9645014b2161b59ddb8692308e063/std/range/package.d#L7851

slide requires just hasSlicing:

https://github.com/dlang/phobos/blob/193c61d985a9645014b2161b59ddb8692308e063/std/range/package.d#L8650

Now why does "aa"[0.. 1] work, but hasSlicing return false?
Because it's explicitly excluded:

https://github.com/dlang/phobos/blob/193c61d985a9645014b2161b59ddb8692308e063/std/range/primitives.d#L1557

tl;dr: if you want to do anything useful with strings, byCodeUnit 
is usually your best friend.


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 Seb via Digitalmars-d-learn

On Thursday, 5 April 2018 at 08:57:11 UTC, SimonN wrote:

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


FYI: The problem isn't chunks, but that strings aren't 
bi-directional ranges (hello ugly auto-decoding!).

Simply disable it with byCodeUnit:

---
import std.experimental.all;
void main()
{

"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".byCodeUnit.chunks(2).retro.joiner.writeln;

"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".byCodeUnit.slide(2, 2).retro.joiner.writeln;

}
---

Oh and the new slide is a generalization of chunks.

https://run.dlang.io/is/ggrh14


Re: merkle reverse

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

05.04.2018 11:57, SimonN пишет:


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


It's a pity that retro can't work with chunks without array, it would be 
really nice!


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


merkle reverse

2018-04-05 Thread aerto via Digitalmars-d-learn
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