Re: Generating code based on UDA

2014-10-25 Thread Shammah Chancellor via Digitalmars-d-learn

On 2014-10-25 13:37:54 +, Rares Pop said:


Hello everyone,

I am trying to understand UDA traits scoping while mixing in code.
Aiming to generate code based on UDA I wonder if the following is possible:

class A
{
@Inject
Logger logger;

@Inject
SomeOtherClass dependency;

mixin injections!(A)

...
}

In "injections" function I want to iterate through members annotated 
with the @Inject attribute and generate some specific code.

So far in my attempts the compiler complains about unknown identifier A.
Should the A class be available to the compiler at the time of the 
mixin invocation?


Thanks for your help,
Rares


Very much possible.  Since I don't see what your template is doing, I'm 
going to give it a guess:


class A{
mixin injections;
}

template injections
{

 typeof(this);  // e.g. foreach( tra; 
__traits(getAttributes, typeof(this)))



}


typeof(this) will be A.



Re: package reflection

2014-06-22 Thread Shammah Chancellor via Digitalmars-d-learn

On 2014-06-22 14:11:58 +, sigod said:

In the video "Case Studies In Simplifying Code With Compile-Time 
Reflection" [was pointed out][0] that it is possible to reflect on 
imported packages.


So, I tried:

reflection.d:
```
import std.stdio;

import test.module1;
import test.module2;

void main() {
foreach (m; __traits(allMembers, mixin(__MODULE__))) {
writeln(m);
}

writeln("--");

foreach (m; __traits(allMembers, test)) {
writeln(m);
}
}
```

test/module1.d:
```
module test.module1;

void module_1() {}
```

test/module2.d:
```
module test.module2;

void module_2() {}
```

It produces:
```
$ rdmd reflection.d
object
std
test
main
--
object
module_1
```

As you see `module_2` wasn't listed. If I change order of import 
declarations `module_2` will be listed instead of `module_1`.


I also tried to create `test/package.d` and publicly import other 
modules through it, but it behave in the same way.


So, how to reflect on imported packages?

[0]: http://youtu.be/xpImt14KTdc?t=42m26s


This is very frustrating indeed, and I have an open bug request about 
it. Please bump it so it gets some attention:


https://issues.dlang.org/show_bug.cgi?id=11595

-Shammah



Re: Non-blocking array queue.

2014-03-08 Thread Shammah Chancellor

On 2014-03-08 21:16:36 +, Martin said:


On Saturday, 8 March 2014 at 21:12:42 UTC, Shammah Chancellor wrote:

On 2014-03-08 19:58:01 +, Martin said:


On Saturday, 8 March 2014 at 19:02:26 UTC, Shammah Chancellor wrote:

Hi,

I'm interesting in implementing a non-blocking queue.   My thought is 
to use a fixed-size array, and increment back of the queue with a 
integer.   I was thinking I could make this non-blocking via an atomic 
increment operation before assigning the pushed value onto the queue.   
So, my question is:   How would you do an atomic increment in a 
cross-platform way in D?



Thanks!
-S.


I think you could use http://dlang.org/phobos/core_atomic.html, maybe?


I didn't see a way to get an an increment operation.   atomicOp doesn't 
seem to offer unitary operations.


-S.


atomicOp!("+=")(value, 1);

Should work, I believe. Or is that not what you meant?


I was considering using that, but in the channel I was told that would 
be inefficient assembly when it should normally be one operation?




Re: Non-blocking array queue.

2014-03-08 Thread Shammah Chancellor

On 2014-03-08 19:58:01 +, Martin said:


On Saturday, 8 March 2014 at 19:02:26 UTC, Shammah Chancellor wrote:

Hi,

I'm interesting in implementing a non-blocking queue.   My thought is 
to use a fixed-size array, and increment back of the queue with a 
integer.   I was thinking I could make this non-blocking via an atomic 
increment operation before assigning the pushed value onto the queue.   
So, my question is:   How would you do an atomic increment in a 
cross-platform way in D?



Thanks!
-S.


I think you could use http://dlang.org/phobos/core_atomic.html, maybe?


I didn't see a way to get an an increment operation.   atomicOp doesn't 
seem to offer unitary operations.


-S.



Non-blocking array queue.

2014-03-08 Thread Shammah Chancellor

Hi,

I'm interesting in implementing a non-blocking queue.   My thought is 
to use a fixed-size array, and increment back of the queue with a 
integer.   I was thinking I could make this non-blocking via an atomic 
increment operation before assigning the pushed value onto the queue.   
So, my question is:   How would you do an atomic increment in a 
cross-platform way in D?



Thanks!
-S.



Re: Searching for a string in a text buffer with a regular expression

