Re: Interior immutability and rvalues

2016-07-15 Thread maik klein via Digitalmars-d-learn

On Friday, 15 July 2016 at 12:05:47 UTC, ag0aep6g wrote:

On 07/15/2016 10:29 AM, maik klein wrote:

[...]


Sure. Just instantiate Rc with a const/immutable T. I.e., write 
`Rc!(const int)` instead of `const Rc!int`. Or with auto and 
makeRc: `auto rc = makeRc(immutable int(5));`.



[...]


When you pass an rvalue to a function, the parameter inside the 
function is still an lvalue. The argument being an rvalue just 
means that you can't pass it in a ref parameter.



[...]


Ok, not being copyable is the problem.


[...]


If args[0] can be moved, can args[1] and args[2] be moved, too? 
I mean, can you just move everything without testing for 
hasElaborateCopyConstructor? Just a thought.


Thanks I didn't know that you could have type qualifiers inside 
templates, D still surprises me sometimes.


I don't think it is practical to call move on "everything", for 
example maybe you just want to pass a `ref` or a `class`.


Interior immutability and rvalues

2016-07-15 Thread maik klein via Digitalmars-d-learn

There are two things that bothered me for quite some time

Interior immutability:

Consider a something like this

https://dpaste.dzfl.pl/fa5be84d26bc

The implementation is totally wrong and it doesn't make sense, 
but it shows that Rc can not be const/immutable because at least 
"dup" needs to increment the counter.


Is it possible to express that Rc should be mutable but the value 
that it wraps should be either mutable or const/immutable?


Rvalues and forwarding:

The problem is that when you pass an rvalue to a function you 
lose the information that is an rvalue. There is nothing like 
std::forward from c++ that I am aware of.


That becomes a problem when I use variadics with non copyable 
types. I need to call move on types that can not be copied.


I guess what I could do is to use 
https://dlang.org/phobos/std_traits.html#hasElaborateCopyConstructor to detect which types in the variadic args are actually non copyable and then call .move on them.


Is this how you would do it? The use case would be something like 
this


void test(Args...)(Args args){
someOtherTest(args); // doesn't work because args contains 
some non copyable types

}

void test(Args...)(Args args){
someOtherTest(mixin forward!(args));
}

//expands to

void test(Args...)(Args args){
someOtherTest(args[0].move, args[1], args[2]);
}


Implicit conversion without alias this?

2016-06-03 Thread maik klein via Digitalmars-d-learn

I have my own version of Algebraic

struct Ok(T){
T value;
}

struct Err(E){
E value;
}

auto ok(T)(auto ref T value){
return Ok!T(value);
}

auto err(E)(auto ref E err){
return Err!E(err);
}

alias Result(T, E) = Algebraic!(Ok!T, Err!E);

I have a constructor and opAssign which allows me to write

Result!(int, string) res = ok(5);

But it seems strange that I can not do the same thing to function 
returns


Result!(int, string) test(){
return ok(5); // Error: cannot implicitly convert expression 
(ok(5)) of type Ok!int to Algebraic!(Ok!int, Err!string)

}

I can not add implicit conversion with alias this from Ok!T to 
Result!(T, ???) because "Ok" doesn't know about the error type.


That is a bit unergonomic because I always seem to need the full 
type


like

auto ok(T, E)(auto ref T value){
return Result!(T, E)(Ok!T(value));
}

I basically try to mirror 
http://rustbyexample.com/std/result.html but I don't think that 
is possible.


Any ideas?





Re: Linking a shared library in dub

2016-03-30 Thread maik klein via Digitalmars-d-learn

On Thursday, 31 March 2016 at 00:06:19 UTC, maik klein wrote:

On Wednesday, 30 March 2016 at 17:38:15 UTC, maik klein wrote:
On Wednesday, 30 March 2016 at 12:46:08 UTC, Vadim Lopatin 
wrote:

On Wednesday, 30 March 2016 at 12:19:34 UTC, maik klein wrote:
I want to finally convert my project to windows. That means 
that I want to build it on windows and linux.


The problem is that I have one external c library 'glfw'. I 
thought that I would just link with it explicitly but 
actually I am not completely sure how.


Try using Derelict based binding

http://code.dlang.org/packages/derelict-glfw3


I am already using the derelict binding but I want to 
explicitly link with the .a or .so c lib because I don't have 
a package manager on windows.


Okay I think I understand know what you mean, I think you meant 
I should use dynamic loading like this right?


DerelictGLFW3.load("deps/glfw/build/src/libglfw.so");

This works but I am not sure yet that I want to load it at the 
application level.


I was able to link with a static lib like this