2013-12-06 Thread Shammah Chancellor

On 2013-12-06 08:53:04 +, maxpat78 said:


While porting a simple Python script to D, I found the following problem.

I need to read in some thousand of little text files and search every 
one for a match with a given regular expression.


Obviously, the program can't (and it should not) be certain about the 
encoding of each input file.


I initially used read() casting it with a cast(char[]), but, at some 
point, the regex engine crashed with an exception: it encountered an 
UTF-8 character it couldn't automatically decode. This is right, since 
char[] is not byte[].


Now I'm casting with a Latin1String, since I know this is the right 
encoding for the input buffers: and it works fine, at last... but what 
about if I'd need to treat a RAW (binary? unknown encoding?) buffer?


Is there a simple and elegant solution in D for such case?
Python didn't gave such problems!


Why don't you follow one of the file reading examples?

readText is what you're looking for.

http://dlang.org/phobos/std_file.html#.readText



Re: Monads compared to InputRanges?

2013-12-04 Thread Shammah Chancellor

On 2013-12-04 08:24:02 +, qznc said:


On Wednesday, 4 December 2013 at 01:53:39 UTC, Shammah Chancellor wrote:

Or is D syntax not generic enough to define monads?


I started to port monads to D [0]. You can do it, but it looks ugly. 
The trick is to implement (Haskell) type classes via template 
specialization. I came to the conclusion that it is not worth it.


What D kind of lacks is a way to define a general type class aka the 
interface. Of course, you could use the "interface" keyword, but then 
you cannot apply it to structs. Haskell has no structs (value type 
records), so they do not have this problem. Look at how isInputRange is 
implemented [1]. The traits in Rust [2] provide this interface 
mechanisms as a language feature. D uses static-if instead.


Not Haskell, not D, not Rust can check, if your monad actually follows 
the monad laws [3]. This would probably require a full theorem prover 
in your language. So Coq, Isabelle, and maybe ATS could do that. A 
similar challenge would be to check if a user-defined plus operator is 
commutative (a+b == b+a) like arithmetic plus operations.


[0] 
https://bitbucket.org/qznc/d-monad/src/5b9d41c611093db74485b017a72473447f8d5595/generic.d?at=master 

[1] 
https://github.com/D-Programming-Language/phobos/blob/master/std/range.d#L519 


[2] http://static.rust-lang.org/doc/0.8/tutorial.html#generics
[3] http://www.haskell.org/haskellwiki/Monad_laws


I was talking on the D newsgroup about using an interface type and 
implementing isConceptOf!() to be used with structs.
Wouldn't that fix the problem?


-Shammah



Re: Monads compared to InputRanges?

2013-12-03 Thread Shammah Chancellor

On 2013-12-03 23:49:47 +, Max Klyga said:


On 2013-12-03 23:02:13 +, Shammah Chancellor said:


On 2013-12-03 21:51:20 +, Max Klyga said:


On 2013-12-03 02:45:44 +, Shammah Chancellor said:

I'm not particularly familiar with the syntax being used in the variet 
of monad examples.   I'm trying to figure out how this is different 
from UFCS on InputRanges.   It seems like std.algorithm implements 
something which accomplished the same thing, but much easier to 
understand?


Can somebody maybe do a compare and contrast for me?

-Shammah


Monads and input ranges are different things. I'll try to briefly 
explain monads. Hope this will not worsen the situation by being too 
confusing.


InputRanges provide a generic way for iterating over something.

UFCS can be used to create a range interface on things that do not provide it.

Monads are an abstraction for composing things within some context 
(concatenating lists, composing operations on nullable values, 
composing asynchronous operations). That sounds a bit too general and 
vague, because it is. One can think about as a design pattern.

Monad has two operations:
 - make a monad out of a value
 - apply a function that takes a value and returns a new monad of the 
same kind to value inside a monad


second operation has a different meaning for different monad kinds but 
generally it means 'execute this code within current context'


for nullable values this means 'execute only if there exist a value'
for asynchronous operations this means 'execute this when the value is ready'

This operation is commonly named 'bind' or 'flatMap'

Some languages provide syntax sugar for monads (Scala's for, Haskell's do)
Monads are easier to understand once you've seen enough examples of 
things that are monads.


Suppose you have a list of movies and want to produce a list of names 
of all actors stating in those movies.

In scala you would typically write something like this:

for (movie <- movies; actor <- movie.actors) yield actor.name

Compiler rewrites that to

movies.flatMap(movie => movie.actors).map(actor => actor.name)
  ^
   -- this function takes a list 
element and returns a new list, effectively creating a list of lists 
and then flattening it by concatenating all the lists into one, hence 
the name 'flatMap'. It transforms and then flattens.


Another popular example for Monads are optional values (similar to 
nullables but forcing you to check for presence of value and explicitly 
avoiding null dereferencing)


A common pattern for working with optional values is returning null 
from your function if your input is null


So if say we are parsing JSON and we want to process only values that 
contain certain field, that in turn contains another field. Example in 
pseudo-scala:


	for (value <- json.get("value"); // type of value is Option(JsonNode) 
meaning that actual json node might be absent
	   anotherValue <- value.get("another")) // this is executed only 
if value is present

doSomethingFancy(anotherValue) // ditto

and again, compiler will rewrite this into

	json.get("value").flatMap(value => 
value.get("another")).foreach(anotherValue => 
doSomethingFancy(anotherValue))


Once again we see that flat map is used. The pattern is same - get the 
value out of the box, transform it to another box of the same kind in 
the context meaningful for this particular box kind


So the main benefit is being able to compose things in a consistent 
way. Once you grasp the whole idea its fun finding out that some thing 
you've been doing can be viewed as a monad. People created quite a lot 
of different monads to this date.



I get the gist of that, but it seems like the range concept with UFCS 
provides the same thing? E.G.  range.map().flatten().map()?


Does it really not accomplish the same thing -- am I missing some key 
point of monads?


You look only at the syntax side of the question.

 range.map(...).flatten.map(...) might look similar and it could be 
possible to squeeze monads to work with this api, but the thing is that 
not every monad could provide a meaningful map function and as a whole 
calling flatten after every map is a bit tiresome.


That may work for some monads, like List, because its effectively a range.
It will also work for Maybe monad. It could be viewed as a range of 0 
or 1 elements.
But things get bad when we try to define other monads in terms of range 
interface.


Current map implementation by design doesn't know anything about range 
it processes. If we try to define Promise monad as a range it will 
practically be useless unless we provide a custom map implementation 
for promises, because std.algorithm.map will return a wrapper range 
that will call popFron

Re: Monads compared to InputRanges?

2013-12-03 Thread Shammah Chancellor

On 2013-12-03 21:51:20 +, Max Klyga said:


On 2013-12-03 02:45:44 +, Shammah Chancellor said:

I'm not particularly familiar with the syntax being used in the variet 
of monad examples.   I'm trying to figure out how this is different 
from UFCS on InputRanges.   It seems like std.algorithm implements 
something which accomplished the same thing, but much easier to 
understand?


Can somebody maybe do a compare and contrast for me?

-Shammah


Monads and input ranges are different things. I'll try to briefly 
explain monads. Hope this will not worsen the situation by being too 
confusing.


InputRanges provide a generic way for iterating over something.

UFCS can be used to create a range interface on things that do not provide it.

Monads are an abstraction for composing things within some context 
(concatenating lists, composing operations on nullable values, 
composing asynchronous operations). That sounds a bit too general and 
vague, because it is. One can think about as a design pattern.

Monad has two operations:
  - make a monad out of a value
  - apply a function that takes a value and returns a new monad of the 
same kind to value inside a monad


second operation has a different meaning for different monad kinds but 
generally it means 'execute this code within current context'


for nullable values this means 'execute only if there exist a value'
for asynchronous operations this means 'execute this when the value is ready'

This operation is commonly named 'bind' or 'flatMap'

Some languages provide syntax sugar for monads (Scala's for, Haskell's do)
Monads are easier to understand once you've seen enough examples of 
things that are monads.


Suppose you have a list of movies and want to produce a list of names 
of all actors stating in those movies.

In scala you would typically write something like this:

for (movie <- movies; actor <- movie.actors) yield actor.name

Compiler rewrites that to

movies.flatMap(movie => movie.actors).map(actor => actor.name)
   ^
    -- this function takes a list 
element and returns a new list, effectively creating a list of lists 
and then flattening it by concatenating all the lists into one, hence 
the name 'flatMap'. It transforms and then flattens.


Another popular example for Monads are optional values (similar to 
nullables but forcing you to check for presence of value and explicitly 
avoiding null dereferencing)


A common pattern for working with optional values is returning null 
from your function if your input is null


So if say we are parsing JSON and we want to process only values that 
contain certain field, that in turn contains another field. Example in 
pseudo-scala:


	for (value <- json.get("value"); // type of value is Option(JsonNode) 
meaning that actual json node might be absent
	   anotherValue <- value.get("another")) // this is executed only 
if value is present

doSomethingFancy(anotherValue) // ditto

and again, compiler will rewrite this into

	json.get("value").flatMap(value => 
value.get("another")).foreach(anotherValue => 
doSomethingFancy(anotherValue))