dependency "derelict-glfw3" version="~>2.0.0"
subConfiguration "derelict-glfw3" "derelict-glfw3-static"
sourceFiles "deps/glfw/build/src/libglfw3.a"
libs "Xi" "pthread" "X11" "Xxf86vm" "Xrandr" "pthread" "GL" "GLU" 
"Xinerama" "Xcursor"




Re: Linking a shared library in dub

2016-03-30 Thread maik klein via Digitalmars-d-learn

On Wednesday, 30 March 2016 at 17:38:15 UTC, maik klein wrote:
On Wednesday, 30 March 2016 at 12:46:08 UTC, Vadim Lopatin 
wrote:

On Wednesday, 30 March 2016 at 12:19:34 UTC, maik klein wrote:
I want to finally convert my project to windows. That means 
that I want to build it on windows and linux.


The problem is that I have one external c library 'glfw'. I 
thought that I would just link with it explicitly but 
actually I am not completely sure how.


Try using Derelict based binding

http://code.dlang.org/packages/derelict-glfw3


I am already using the derelict binding but I want to 
explicitly link with the .a or .so c lib because I don't have a 
package manager on windows.


Okay I think I understand know what you mean, I think you meant I 
should use dynamic loading like this right?


DerelictGLFW3.load("deps/glfw/build/src/libglfw.so");

This works but I am not sure yet that I want to load it at the 
application level.


Re: Linking a shared library in dub

2016-03-30 Thread maik klein via Digitalmars-d-learn

On Wednesday, 30 March 2016 at 12:46:08 UTC, Vadim Lopatin wrote:

On Wednesday, 30 March 2016 at 12:19:34 UTC, maik klein wrote:
I want to finally convert my project to windows. That means 
that I want to build it on windows and linux.


The problem is that I have one external c library 'glfw'. I 
thought that I would just link with it explicitly but actually 
I am not completely sure how.


Try using Derelict based binding

http://code.dlang.org/packages/derelict-glfw3


I am already using the derelict binding but I want to explicitly 
link with the .a or .so c lib because I don't have a package 
manager on windows.


Linking a shared library in dub

2016-03-30 Thread maik klein via Digitalmars-d-learn
I want to finally convert my project to windows. That means that 
I want to build it on windows and linux.


The problem is that I have one external c library 'glfw'. I 
thought that I would just link with it explicitly but actually I 
am not completely sure how.



So I just added a submodule, cloned glfw and build it as a shared 
library


lflags "deps/glfw/build/src/libglfw.so"


This is the eps/glfw/build/src folder:

total 196K
drwxr-xr-x 3 maik users 4.0K Mar 30 14:07 .
drwxr-xr-x 6 maik users 4.0K Mar 30 14:07 ..
drwxr-xr-x 3 maik users 4.0K Mar 30 14:07 CMakeFiles
-rw-r--r-- 1 maik users 2.1K Mar 30 14:07 cmake_install.cmake
-rw-r--r-- 1 maik users   56 Mar 30 14:07 glfw3Config.cmake
-rw-r--r-- 1 maik users 1.6K Mar 30 14:07 glfw3ConfigVersion.cmake
-rw-r--r-- 1 maik users  348 Mar 30 14:07 glfw3.pc
-rw-r--r-- 1 maik users 3.1K Mar 30 14:07 glfw_config.h
lrwxrwxrwx 1 maik users   12 Mar 30 14:07 libglfw.so -> 
libglfw.so.3
lrwxrwxrwx 1 maik users   14 Mar 30 14:07 libglfw.so.3 -> 
libglfw.so.3.2

-rwxr-xr-x 1 maik users 142K Mar 30 14:07 libglfw.so.3.2
-rw-r--r-- 1 maik users  18K Mar 30 14:07 Makefile


But If I try to build it with dub, i'll get "./bin/breeze_opengl: 
error while loading shared libraries: libglfw.so.3: cannot open 
shared object file: No such file or directory"


But as you can see it is in there. I get the same error with

lflags "deps/glfw/build/src/libglfw.so.3"
lflags "deps/glfw/build/src/libglfw.so.3.2"

Also the path seems to be correct because if I try to add a file 
that not exisit I get a different error

lflags "deps/glfw/build/src/doesnotexist.so"

/usr/bin/ld: cannot find deps/glfw/build/src/doesnotexist.so: No 
such file or directory

collect2: error: ld returned 1 exit status

Am I doing something wrong?


Re: I need some help benchmarking SoA vs AoS

2016-03-29 Thread maik klein via Digitalmars-d-learn

On Tuesday, 29 March 2016 at 21:27:15 UTC, ZombineDev wrote:

On Saturday, 26 March 2016 at 17:43:48 UTC, maik klein wrote:

On Saturday, 26 March 2016 at 17:06:39 UTC, ag0aep6g wrote:

On 26.03.2016 18:04, ag0aep6g wrote:

https://gist.github.com/aG0aep6G/a1b87df1ac5930870ffe/revisions


PS: Those enforces are for a size of 100_000 not 1_000_000, 
because I'm impatient.


Thanks, okay that gives me more more reliable results.
for 1_000_000

benchmarking complete access
AoS: 1 sec, 87 ms, 266 μs, and 4 hnsecs
SoA: 1 sec, 491 ms, 186 μs, and 6 hnsecs
benchmarking partial access
AoS: 7 secs, 167 ms, 635 μs, and 8 hnsecs
SoA: 1 sec, 20 ms, 573 μs, and 1 hnsec

This is sort of what I expected. I will do a few more 
benchmarks now. I probably also randomize the inputs.


Can you benchmark my implementation 
(http://dpaste.dzfl.pl/3de1e18756f8) against yours? It should 
have roughly the same API, except that mine doesn't support 
pre-allocation (reserving capacity) - I wanted to keep it 
minimalistic.
During access it should have the same performance, however the 
insertion behavior should be noticeably different. I'm 
interested to see if one larger allocation on insertion would 
be faster than a number of small ones (or vice-versa). Though, 
AoS should be the fastest in this regard (growth performance).


Yes I'll do it tomorrow, though I am not sure how much you can 
rely on the data. I think it really depends on how fragmented the 
heap currently is.


I will also benchmark memory access, just to see if there is any 
difference. I recently asked a question about it on SO 
https://stackoverflow.com/questions/36296960/pros-and-cons-of-one-big-buffer-vs-many-smaller-buffer?


Doesn't seem to be well received though.


Re: I need some help benchmarking SoA vs AoS

2016-03-26 Thread maik klein via Digitalmars-d-learn

On Saturday, 26 March 2016 at 17:06:39 UTC, ag0aep6g wrote:

On 26.03.2016 18:04, ag0aep6g wrote:

https://gist.github.com/aG0aep6G/a1b87df1ac5930870ffe/revisions


PS: Those enforces are for a size of 100_000 not 1_000_000, 
because I'm impatient.


Thanks, okay that gives me more more reliable results.
for 1_000_000

benchmarking complete access
AoS: 1 sec, 87 ms, 266 μs, and 4 hnsecs
SoA: 1 sec, 491 ms, 186 μs, and 6 hnsecs
benchmarking partial access
AoS: 7 secs, 167 ms, 635 μs, and 8 hnsecs
SoA: 1 sec, 20 ms, 573 μs, and 1 hnsec

This is sort of what I expected. I will do a few more benchmarks 
now. I probably also randomize the inputs.


I need some help benchmarking SoA vs AoS

2016-03-26 Thread maik klein via Digitalmars-d-learn
I recently wrote an article an SoA 
https://maikklein.github.io/post/soa-d/


But now I wanted to actually benchmark SoA vs AoS and it is so 
much harder than I thought.


In DMD SoA basically always beats AoS by a huge chuck. SoA is 
always at least twice as fast compared to AoS.


But with LDC it is just really hard to get reliable results.

I have created a example without any dependencies

http://dpaste.dzfl.pl/877a925e0a33

dub run -b release --compiler=dmd

benchmarking complete access
AoS: 419 ms, 938 μs, and 2 hnsecs
SoA: 11 μs and 8 hnsecs
benchmarking partial access
AoS: 521 ms, 381 μs, and 3 hnsecs
SoA: 5 μs


dub run -b release --compiler=ldc

benchmarking complete access
AoS: 1 μs and 6 hnsecs
SoA: 1 hnsec
benchmarking partial access
AoS: 1 hnsec
SoA: 1 hnsec


The problem I have is that LDC always seems to optimize the 
functions too much. At least one function executes always in "1 
hnsec".


When I do manage do create an testcase where AoS and SoA have a 
reasonable time, then they are equally fast, no matter what I do.


What I wanted to see:

If I iterate over a collection and I always access all members, I 
would assume that AoS vs SoA should be equally fast.


If I iterate over a collection where the elements have a big size 
and I only access some members I would assume SoA to be much 
faster.


Any help tips are greatly appreciated.


Implementing virtual dispatch in D

2016-03-19 Thread maik klein via Digitalmars-d-learn
So this is mostly curiosity and not completely related to D but I 
would like to know how a vtable is actually implemented. All the 
explanations that I have seen so far are a bit vague and it would 
be nice to actually see some code.


I tried to implement the following myself

interface Something{
   void print();
   int getNumber();
}

This is how I would do it:

struct VDispatch(Types...){
void* vptr;
char typeId;

void print(){
foreach(index, type; Types){
if(index == typeId){
(cast(type*)vptr).print();
}
}
}

int getNumber(){
foreach(index, type; Types){
if(index == typeId){
return (cast(type*)vptr).getNumber();
}
}
throw new Error("Unknown Type");
}

this(T)(T* ptr){
import std.meta: staticIndexOf;
vptr = cast(void*)ptr;
typeId = staticIndexOf!(T, Types);
}
}


struct Foo{
int number;
void print(){
import std.stdio;
writeln("Foo: ", number);
}
int getNumber(){
return number;
}
}

struct Bar{
int number;
void print(){
import std.stdio;
writeln("Bar: ", number);
}
int getNumber(){
return number;
}
}

unittest{
import std.stdio;
alias VFooBar = VDispatch!(Foo, Bar);
auto t = VFooBar(new Foo(42));
auto t1 = VFooBar(new Bar(24));
t.print();
t1.print();
writeln(t.getNumber());
writeln(t1.getNumber());
}

Is this how it works internally? I assume the compiler would 
generate which types actually supported at runtime? I have 
modeled this as a variadic template "Types..." and it has to be 
managed by the user.




Bikeshed: Implementing a command queue.

2016-03-12 Thread maik klein via Digitalmars-d-learn
I wanted to implement a simple command queue in D. To give a bit 
of context, I want to create a command queue for opengl. Instead 
of interacting directly with opengl, you will create commands, 
put them in a queue and then the renderer will read those 
commands and execute the correct OpenGl calls.



I have a few options:

I could use an ADT to create commands but then all commands would 
have the size of the biggest command, also Algebraic is not nice 
nicest thing in D.


I could use runtime polymorphism `class SomeCommand: Command{}` 
but then I would end up with a lot of pointers in the queue, also 
I would need to worry about the allocations.


I have also seen this, but it is a bit more low level and is 
similar to assembly.


Queue:
Command1
int
int
Command2
float
Command3
Command4
int
float double

The first entry would always be the command which is followed by 
the arguments. So you would pop the command out and with the 
command you know how far you need to go into the queue


//pseudo code
auto c = queue.pop!Command;

if(c == Command1){
   int arg1 = queue.pop!int;
   int arg2 = queue.pop!int;
}
if(c == Command2){
   int arg1 = queue.pop!float;

}

How would you implement a simple command queue?







Iterating over thread local storage variables

2016-03-11 Thread maik klein via Digitalmars-d-learn
I want to create a logger in a multithreaded system. I wanted to 
expose a global variable like


logger.log("something");

I also wanted to reuse D's thread local global variables because 
that would make it easy to log in a multithreaded system.


This is really easy to do, but the problem is that at one point I 
need to collect all `loggers` and merge them.


So I thought about writing something like this:

import std.stdio;
class Singleton(T)
{
import std.container: Array;
private this() {}

// Cache instantiation flag in thread-local bool
// Thread local
private static bool instantiated_;

// Thread global
private __gshared Singleton!T instance_;

static Singleton!T get()
{
if (!instantiated_)
{
synchronized(Singleton!T.classinfo){
if (!instance_){
instance_ = new Singleton!T();
}
instantiated_ = true;
instance_.tls.insertBack(_.value);
}
}

return instance_;
}
__gshared Array!(T*) tls;
static T value;
}
unittest{
import std.concurrency;
import core.thread;
auto s = Singleton!int.get();
foreach(index; 0..10){
spawn((int a){
auto s = Singleton!int.get();
s.value = a;
}, index);
}
Thread.sleep( dur!("seconds")( 1 ) );
writeln("--");
foreach(p; s.tls){
writeln(*p);
}
}

Basically every time `instantiated_` is false, I know that I am 
on a new thread and then I push the reference of `value` into a 
global array.


But how do I access `tls` in a thread safe manner?

Is there another way of doing this?



Re: Transposing a static array

2016-02-20 Thread maik klein via Digitalmars-d-learn

On Saturday, 20 February 2016 at 03:02:11 UTC, cym13 wrote:

On Saturday, 20 February 2016 at 02:26:56 UTC, maik klein wrote:
On Saturday, 20 February 2016 at 02:22:12 UTC, Ali Çehreli 
wrote:

[...]


Your "Method B" is how I did it too but how do I convert it 
back to a static array of float[2][3]?


I don't see the point of using transposed which gives a range 
out if you want to put it back into a float[2][3] right away, 
just do a double foreach:


void main(string[] args) {
float[3][2] src = [[1, 2, 3], [2, 3, 4]];

float[2][3] dst;

foreach (i ; 0..src.length)
foreach (j ; 0..src[0].length)
dst[j][i] = src[i][j];

assert(dst == [[1, 2], [2, 3], [3, 4]]);
}


You are right. I restricted myself from using indices because I 
wanted to learn ranges but I think that working with matrices is 
actually much simpler by just using good old for loops.


Re: Transposing a static array

2016-02-19 Thread maik klein via Digitalmars-d-learn

On Saturday, 20 February 2016 at 02:22:12 UTC, Ali Çehreli wrote:

On 02/19/2016 06:00 PM, maik klein wrote:

How would I transpose

float[3][2]

to

float[2][3]

with http://dlang.org/phobos/std_range.html#.transposed




Because static arrays are not ranges, they must be used as 
slices with the help of []. The following code does the same 
thing in two different ways:


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

void main() {
float[3][2] arr = [ [1, 2, 3],
[4, 5, 6] ];

// Method A
{
float[][] arr2;

foreach (ref a; arr) {
arr2 ~= a[];
}

writeln(arr2.transposed);
}

// Method B
{
auto r = arr[].map!((ref a) => a[]).array.transposed;
writeln(r);
}
}

Ali


Your "Method B" is how I did it too but how do I convert it back 
to a static array of float[2][3]?


Transposing a static array

2016-02-19 Thread maik klein via Digitalmars-d-learn

How would I transpose

float[3][2]

to

float[2][3]

with http://dlang.org/phobos/std_range.html#.transposed




Re: Confusion regarding struct lifecycle

2016-02-15 Thread maik klein via Digitalmars-d-learn

On Tuesday, 16 February 2016 at 02:09:15 UTC, Matt Elkins wrote:
I've been bitten again by my lack of understanding of the D 
struct lifecycle :-/. I managed to reduce my buggy program to 
the following example:


[...]


In D you can always call Foo.init even with @disable this(), The 
first 3 destructor calls are from the 3 Foo.inits in your static 
array. I guess because you disabled the copy constructor, the 
Foo's will be moved and then they also need to call the 
destructor of the Foo.inits. Just like std::move does.


Containers with non copyable types

2016-02-01 Thread maik klein via Digitalmars-d-learn

For example it is no problem in C++ to have

std::vector vuf;

But how can this be expressed in D?

For example

Array!(Unique!int) ua;

doesn't compile because it requires this(this) which is obviously 
disabled for "Unique".





Re: Ownership semantics

2016-01-31 Thread maik klein via Digitalmars-d-learn
On Sunday, 31 January 2016 at 20:20:52 UTC, Steven Schveighoffer 
wrote:

On 1/31/16 3:15 PM, Matt Elkins wrote:

On Sunday, 31 January 2016 at 20:11:07 UTC, Matt Elkins wrote:

On Sunday, 31 January 2016 at 20:10:03 UTC, Matt Elkins wrote:
On Sunday, 31 January 2016 at 20:07:26 UTC, Steven 
Schveighoffer wrote:
What is likely happening is that ptr is already collected, 
and you

are invalidly attempting to re-free it.


The GC can collect this memory even though there is still an
outstanding root-reachable pointer to it?


Or maybe it isn't root-reachable?


No, it is still present even if root-reachable:

[code]
unittest
{
 import std.algorithm;

 int* x;
 {
 auto map = new UniquePtr!int[1];
 auto uniqueX = UniquePtr!int(5);
 x = uniqueX.get();
 map[0] = move(uniqueX);
 }
}
[/code]

[output]
core.exception.InvalidMemoryOperationError@src\core\exception.d(679):
Invalid memory operation

Program exited with code 1
Made 632560 for this 18FD90
Disposing null for this 18FD70
Disposed null for this 18FD70
Disposing null for this 18FD90
Disposed null for this 18FD90
All unit tests have been run successfully.
Disposing 632560 for this 632550
[/output]


Oh, nevermind. This is actually simpler.

You can't do memory operations inside a destructor during 
collection. I forgot about that.


But the rule I stated is still in force.

-Steve
Honestly I don't quite understand why it would refree the ptr, 
but switching to malloc does seem to solve the problem.


struct UniquePtr(T) {
import std.experimental.allocator;
private T* ptr = null;
IAllocator alloc;
@disable this(this); // This disables both copy construction 
and opAssign


this(Args...)(auto ref Args args){
import std.experimental.allocator.mallocator;
alloc = allocatorObject(Mallocator.instance);
ptr = alloc.make!T(args);
}

~this() {
alloc.dispose(ptr);
}

inout(T)* get() inout {
return ptr;
}

// Move operations
this(UniquePtr!T that) {
this.ptr = that.ptr;
that.ptr = null;
}

ref UniquePtr!T opAssign(UniquePtr!T that) { // Notice no 
"ref" on "that"

import std.algorithm.mutation;
swap(this.ptr, that.ptr); // We change it anyways, 
because it's a temporary

return this;
}
}



Re: Declaring rvalue function arguments

2016-01-31 Thread maik klein via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:42:19 UTC, anonymous wrote:

On 31.01.2016 18:21, Matt Elkins wrote:
I know I can mark an argument ref to require lvalues, so I'm 
wondering
whether there is an equivalent for rvalues; that is, is there 
a way to

specify that an argument to a function MUST be an rvalue?

For example, in C++ I can do this:
[code]
void foo(int && x) {...}

foo(5); // Works fine
int y = 5;
foo(y); // Compile error; y is not an rvalue
[/code]

This functionality turns out to be really useful when dealing 
with

transferring ownership of resources.


I don't know if this works in all cases, but it passes that 
simple test:



@disable void foo(ref int x);
void foo(int x) {}

void main()
{
foo(5); /* works */
int y = 5;
foo(y); /* error */
}



The problem is that x will be copied afaik which is not what you 
want if you want to deal with ownership.


Re: Declaring rvalue function arguments

2016-01-31 Thread maik klein via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:21:54 UTC, Matt Elkins wrote:
I know I can mark an argument ref to require lvalues, so I'm 
wondering whether there is an equivalent for rvalues; that is, 
is there a way to specify that an argument to a function MUST 
be an rvalue?


For example, in C++ I can do this:
[code]
void foo(int && x) {...}

foo(5); // Works fine
int y = 5;
foo(y); // Compile error; y is not an rvalue
[/code]

This functionality turns out to be really useful when dealing 
with transferring ownership of resources.


I am also very interested in this. I just asked this question 
today on SO 
https://stackoverflow.com/questions/35115702/how-do-i-express-ownership-semantics-in-d





Re: Declaring rvalue function arguments

2016-01-31 Thread maik klein via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:55:53 UTC, Matt Elkins wrote:
Errr, ignore the makeFoo() line. Left that in by accident, has 
no bearing on the issue.


I have found an interesting SO answer 
http://stackoverflow.com/a/35114945/944430


This would explain everything that we would need. I am just not 
100% sure if everything he says is actually true.


Ownership semantics

2016-01-31 Thread maik klein via Digitalmars-d-learn
I recently asked a question about ownership semantics in D 
https://stackoverflow.com/questions/35115702/how-do-i-express-ownership-semantics-in-d


But a few minutes ago I found an answer on SO that could 
potentially explain a lot.


http://stackoverflow.com/a/35114945/944430

Sadly it has some pseudo code in it so I implemented it with 
std.experimental.allocator


struct UniquePtr(T) {
import std.experimental.allocator;
private T* ptr = null;

@disable this(this); // This disables both copy construction 
and opAssign


this(Args...)(auto ref Args args){
ptr = theAllocator.make!T(args);
}

~this() {
theAllocator.dispose(ptr);
}

inout(T)* get() inout {
return ptr;
}

// Move operations
this(UniquePtr!T that) {
this.ptr = that.ptr;
that.ptr = null;
}

ref UniquePtr!T opAssign(UniquePtr!T that) { // Notice no 
"ref" on "that"

import std.algorithm.mutation;
swap(this.ptr, that.ptr); // We change it anyways, 
because it's a temporary

return this;
}
}

Is this code correct? One problem that I have is

UniquePtr!int[int] map;

will result in a memory exception and I have no idea why.


Re: nogc Array

2016-01-25 Thread maik klein via Digitalmars-d-learn

On Tuesday, 26 January 2016 at 03:03:40 UTC, Igor wrote:
Is there a GC-less array that we can use out of the box or do I 
have to create my own?


https://dlang.org/phobos/std_container_array.html


Deleting an object

2016-01-18 Thread Maik Klein via Digitalmars-d-learn
I have also asked this question here 
https://stackoverflow.com/questions/34838742/weak-references-or-pointers


But I try to word it differently.

I have a game with GameObjects, a system manages those 
GameObjects. GameObjects can hold a pointer/reference to each 
other.


But at one point a GameObject dies and when it does it shouldn't 
be able to be accessed by other GameObjects nor should it be kept 
alive in memory.


How do I express this in D?

I have also looked at core.memory.GC

  auto foo = new Foo!int();
  auto foo2 = foo;
  GC.free(foo);

  if(foo != null)
writeln(*foo);
  if(foo2 != null)
writeln(*foo2);

But it seems that `GC.free` behaves like C++'s `delete` and 
doesn't actually null all the pointers.


Re: Unable to call each on a lockstep range containing 2 or more ranges

2015-11-18 Thread maik klein via Digitalmars-d-learn

On Wednesday, 18 November 2015 at 17:22:52 UTC, Meta wrote:
On Wednesday, 18 November 2015 at 12:20:42 UTC, maik klein 
wrote:

[...]


Which version of the compiler are you using?

Linux - DMD64 D Compiler v2.069.0




Unable to call each on a lockstep range containing 2 or more ranges

2015-11-18 Thread maik klein via Digitalmars-d-learn

https://stackoverflow.com/questions/33779822/unable-to-call-each-on-a-lockstep-range-containing-2-or-more-ranges

http://dpaste.dzfl.pl/76c79f1f12ab

void main(){
  import std.container;
  import std.stdio;
  import std.algorithm.iteration;
  import std.range;
  Array!int ai = [1,2,3,4];
  Array!int ai1 = [1,2,3,4];
  Array!int ai2 = [1,2,3,4];

  auto arange = lockstep(ai[],ai1[]);
  arange.each!((a,b) => writeln(a, b));

  auto arange2 = lockstep(ai[],ai1[],ai2[]);
  arange2.each!((a,b,c) => writeln(a, b, c));
}

Error: template std.algorithm.iteration.each cannot deduce 
function from argument types !((a, b, c) => writeln(a, b, 
c))(Lockstep!(RangeT!(Array!int), RangeT!(Array!int), 
RangeT!(Array!int))), candidates are: 
/opt/compilers/dmd2/include/std/algorithm/iteration.d(820):

std.algorithm.iteration.each(alias pred = "a")


"arange" works but "arange2" doesn't because the compiler is 
unable to deduce the the function. The error even appears if I 
explicitly add the argument types.


Re: Unable to call each on a lockstep range containing 2 or more ranges

2015-11-18 Thread maik klein via Digitalmars-d-learn

On Wednesday, 18 November 2015 at 13:51:59 UTC, John Colvin wrote:
On Wednesday, 18 November 2015 at 12:20:42 UTC, maik klein 
wrote:

[...]


I think this is a bug, please report it at issues.dlang.org and 
perhaps there will be an explanation or it will be fixed.

In the mean time, something like this should work:

  auto arange2 = zip(ai[],ai1[],ai2[]);

  arange2.each!((t) => writeln(t[0], t[1], t[2]));
  // or if you really must have the names:
  arange2.each!((t) => (a,b,c){ writeln(a, b, c); }(t.expand));


Thanks, but the problem I have with zip is that it doesn't work 
with "ref".



for example

auto arange3 = zip(ai[],ai1[],ai2[]);
foreach(ref a; arange3){
  a[0] = 42;
}
Won't change anything. Is this another bug?




Filtering a tuple of containers with indices

2015-11-17 Thread maik klein via Digitalmars-d-learn

The question is also posted on

https://stackoverflow.com/questions/33757981/filtering-a-tuple-of-containers-with-indicies


template tupIndexToRange(alias Tup, Indices...){
  import std.meta;
  static if(Indicies.length == 0){
alias tupIndexToRange = AliasSeq!();
  }
  else{
alias tupIndexToRange = AliasSeq!(Tup[ Indices[0] ][], 
tupIndexToRange!(Tup,Indices[1..$]));

  }
}

void main{
  alias Integrals = AliasSeq!(Array!int, Array!float, 
Array!double);

  Integrals integrals;

  alias IntegralRange = tupIndexToRange!(integrals,0,1);
}

void main{
  alias Integrals = AliasSeq!(Array!int, Array!float, 
Array!double);

  Integrals integrals;

  alias IntegralRange = tupIndexToRange!(integrals,0,1);
}

I want to achieve something like this

auto range = zip(tupIndexToRange!(integrals,0,1));

I think the main problem is that Tup[ Indicies[0] ] doesn't work, 
to me it should have expanded to this 
AliasSeq!(itegrals[0][],integrals[1][]);



This is roughly what I want to achieve

  alias Integrals = AliasSeq!(Array!int, Array!float, 
Array!double);

  Integrals integrals;
  integrals[0].insertBack(1);
  integrals[1].insertBack(2);
  integrals[2].insertBack(3);

  auto range = zip(tuple(integrals[0][],integrals[1][]).expand);
  writeln(range);
  foreach(e;range){
writeln("element: ",e);
  }
But instead of "auto range = 
zip(tuple(integrals[0][],integrals[1][]).expand);" I want it to 
be generic "auto range = zip(tupIndexToRange!(integrals, 
AliasSeq!(0, 1)).expand);"