Once again we see that flat map is used. The pattern is same - get the 
value out of the box, transform it to another box of the same kind in 
the context meaningful for this particular box kind


So the main benefit is being able to compose things in a consistent 
way. Once you grasp the whole idea its fun finding out that some thing 
you've been doing can be viewed as a monad. People created quite a lot 
of different monads to this date.



I get the gist of that, but it seems like the range concept with UFCS 
provides the same thing? E.G.  range.map().flatten().map()?


Does it really not accomplish the same thing -- am I missing some key 
point of monads?  



Monads compared to InputRanges?

2013-12-02 Thread Shammah Chancellor
I'm not particularly familiar with the syntax being used in the variet 
of monad examples.   I'm trying to figure out how this is different 
from UFCS on InputRanges.   It seems like std.algorithm implements 
something which accomplished the same thing, but much easier to 
understand?


Can somebody maybe do a compare and contrast for me?

-Shammah



Re: TypeInfo.compare is not implemented

2013-11-30 Thread Shammah Chancellor

On 2013-11-30 13:39:15 +, Leandro Motta Barros said:


Hello,

I my FewDee game prototyping library (https://bitbucket.org/lmb/fewdee) 
I ignored most of the usual reccomendations like "be careful with the 
GC, it's slow" and "associative arrays are buggy in D, so avoid them". 
I just used whatever I found convenient to have my stuff running with 
minimal effort.


So, I did something that may be an abuse of D's associative arrays:

alias
  Tuple!(const(GameState), ALLEGRO_EVENT_TYPE)
  stateTypePair;

// GameState is a class, ALLEGRO_EVENT_TYPE is
// some integral data type

EventHandler[EventHandlerID][stateTypePair]
   _eventHandlers;

// EventHandler is a delegate. EventHandlerID is
// an integral type.

This used to work (surprisingly? :-) ) until very recently (when I 
upgraded to DMD 2.064, it seems).


Now, I am getting this

   object.Error: TypeInfo.compare is not implemented

when I try to use my '_eventHandlers' AA.

So, any suggestions?

Thanks a lot!

LMB


DMD version?  Can you post a reduced example which produces the error.  
I can't tell where a typeinfo would be getting used from that example.


-Shammah



Re: D code beautifier

2013-11-28 Thread Shammah Chancellor

On 2013-11-28 22:28:54 +, seany said:


does such a thing exist? like html code beautifiers?


Most IDE's support this.   Try Xamarin Studio with MonoD.

http://mono-d.alexanderbothe.com



Re: casting as char at CT fail

2013-11-28 Thread Shammah Chancellor

On 2013-11-28 03:40:25 +, Kenji Hara said:


On Tuesday, 26 November 2013 at 23:31:16 UTC, bioinfornatics wrote:

Hi,
this time i have so many question about CT …
iws and ibuclaw help me for this.

I stuck currently about a cast at CT -> http://www.dpaste.dzfl.pl/1a28a22c

it seem this should works but not…
So if you confirm maybe a report is needed

thanks to everyone


I found two compiler issues:

https://d.puremagic.com/issues/show_bug.cgi?id=11627
https://d.puremagic.com/issues/show_bug.cgi?id=11629

Kenji Hara


Kenji you are awesome!

Also,  I had got his code working to a point: 
http://www.dpaste.dzfl.pl/985a2f42  and got another compiler bug.