Maybe I need use mixins?


Re: Filtering a tuple of containers with indices

2015-11-17 Thread maik klein via Digitalmars-d-learn

On Tuesday, 17 November 2015 at 15:48:10 UTC, anonymous wrote:

On 17.11.2015 15:32, maik klein wrote:

[...]

[snip]

I don't quite understand how that code is supposed to work. 
Maybe there's just some detail missing, but it could also be 
that your approach can't work.


[...]


Thanks but I have one question.

.selectFromTuple!(0, 1).expand

Does this result in a copy? I avoided doing it like this because 
I was worried that I would copy every array. But I also don't 
fully understand when D will copy.



Also doing

  foreach(e;range){
e[0] = 10;
e[1] = 10.0f;
writeln("element: ",e);
  }
  foreach(e;range){
writeln("element: ",e);
  }

doesn't mutate the range at all.



Cannot use local 'i' as parameter to non-global template

2015-11-07 Thread maik klein via Digitalmars-d-learn

template IsSame(T){
  template As(alias t){
enum As = is(T : typeof(t));
  }
}
void main()
{
  int i;
  enum b = IsSame!int.As!(i);
}

Err:

Error: template instance As!(i) cannot use local 'i' as parameter 
to non-global template As(alias t) dmd failed with exit code 1

I don't understand the error message.

I also tried

template IsSame(T){
  enum As(alias t) = is(T : typeof(t));
}

Which results in

Error: template app.IsSame!int.As cannot deduce function from 
argument types !()(int), candidates are: source/app.d(50,8):

app.IsSame!int.As(alias t)

What am I doing wrong?

Ps: Also posted on SO 
https://stackoverflow.com/questions/33584130/cannot-use-local-i-as-parameter-to-non-global-template not sure where people usually ask questions about D.


Re: Is it possible to filter variadics?

2015-11-04 Thread maik klein via Digitalmars-d-learn

On Wednesday, 4 November 2015 at 06:20:30 UTC, Jakob Ovrum wrote:

On Tuesday, 3 November 2015 at 23:41:10 UTC, maik klein wrote:

[...]


import std.algorithm.iteration : sum;
import std.meta : allSatisfy, Filter;
import std.traits;
import std.typecons : tuple;
import std.range : only;

// These two are necessary since the ones in std.traits
// don't accept non-types
enum isIntegral(alias i) = std.traits.isIntegral!(typeof(i));
enum isFloatingPoint(alias f) = 
std.traits.isFloatingPoint!(typeof(f));


auto separateSum(T...)(T args)
if(allSatisfy!(isNumeric, T))
{
	return tuple(only(Filter!(isIntegral, args)).sum(), 
only(Filter!(isFloatingPoint, args)).sum());

}