/opt/compilers/dmd2/include/std/range.d(4220): Error: Internal Compiler 
Error: CTFE literal Tuple(void, void)._expand_field_0
dmd: ctfeexpr.c:359: Expression* copyLiteral(Expression*): Assertion 
`0' failed.

Seems to happen at the end while trying to instantiate the enum.

I am having trouble turning it into a reduced test case.  Can't find 
the source of the problem.   Here's the full snippet: 
http://www.dpaste.dzfl.pl/fork/985a2f42


Thanks for looking into this!



Re: template operator overload

2013-11-27 Thread Shammah Chancellor

On 2013-11-27 16:07:50 +, Namespace said:

Just out of curiosity: Is it possible to call an overloaded operator 
with a template type?


import std.stdio;

struct A {
void opIndex(T)(size_t index) {

}
}

void main() {
A a;
a.opIndex!int(0); // [1]
a!int[0]; // [2]
}


[1] works, but [2] fails.
How can I call opIndex with bracket syntax and a typename? Or is this 
not possible?


You need to simply use template deduction, and cast the parameter to 
what you're wanting to use between the brackets.


a[cast(int)0] (although zero is already an int);




Re: casting as char at CT fail

2013-11-27 Thread Shammah Chancellor

On 2013-11-27 06:06:49 +, bioinfornatics said:


On Wednesday, 27 November 2013 at 01:22:07 UTC, Shammah Chancellor wrote:

On 2013-11-26 23:31:14 +, bioinfornatics said:


Hi,
this time i have so many question about CT …
iws and ibuclaw help me for this.

I stuck currently about a cast at CT -> http://www.dpaste.dzfl.pl/1a28a22c

it seem this should works but not…
So if you confirm maybe a report is needed

thanks to everyone



String at compile time seem to be represented as dchar.   Also, the 
loop on bitsPerChar won't work at compile time right now.

I think  maskTmp = cast(T)((1 << bitsPerChar) - 1);
does the same thing though.

http://www.dpaste.dzfl.pl/985a2f42

Fails with some weird internal DMD error now though while trying to 
instantiate the enum.   Maybe time for a bug report?


ldc2 fail too but error message is better, i think.

$ ldc2 BaseTest2.d
/usr/include/d/std/range.d(4171): Error: pointer cast from 
immutable(dchar)* to dchar* is not supported at compile time

BaseTest2.d(56):called from here: __r11.front()
BaseTest2.d(99):called from here: Base(cast(ubyte)0u, null, 
cast(ubyte)0u, cast(ubyte)0u, null, null).this(cast(ubyte)4u, "ACGT", 
[cast(ubyte)0u, cast(ubyte)1u, cast(ubyte)2u, cast(ubyte)3u])
BaseTest2.d(101): Error: function BaseTest2.Base!(ubyte, 
dchar).Base.encode (const(immutable(dchar)[]) word) const is not 
callable using argument types (string)


The cast is unnecessary just do the assignment using dchars.   Even 
with that fixed though, there is annother problem as seen in my dpaste.




Re: casting as char at CT fail

2013-11-26 Thread Shammah Chancellor

On 2013-11-26 23:31:14 +, bioinfornatics said:


Hi,
this time i have so many question about CT …
iws and ibuclaw help me for this.

I stuck currently about a cast at CT -> http://www.dpaste.dzfl.pl/1a28a22c

it seem this should works but not…
So if you confirm maybe a report is needed

thanks to everyone



String at compile time seem to be represented as dchar.   Also, the 
loop on bitsPerChar won't work at compile time right now. I think 	 
maskTmp = cast(T)((1 << bitsPerChar) - 1);

does the same thing though.

http://www.dpaste.dzfl.pl/985a2f42

Fails with some weird internal DMD error now though while trying to 
instantiate the enum.   Maybe time for a bug report?




Re: recursive template at ctfe

2013-11-26 Thread Shammah Chancellor

On 2013-11-26 21:31:55 +, bioinfornatics said:


On Tuesday, 26 November 2013 at 21:18:29 UTC, Shammah Chancellor wrote:

On 2013-11-26 21:00:56 +, bioinfornatics said:


On Tuesday, 26 November 2013 at 20:50:13 UTC, bioinfornatics wrote:

On Tuesday, 26 November 2013 at 20:29:00 UTC, bearophile wrote:

bioinfornatics:

I wrote some template to compute at compile time how many bits is need 
for a number x. http://www.dpaste.dzfl.pl/99a842fd


That works for small number but after i got an error about limit recursion


Instead of template recursion, have you tried regular code run at compile time?

http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious

Bye,
bearophile


Thanks i will take a look


this one seem to be interesting 
http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup


is like i do but use a table than me i used a recursive way. I go to try it :-)


I think you just have a bug in your template code not terminating.   At 
most you should execute 4 times.   I think there's a problem with 
casting down from byte to bool.


However, not user if LesserType is what you're after, but this works:

template log2(ulong x)
{
static if( x >> 8 )
{
enum log2 = log2!(x >> 8) + 8;
}
else static if( x >> 1)
{
enum log2 = log2!(x>>1) + 1;
} else
{
enum log2 = 1;
}
}


Thanks your way is much easier to write, works fine :-)


I would suggest turning it into a compile-time-function though as this 
will instantiate a large number of templates if you use is 
repetitively.   Remember that templates are cached by DMD.


int log2(const ulong x)
{
  if( x >> 8 )
 {
   return log2(x >> 8) + 8;
 }
 else if( x >> 1)
 {
   return log2(x>>1) + 1;
 } else
 {
   return 1;
 }
}

void main()
{
 pragma(msg, log2(1UL<<63));
}



Re: recursive template at ctfe

2013-11-26 Thread Shammah Chancellor

On 2013-11-26 21:00:56 +, bioinfornatics said:


On Tuesday, 26 November 2013 at 20:50:13 UTC, bioinfornatics wrote:

On Tuesday, 26 November 2013 at 20:29:00 UTC, bearophile wrote:

bioinfornatics:

I wrote some template to compute at compile time how many bits is need 
for a number x. http://www.dpaste.dzfl.pl/99a842fd


That works for small number but after i got an error about limit recursion


Instead of template recursion, have you tried regular code run at compile time?

http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious

Bye,
bearophile


Thanks i will take a look


this one seem to be interesting 
http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup


is like i do but use a table than me i used a recursive way. I go to try it :-)


I think you just have a bug in your template code not terminating.   At 
most you should execute 4 times.   I think there's a problem with 
casting down from byte to bool.


However, not user if LesserType is what you're after, but this works:

template log2(ulong x)
{
 static if( x >> 8 )
 {
   enum log2 = log2!(x >> 8) + 8;
 }
 else static if( x >> 1)
 {
   enum log2 = log2!(x>>1) + 1;
 } else
 {
   enum log2 = 1;
 }
}



Re: std.concurrency and immutable

2013-11-26 Thread Shammah Chancellor

On 2013-11-25 20:55:15 +, Antoche said:


On Monday, 25 November 2013 at 11:48:06 UTC, Shammah Chancellor wrote:

On 2013-11-25 06:03:27 +, Antoche said:


The following code compiles but doesn't work as expected:

import std.stdio;
import std.concurrency;

class A
{
this() immutable {}
}

void main()
{
auto tid = spawn( &fooBar, thisTid );
while(true)
{
receive(
(Variant any) {
writeln( "Received a variant" );
writeln( "Received ", any );
}
);
}
}

void fooBar( Tid masterTid )
{
scope(failure) writeln( "fooBar failed" );
scope(success) writeln( "fooBar succeeded" );
scope(exit) writeln( "fooBar exiting" );
try
{
immutable A b = new immutable A();
masterTid.send( 42 ); // This works
masterTid.send( b );  // This doesn't
}
catch( Exception e )
{
writeln( "Exception received" );
}
}


I see this in the console:

fooBar exiting
fooBar failed
Received a variant
Received 42

(then it just hangs)

I'm especially puzzled by:
* Sending an int as a message works but not an immutable object.
Wasn't this  (safely sharing objects across threads) one of the
basic use cases for the immutable type qualifier?
* scope(failure) failed but my exception handler didn't catch
anything. How is this possible? What could cause that?
Assertions/abort?

There seemed to be a 3-year-old ticket on this issue
(http://d.puremagic.com/issues/show_bug.cgi?id=5538) with very
little activity, which is a bit surprising given how much
emphasis is given to this feature (the D homepage mentions "D
offers an innovative approach to concurrency, featuring true
immutable data, message passing, no sharing by default, and
controlled mutable sharing across threads", and TDPL devotes a
whole chapter on it). This thread
(http://forum.dlang.org/thread/kgk8hc$12fa$1...@digitalmars.com)
also says std.concurrency is "very buggy".

If I can't use std.concurrency, is there any other safe
alternative for multithreaded programming with D?

Thanks,
A.



There is a bug with the internals of send/receive.   It has to be able 
to copy the reference to a another place while sending --  and it seems 
it can't do that because it's immutable. I don't think many people 
are using it.I personally did not realize the bug was from 2011.  I 
think DMD has been fixed enough to make a patch to phobos now.  I'm 
going to ping this bug report.


However,  even CONSTRUCTING immutable objects right now is very 
difficult.   It's arguably "correct" but, seems impossible to actually 
be able to make something of use without many many idups.  It's kind of 
in the same boat as shared.


What I am currently doing, is casting to shared, and then back.
I tried making my classes shared, and also immutable as you have.   
Nothing else seems to work:



class A
{
this() {}
}

void main()
{
auto tid = spawn( &fooBar, thisTid );
while(true)
{
receive(

   (shared A _m)
   {
auto m = cast(A)_m;
//Do stuff.
   },

(Variant any) {
writeln( "Received a variant" );
writeln( "Received ", any );
}
);
}
}

void fooBar( Tid masterTid )
{
scope(failure) writeln( "fooBar failed" );
scope(success) writeln( "fooBar succeeded" );
scope(exit) writeln( "fooBar exiting" );
try
{
immutable A b = new A();
masterTid.send( 42 ); // This works
masterTid.send( cast(shared) b );  // Should work
}
catch( Exception e )
{
writeln( "Exception received" );
}
}


-Shammah


Thanks for the suggestion. My problem with casting is that it results 
in undefined behaviour, so I have no guarantee whatsoever what the 
program is actually going to do. I could simply not use immutable at 
all, and use shared instead, but then I might as well stick to C++ and 
volatile. The whole point of using D was trying to write safer code 
with equivalent performance.


I see std.parallelism seems to offer some features that might 
compensate for the broken std.concurrency. Is it working better or is 
it as broken as std.concurrency? Is there any other way to write safe 
multithreaded programs?


Finally, can anyone explained why the scope(failure) is reached? 
Looking at the stacktrace in gdb at this point gives me no indication 
of what's happening.



Try wrapping it in a Try/catch and see.Sending non-value types 
right now seems to be a bit frustrating.   Unless you *need* 
polymorphism for your messages I would suggest sending immutable struct 
references or something.   Or you can also use the idea I suggested and 
cast(const) to ensure you are not messing with the data again 
afterwards.I am going to ping this issue very heavily though, and 
possibly start working on std.concurrency myself.   The current state 
of the library is unacceptable.


-Shammah



Re: Enum of functions?

2013-11-25 Thread Shammah Chancellor

On 2013-11-25 23:32:25 +, Chris Williams said:


Is there any way to do something like this?

import std.stdio;

enum Foo : void function() {
WOMBAT = () {writeln("Wombat");}
}

void doStuff(Foo f) {
f();
}

int main() {
doStuff( Foo.WOMBAT );

return 0;
}

Currently, I get the errors:

hello.d(4): Error: non-constant nested delegate literal expression __lambda1
hello.d(12): Error: delegate hello.Foo.__lambda1 is a nested function 
and cannot be accessed from D main


I can fix it by declaring a function outside of Foo and setting WOMBAT 
= &fname, but it seems like I should be able to create a hidden lambda.


What is the practical purpose of such a thing?

-Shammah



Re: std.concurrency and immutable

2013-11-25 Thread Shammah Chancellor

On 2013-11-25 14:08:53 +, Dicebot said:

Sending immutable classes currently does not work because of 
https://d.puremagic.com/issues/show_bug.cgi?id=7069 (and has never 
worked despite being intended).


Can you send immutable struct references?



Re: Cleverness of the compiler

2013-11-25 Thread Shammah Chancellor

On 2013-11-25 10:34:39 +, Namespace said:


On Monday, 25 November 2013 at 03:13:48 UTC, Shammah Chancellor wrote:

On 2013-11-25 00:08:50 +, Namespace said:

I love this feature, but I'm unsure how it works. Can someone explain 
me, how the compiler deduce that he should read 4 bytes for each index 
(the 'at' function)? The type is void*, not int*.


It doesn't work.  That code is buggy.  It's overwriting previous 
elements with new ones.   Indexing a void* only moves up by 1 byte.


void main() {
pragma(msg, void.sizeof)
Tarray arr;
arr.push(42);
int a;
arr.at(0, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
arr.push(23);
arr.at(1, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
arr.push(1337);
arr.at(2, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
writeln(arr.capacity);
arr.push(ushort.max); //Write a ushort to test.
arr.at(3, &a); //Only works because we're on a little endian platform
writeln(a, "::", arr.length, "::", arr.capacity);
arr.at(2, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
}


Ok, that calms me down. Thought I had missed something.


Yeah.  You had me confused for a bit too.  :)  Couldn't figure out why 
Ushort.max was being re-read correctly.  I'm use to big-endian 
platforms.   It certainly would have been miraculous if the compiler 
knew what kind of elements you put in the array to be able to index to 
the right location.


-Shammah



Re: std.concurrency and immutable

2013-11-25 Thread Shammah Chancellor

On 2013-11-25 06:03:27 +, Antoche said:


The following code compiles but doesn't work as expected:

  import std.stdio;
  import std.concurrency;

  class A
  {
  this() immutable {}
  }

  void main()
  {
  auto tid = spawn( &fooBar, thisTid );
  while(true)
  {
  receive(
  (Variant any) {
  writeln( "Received a variant" );
  writeln( "Received ", any );
  }
  );
  }
  }

  void fooBar( Tid masterTid )
  {
  scope(failure) writeln( "fooBar failed" );
  scope(success) writeln( "fooBar succeeded" );
  scope(exit) writeln( "fooBar exiting" );
  try
  {
  immutable A b = new immutable A();
  masterTid.send( 42 ); // This works
  masterTid.send( b );  // This doesn't
  }
  catch( Exception e )
  {
  writeln( "Exception received" );
  }
  }


I see this in the console:

  fooBar exiting
  fooBar failed
  Received a variant
  Received 42

(then it just hangs)

I'm especially puzzled by:
   * Sending an int as a message works but not an immutable object.
Wasn't this  (safely sharing objects across threads) one of the
basic use cases for the immutable type qualifier?
   * scope(failure) failed but my exception handler didn't catch
anything. How is this possible? What could cause that?
Assertions/abort?

There seemed to be a 3-year-old ticket on this issue
(http://d.puremagic.com/issues/show_bug.cgi?id=5538) with very
little activity, which is a bit surprising given how much
emphasis is given to this feature (the D homepage mentions "D
offers an innovative approach to concurrency, featuring true
immutable data, message passing, no sharing by default, and
controlled mutable sharing across threads", and TDPL devotes a
whole chapter on it). This thread
(http://forum.dlang.org/thread/kgk8hc$12fa$1...@digitalmars.com)
also says std.concurrency is "very buggy".

If I can't use std.concurrency, is there any other safe
alternative for multithreaded programming with D?

Thanks,
A.



There is a bug with the internals of send/receive.   It has to be able 
to copy the reference to a another place while sending --  and it seems 
it can't do that because it's immutable. I don't think many people 
are using it.I personally did not realize the bug was from 2011.  I 
think DMD has been fixed enough to make a patch to phobos now.  I'm 
going to ping this bug report.


However,  even CONSTRUCTING immutable objects right now is very 
difficult.   It's arguably "correct" but, seems impossible to actually 
be able to make something of use without many many idups.  It's kind of 
in the same boat as shared.


What I am currently doing, is casting to shared, and then back.  I 
tried making my classes shared, and also immutable as you have.   
Nothing else seems to work:



class A
  {
  this() {}
  }

  void main()
  {
  auto tid = spawn( &fooBar, thisTid );
  while(true)
  {
  receive(

   (shared A _m)
   {
auto m = cast(A)_m;
//Do stuff.
   },

  (Variant any) {
  writeln( "Received a variant" );
  writeln( "Received ", any );
  }
  );
  }
  }

  void fooBar( Tid masterTid )
  {
  scope(failure) writeln( "fooBar failed" );
  scope(success) writeln( "fooBar succeeded" );
  scope(exit) writeln( "fooBar exiting" );
  try
  {
  immutable A b = new A();
  masterTid.send( 42 ); // This works
  masterTid.send( cast(shared) b );  // Should work
  }
  catch( Exception e )
  {
  writeln( "Exception received" );
  }
  }


-Shammah






Re: Cleverness of the compiler

2013-11-24 Thread Shammah Chancellor

On 2013-11-25 00:08:50 +, Namespace said:

I love this feature, but I'm unsure how it works. Can someone explain 
me, how the compiler deduce that he should read 4 bytes for each index 
(the 'at' function)? The type is void*, not int*.


It doesn't work.  That code is buggy.  It's overwriting previous 
elements with new ones.   Indexing a void* only moves up by 1 byte.


void main() {
 pragma(msg, void.sizeof)
Tarray arr;
arr.push(42);
int a;
arr.at(0, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
arr.push(23);
arr.at(1, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
arr.push(1337);
arr.at(2, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
 writeln(arr.capacity);
arr.push(ushort.max); //Write a ushort to test.
arr.at(3, &a); //Only works because we're on a little endian platform
writeln(a, "::", arr.length, "::", arr.capacity);
arr.at(2, &a);
writeln(a, "::", arr.length, "::", arr.capacity);
}



Re: Composing features at compile time

2013-11-24 Thread Shammah Chancellor
Based on what your actual problem is -- it seems like you need to 
refactor your code a little.   Also,  you should trust that the 
compiler optimizes correctly.


eg.

if( valueMeta.isValid && pointersSupported)  should be optimized out 
when pointerSupported == false and the comparison of it should be 
optimized out when it is true.




Re: std.json

2013-11-13 Thread Shammah Chancellor

On 2012-05-17 14:08:26 +, Vincent said:


On Sunday, 25 March 2012 at 17:50:45 UTC, Andrea Fontana wrote:

Hope it's clear...


Nope, it's something like chess and have nothing common with simplicity 
of the real JSON usage! This is example from C#:


var p = JsonConvert.DeserializeObject("{some real JSON, not 
crapy EOS}");

var str = JsonConvert.SerializeObject(p);

That's it! And this is how it SHOULD be implemented. Cannot catch why 
this stupid realization came to standard library... :((


This is planned in the upgrade to std.json which is currently being 
developed.   However, you'll note that you cannot parse generic JSON 
that way ( since you need a defined type "Person").   The current 
parseJSON is really a different feature from what exists in your 
example, and was implemented before opDispatch was introduced.   C# has 
a similar feature to deserialize JSON into ExpandoObjects, but that's 
also different from your example.




Reflecting on a module

2013-11-06 Thread Shammah Chancellor
How does one reflect on all the classes in a module?  I would like to 
read their attributes and generate an enum from attributes on said 
classes.