pure nothrow @safe unittest
{
assert(separateSum(2, 2.0) == tuple(2, 2.0));
assert(separateSum(3, 2.0, 5, 1.0, 1.0) == tuple(8, 4.0));
}


Thanks, that is exactly what I wanted to achieve. What is the 
performance implication of 'only' in this context? Will it copy 
all arguments?


Is it possible to filter variadics?

2015-11-03 Thread maik klein via Digitalmars-d-learn

Is it possible to filter variadics for example if I would call

void printSumIntFloats(Ts...)(Ts ts){...}

printSumIntFloats(1,1.0f,2,2.0f);

I want to print the sum of all integers and the sum of all floats.


//Pseudo code
void printSumIntFloats(Ts...)(Ts ts){
auto sumOfInts = ts
  .filter!(isInteger)
  .reduce(a => a + b);
writeln(sumOfInts);
...
}

Is something like this possible?



Re: Are there any exercises/challenges for D?

2014-08-24 Thread maik klein via Digitalmars-d-learn

On Sunday, 24 August 2014 at 21:51:39 UTC, Weaseldog wrote:

On Sunday, 24 August 2014 at 20:32:02 UTC, maik klein wrote:

Are there any exercises/challenges for D?

Something like this? 
http://www.haskell.org/haskellwiki/99_questions/1_to_10


Well, you could port 99 lisp problems to D - D can be written 
in a fairly functional style ;)


I am just trying to learn D by writing code. Of course I could 
just do them in D but I would like to compare my version with 
idiomatic D.


It's actually quite strange that no one has done something like 
this in D, it's usually the first thing people do.