Re: Pegged v0.4: longest-match, left-recursion, and expandable parse trees

2017-03-03 Thread Philippe Sigaud via Digitalmars-d-announce

Thank you all for the positive comments!


Pegged v0.4: longest-match, left-recursion, and expandable parse trees

2017-03-02 Thread Philippe Sigaud via Digitalmars-d-announce

Hi,

Pegged is a parser generator based on Parsing Expression Grammars 
(PEG) written in D, that aims to be both simple to use and work 
at compile-time.


See: https://github.com/PhilippeSigaud/Pegged

To use Pegged, just call the grammar function with a PEG and mix 
it in your module. For example:


import pegged.grammar;

mixin(grammar(`
Arithmetic:
Term < Factor (Add / Sub)*
Add  < "+" Factor
Sub  < "-" Factor
Factor   < Primary (Mul / Div)*
Mul  < "*" Primary
Div  < "/" Primary
Primary  < Parens / Neg / Pos / Number / Variable
Parens   < "(" Term ")"
Neg  < "-" Primary
Pos  < "+" Primary
Number   < ~([0-9]+)

Variable <- identifier
`));

This will create the `Arithmetic` parser, that can parse your 
usual arithmetic expresion at runtime or compile-time.


// Parsing at compile-time:
enum parseTree1 = Arithmetic("1 + 2 - (3*x-5)*6");
// Runtime:
auto parseTree2 = Arithmetic("1 + 2 - (3*x-5)*6");

-


This minor release v0.4 (v0.4.1 right now) is on dub 
(code.dlang.org) right now and introduces the following new 
features:


 * A longest-match alternation operator, |, which will always 
choose the longest match during a parse. See 
[https://github.com/PhilippeSigaud/Pegged/wiki/Extended-PEG-Syntax] for more details and the interest of this operator for grammar writers.


 * The left-recursion engine, introduced in version v0.3.0 is now 
fully documented in the wiki at 
[https://github.com/PhilippeSigaud/Pegged/wiki/Left-Recursion]. 
Pegged can deal with left recursion, hidden left recursion and 
indirect left recursion. Try it!


 * These improvements allow Pegged to generate a parser that 
fully parses Extended Pascal files, based on the official ISO 
10206:1990 grammar. Have a look at it in the 
[https://github.com/PhilippeSigaud/Pegged/tree/master/pegged/examples/extended_pascal] directory.


 * The new toHTML function can be used to generate an HTML file 
containing an expandable tree view that can be manipulated with 
an HTML5-compliant browser. See 
[https://github.com/PhilippeSigaud/Pegged/wiki/Parse-Result] for 
more details on this new fun way to explore parse results (and 
parse failures!).



Pegged documentation can be found on the wiki 
[https://github.com/PhilippeSigaud/Pegged/wiki], along with a 
tutorial 
[https://github.com/PhilippeSigaud/Pegged/wiki/Pegged-Tutorial].



Thanks a lot for Bastiaan Veelo for these wonderful improvements 
to Pegged!





Re: Regex in ctfe?

2016-01-31 Thread Philippe Sigaud via Digitalmars-d

On Tuesday, 26 January 2016 at 01:34:09 UTC, Manu wrote:

Possible to std.regex in ctfe?

(...)
I have a string import destined for a mixin, and I want to 
parse it with regex, but I haven't been able to make it work. 
The docs mention nothing about this possibility.


Hi Manu,

a possible solution for that would be to use my Pegged 
(https://github.com/PhilippeSigaud/Pegged) project. It's a parser 
generator that creates compile-time (and runtime) parsers. It's 
not directly compatible with Phobos regexes, but it's quite easy 
to extract the matched strings.


Bastiaan Veelo recently added support for left-recursive 
grammars, which means we can now generate parsers for many more 
grammars (although if your parsing need is covered by regexes, 
that probably won't interest you...)



Philippe


Re: Reducing Pegged ASTs

2014-11-25 Thread Philippe Sigaud via Digitalmars-d-learn
On Tue, Nov 25, 2014 at 4:12 PM, Nordlöw
digitalmars-d-learn@puremagic.com wrote:
 Is there a way to (on the fly) reduce Pegged parse results such as

 C [0, 6][int, x, ;]
  +-C.TranslationUnit [0, 6][int, x, ;]
 +-C.ExternalDeclaration [0, 6][int, x, ;]
+-C.Declaration [0, 6][int, x, ;]
   +-C.DeclarationSpecifiers [0, 4][int]
   |  +-C.TypeSpecifier [0, 4][int]
   +-C.InitDeclaratorList [4, 5][x]
  +-C.InitDeclarator [4, 5][x]
 +-C.Declarator [4, 5][x]
+-C.DirectDeclarator [4, 5][x]
   +-C.Identifier [4, 5][x]

 to

 C [0, 6][int, x, ;]
  +-C.TranslationUnit [0, 6][int, x, ;]
 +-C.ExternalDeclaration [0, 6][int, x, ;]
+-C.Declaration [0, 6][int, x, ;]
   +-C.TypeSpecifier [0, 4][int]
   +-C.Identifier [4, 5][x]

 and still, when needed, be able query that C.Identifier is an instance of
 C.DirectDeclarator etc?

The reducing can be done, either with operators or semantic actions.
IIRC there is a free function in Pegged that does it.
I did not automate it, because every time I cut down severely a parse
tree, I later regret it because I lost information that way.

Cutting while still retaining original info (who is this node's
ancestor) is more difficult: you would have to store it somewhere
anyhow. You cannot create node classes to represent the hierarchy,
because of loops in the grammar: an Identifier can have many different
ancestors.

Note also that Pegged produces parse trees (complete parsing
information), not ASTs. ASTs would indeed be much smaller, but we
would have to define what are the master nodes in the D grammar.

 If not this seems like a cool feature to have ;)

 I guess it would reduce memory requirements by about a magnitude right?

If you want to remember the intermediate nodes you cut down, not
really, since you still need to store them somehow.

I think what's consuming memory right now is that I duplicate the
matched strings at each level, even concatenating them at the higher
levels. I should let them only in the 'leaves' of the tree (heck, like
an AST).

Halas, I've no free time to code anything in D these days... but of
course, feel free to push any pull request you might have!



Re: accessing numeric template parameters

2014-11-03 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Nov 3, 2014 at 3:27 PM, Dominikus Dittes Scherkl via
Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote:
 If I have a struct with numeric template parameter, how can I access it
 within member functions? Like normal member variables? And how about the
 constructor?

 struct polynomial(uint base)
 {
 private:
uint[] N;
 public:
this(uint x) { base = x; }

base is part of the type. polynomial is just a 'recipe' for a type,
the real struct would be Polynomial!(0), Polynomial!(1), etc. Note
that Polynomial!0, Polynomial!1, ... are all different types.

Being part of the type means it's defined only at compile-time, you
cannot use a runtime value (like 'x') to initialize it.

Note that with your current code, `base' is not visible outside
Polynomial. You can alias it to a field to make it visible:

struct Polynomial(uint base)
{
alias b = base; // b is visible outside (but set at compile-time !)
...
}

You can create one like this:

Polynomial!2 poly;
poly.N = [0,1,0,0,1,1];

assert(poly.b == 2);

Of course, you cannot change b: `poly.b = 3;' is forbidden.


Re: how to expand tuple?

2014-11-02 Thread Philippe Sigaud via Digitalmars-d-learn
Any time you want to return or store a group of values of different types.

In a way, tuples are just structs without a name (anonymous structs,
if you will).

Say you have function `foo' and want it to return an int and a string.
In D, you cannot do:

(int, string) foo() { ...  return (3, abc);}

But you can do:

import std.typecons: tuple;
auto foo() { return tuple(3, abc);}

Which is more or less equivalent to:

struct FooReturn { int i; string s;}
FooReturn foo() { return FooReturn(3, abc);}


`Tuple' and its associated factory function `tuple' is just the
standard way to group values together in Phobos. You'll see some
functions returning Tuples, for example. Some D constructs also
recognize std.typecons.Tuple and deal with it elegantly. By defining
you own struct (like `FooReturn' in the previous example), you gain
some control on your code (you can define how people can interact with
FooReturn, you can test for it, etc), but you also lose the
possibility of easy interaction with some parts of Phobos.


Re: how to expand tuple?

2014-11-01 Thread Philippe Sigaud via Digitalmars-d-learn
On Sat, Nov 1, 2014 at 9:34 PM, Suliman via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 Few questions.

 1. In examples tuples are created with keyword auto. Can I create them with
 another keyword. Or auto mean structure of data, that have not standard type
 like (int or string)?

`tuple' is a function defined in the std.typecons module. It's a
helper function to create Tuple!(T...), a templated struct acting as a
tuple.

Don't forget the type will depend on the types of the arguments, so:

auto tup = tuple(1.0, abc, [2,3]);

contains a float, a string and an array of int's, so it's type is
Tuple!(float, string, int[]):

Tuple!(float, string, int[]) tup = tuple(1.0, abc, [2,3]);

It's a bit long to type, so most people prefer using `auto' for such
declarations.




 2. How ti expend tuple? I tried to do:

auto imglist = tuple(aaa);
imglist.expand[sss];
writeln(imglist);

 but got very strange error:
 app.d(30): Error: cannot implicitly convert expression (sss) of type
 string to  uint

Expand, you mean, as in appending to a tuple? It can be done, but it
will create a new type.

First, tup.expand gives you access to the 'raw' tuple ( a template
parameter list, to be precise) underneath Tuple!(T...). The returned
value can be indexed, sliced and its length is known at compile time.

Continuing with my example:

auto first = tup.expand[0]; // 1.0
auto slice = tup.expand[1..$]; // (abc, [2,3])
auto len = tup.expand.length; // 3, since tup has three elements.

That explains the error you get: imglist.expand is a bit like a
vector: it can be indexed, but with uint, not with a string. I thought
you were expanding it, but to the compiler you were trying to index
using a string.


If you really want to append to a tuple, you must create a new
variable, since the augmented tuple will have a different type:

auto tup2 = tuple(tup.expand, 'd'); // tup2 == (1.0, abc, [2,3], 'd')

The type of tup2 is then Tuple!(float, string, int[], char)


Note that, in your case, as you're using only strings, an array of
strings would probably be easier to use.


Re: how to expand tuple?

2014-11-01 Thread Philippe Sigaud via Digitalmars-d-learn
 I thought you were expanding it

Drat. *You* thought you were expanding it.


Re: D Parsing (again)/ D grammar

2014-10-03 Thread Philippe Sigaud via Digitalmars-d
 Thanks a lot, by the way!

 I've just skimmed through the code and the README... You did not use the
 packed forest representation, did you..?

Sorry for the microscopic documentation (Pegged is more documented
than that...), it was a 'for me only' project.

The forest is packed, in the sense that common nodes are re-used and
shared among parse trees: all intermediate parse results from any
grammar part is stored and used to produce the parse nodes.

The range view gives access to parse trees one after another, but the
global parse forest is present in the grammar object (or rather,
generated and completed during the parse process: each new parse
result completes the parse forest).

It has a strange effect on parsing times repartition among the parse results:
If you time the different parse trees, you'll see that the first one
might take maybe 40% of the entire parsing time all by itself, because
it has to discover all parse results alone. The following trees are
very rapidly calculated, since the intermediate parse results are
already known. Of course, once the parse trees begin to deviate from
the first ones, the process slows down again since they have to
explore as-yet-unused rules and input slices.

I'm not sure the previous paragraph is clear...

Imagine you have 10 different parse trees. They could be disributed like this:

# parse result  % global parse time
1  40%
2  2
3  3
4  3
5  5
6  6
7  8
8  10
9  11
1012


Re: D Parsing (again)/ D grammar

2014-10-03 Thread Philippe Sigaud via Digitalmars-d
 Anyway, thank you very much for the code. The weekend is coming - I'll play
 with your implementation and see if there any improvements possible.

Be sure to keep me informed of any enormous mistake I made. I tried
Appender and other concatenation means, without big success.

Btw, I saw on the ML that using byKeys.front() is very slow. Use
keys[0] of somesuch instead.


Re: D Parsing (again)/ D grammar

2014-10-02 Thread Philippe Sigaud via Digitalmars-d
 Chances are that I will be able to get the original GLL parser generator
 from one of algorithm authors (Adrian Johnstone). He's really helpful here.
 From that point, I will only have to add a frontend for generating a
 concrete parser, starting with Python - it already has a fully working
 grammar. Hopefully, I will also be able to find a suitable grammar for D, it
 is always a pleasure to play with the language.

 Otherwise, I will continue my current effort - implementing the GLL parser
 generator in D.

I did that during this summer, almost to the point it was
self-sustained (that is, the GLL parser generator was used to generate
a parser for grammars files). I chose a range interface: input is a
string, the parse forest is output as a range of parse trees.

I loved to see it generate the different possible parse trees on
ambiguous grammars, and accepting left- and right-recursing grammars!
GLL is a very noce algorithm.

Halas, even with some shortcuts on Kleene stars it was quite slow. I
tried to use threads (spawning worker threads on alternatives), but
that did not change the timings much.

I could make it generate a parser for JSON and compared it to the
jsonx module that Sönke presented here. Bah, it was 1000 times slower
(which is all relative: it still takes only a few ms to parse a big
JSON file. But still, far away from the microseconds it should need).
Pegged was faster that this GLL generator, but of course still far
slower than jsonx.

[Of course, Pegged can cheat: it can parse your file at compile-time,
resulting in 0-µs parsing time at runtime :-)]

Also, the way I coded it I hit CTFE limits and could not have it parse
at compile-time. A shame, really.

 This is one of the reasons I prefer LL/RD parsers :-) They are easy to
 follow.

I would like to try a LALR compile-time generator and compile-time
parser. I'm pretty sure LALR tables could be expanded directly as D
code instead of being read during parsing.

Philippe



Re: D Parsing (again)/ D grammar

2014-10-02 Thread Philippe Sigaud via Digitalmars-d
 I did that during this summer, almost to the point it was
 self-sustained (that is, the GLL parser generator was used to generate
 a parser for grammars files). I chose a range interface: input is a
 string, the parse forest is output as a range of parse trees.


 Nice! Is it public? Github?

No github repo. I could put it alongside Pegged, I suppose. I used git
internally, though.

 I was a bit disheartened by the speed I got, so did not publish nor
announced it here.

Note also that I saw it as an alternative engine for my own Pegged
project, so I used the same way of defining grammars (some prefixes
ans suffixes for dropping nodes in the parse tree and so on).

I can send you the code (well the entire repo), if you wish. I did not
touch it for the past 3 months, so I already don't remember what state
it was in :-(.
Looking at the code now, it seems I'm still using Pegged to parse the
initial grammar. Bootstrapping did not go well.

Send me an email at firstname . lastname @gmail.com

(philippe sigaud)


 Halas, even with some shortcuts on Kleene stars it was quite slow. I
 tried to use threads (spawning worker threads on alternatives), but
 that did not change the timings much.


 AFAIK, multithreading is a bad idea in parsing.

I think, as many things in CS, that people developed parsing
algorithms before multicores existed.
Spawning threads or fibers for some alternatives (A | B) seems nice to
me. I got interesting results with a purely multithreaded parser that
spawned children for each choice.


 Actually, in the gll-combinators Scala project they have similar speed
 problems. I don't if it's a fundamental algorithm problem or an
 implementation details that lead to slowdowns.

Well, when all resulting implementations have speed problems...
I found an article by the GLL authors explaining how they coded their
algorithm for more speed, but I couldn't wrap my head around it.

Philippe


Re: D Parsing (again)/ D grammar

2014-10-02 Thread Philippe Sigaud via Digitalmars-d
 I have a huge collection of projects I never published :-) We all do, I
 guess.

Oh, the ratio is more and 100 projects for one published...


 No, this is not exactly what I mean. Multithreading can be perfectly fine in
 some cases, very fruitful sometimes. Say, in NLP, when one has to process
 long or highly ambiguous strings, and the parse tree can become huge and is
 of importance in itself... Yes. In programming language parsing this is just
 a small step towards further stages within a longer pipeline. It has to be
 fast enough to make multithreading on this step an overkill.

I don't know. Using fibers, I'm hoping to get interesting results one
day. I got it by a workstorm before trying fibers. OS threads were a
bit to heavy and didn't work that well.


 BTW, there's one an interesting related work that probably should be taken
 as a positive example of generalized parsing: the Elkhound parser generator.
 It uses a hybrid LALR/GLR approach, thus achieving better performance.
 There's much more to it, I didn't go too deep into it.

Yes, Elkhound is interesting, their approach is nice. But It gave me
the impression to be abandoned for a few years?


 I found an article by the GLL authors explaining how they coded their
 algorithm for more speed, but I couldn't wrap my head around it.


 By now, I have read the original Tomita's GLR paper, Antlr ALL(*) paper, a
 few recent GLR papers, three papers on GLL and a few related ones . It
 took... A while. I sort of understand the idea, but still not sure about the
 details :-)

ALL(*) is on my todo list. I tried to implement it in Spring, but got
bogged down in the details. Even the white paper has some imprecisions
when you really sit down and try to code it.
I could have a look at ANTLR v4 source, but wanted to have a clean
start, right from the white paper.

 What's the name of the paper you read? Modelling GLL Parser
 Implementation?

Yes.


Re: D Parsing (again)/ D grammar

2014-10-02 Thread Philippe Sigaud via Digitalmars-d
On Thu, Oct 2, 2014 at 11:19 PM, Vladimir Kazanov via Digitalmars-d
digitalmars-d@puremagic.com wrote:

 Check the mailbox,

 Thank you

I sent it to you. I was asleep, sorry :-)


Re: How to pack types with variables in one message to send it to another thread? [tuple]

2014-09-07 Thread Philippe Sigaud via Digitalmars-d-learn
You can also create new types:

struct UseSprite { string s;}
struct UseAnimation { string s;}


 It's not a class instance, it's a class type. Something like
 `cast(Sprite) null` in parameters. It can be replaced by string
 Sprite, but in this case I can't use receive() as it is. E.g.

 send(tid,gameobjectId,Sprite,reload);
 //must call sprite.reload();

You could use:

sent(tid, gameobjectId, UseSprite(reload));

 send(tid,gameobjectId,Animation,reload);
 //must call animation.reload();

sent(tid, gameobjectId, UseAnimation(reload));

Another way, if you have way to determine that gameobjectId points to
an animation or a sprite, would be to define a struct name Reload {}
and then:

sent(tid, gameobjectId, Reload());



Third way: if Animation.reload() and Sprite.reload() are static methods:

send(tid, gameobjectId, Sprite.reload);



 But both messages are (int, string, string) so they can't be separate by
 different receiving functions. It will be better if messages was (int,
 Sprite, string) / (int, Animation, string). And it solves my problem. :)
 But I don't know how to achieve this.

See my proposal: define your message as types, directly, and load them
for any data necessary for the call.
UseAnimation(reload), or whatever.


Re: literate programming in D

2014-09-04 Thread Philippe Sigaud via Digitalmars-d-learn
 Ah that sounds interesting too! Immediately I start thinking in terms like
 tidlywiki http://tiddlywiki.com/ or something similar, I guess the emacs way
 described earlier also would support this. I personally always enjoy reading
 the readthedocs stuff http://docs.readthedocs.org/en/latest/ is that the
 sort of stuff you mean?

Tiddlywiki is interesting, but I'm really talking about the way LP was
used by Knuth WEB/CWEB in his explanation of TeX and METAFONT.
The Wikipedia article explains it pretty well
(http://en.wikipedia.org/wiki/Literate_programming)

You write a document combining documentation and code. Then two
different programs (weave and ? for WEB) create the resulting
documentation for one (HTML, pdf, whatever) and the code (a .d file)
for another.


I discovered LP through the incredible book Physically-based
Ray-Tracing. The book is one program, explained and documented using
literate progamming. It's an incredible achievement (1000+ pages of
explanations!).
See:

www.pbrt.org

and more precisely:

http://www.pbrt.org/chapters/pbrt_chapter7.pdf

The code begins at page 18 of the pdf.

For example, at page 22:

Sample Method Definitions ≡
Sample::Sample(SurfaceIntegrator *surf, VolumeIntegrator *vol,
const Scene *scene) {
surf-RequestSamples(this, scene);
vol-RequestSamples(this, scene);
Allocate storage for sample pointers 301
Compute total number of sample values needed 302
Allocate storage for sample values 302
}

The snippet Sample Method Definitions introduces three new snippets,
that will be explained elsewhere. Other snippets might also use the
same references, if needed.

It's not complicated to write a D tool for that, I did that some time
ago. Once you define your begin/end token for snippet definitions, you
can parse them to extract the way they are linked.



Re: String to binary conversion

2014-09-03 Thread Philippe Sigaud via Digitalmars-d
On Wed, Sep 3, 2014 at 7:59 PM, Ali Çehreli digitalmars-d@puremagic.com wrote:

 Also, I've just noticed that Questions about learning D sounds a little
 off because it sounds as if the questions should be like how can I learn
 D. :) How about something like Questions when learning D.

Or even: Learning D



Re: Daemonize v0.1 - simple way to create cross-platform daemons

2014-08-31 Thread Philippe Sigaud via Digitalmars-d-announce
Nice!

I have a few questions/remarks, mainly to simplify the API somewhat.
Please bear with me :-)

 // First you need to describe your daemon via template
 alias daemon = Daemon!(
 DaemonizeExample1, // unique name

Does the user sees/uses this name in any way afterwards? Because I
think you could also produce a unique string at compile-time (by using
__FILE__ and __LINE__, unless someone has a better idea), if the user
does not provide one. Maybe he just wants an anonymous daemon, or
doesn't care, whatever.


 // Setting associative map signal - callbacks
 KeyValueList!(

If I understand correctly, the Daemon template waits for a list of (at
least one) Signal, then a delegate, then some more Signals, another
delegate, and so on?

If that's so I think you could ditch KeyValueList (or build it
invisibly to the user) and let the user write only the signals and
delegates:

alias daemon = Daemon!(
Signal.Terminate, Signal.Quit, Signal.Shutdown, Signal.Stop,
(logger, signal) {
...},
Signal.Hangup,
(logger) {
...}
...
);

Iterate the argument list, collecting Signals. When you hit a
delegate, create a Composition!( ... ) with the previous signals, jump
above the delegate and so on.

Is the idea that, if the delegate has two arguments, then the second
is the signal that will be passed to it, and if it has only one
argument, only the logger will be passed?

What if the user does not want a logger? Is a daemon always associated
to a log file in OSes?



 // Main function where your code is
 (logger, shouldExit) {
 // will stop the daemon in 5 minutes
 auto time = Clock.currSystemTick +
 cast(TickDuration)5.dur!minutes;
 while(!shouldExit()  time  Clock.currSystemTick) {  }

 return 0;
 }

Is the main function always the last delegate?

Concerning the DaemonClient template, could you not ask for Daemon to
generate it on demand? Or is DaemonClient always used in another
module?

Because, given a Daemon, extracting the simplified DaemonClient can be
done, I think.


 * Custom signals

enum Signal : string
{ ... }

@nogc Signal customSignal(string name) @safe pure nothrow
{
return cast(Signal)name;
}

I didn't know you could have an enum and extend it with a cast like this. Wow.


 * Signal composition

What happens when an unhandled signal is passed to a daemon?


 P.S. At the moment library doesn't support Mac and other Posix systems, the
 support is going to be added at next releases.

Do you foresee any difficulty in adapting this to Mac?


Re: Daemonize v0.1 - simple way to create cross-platform daemons

2014-08-31 Thread Philippe Sigaud via Digitalmars-d-announce
 Does the user sees/uses this name in any way afterwards? Because I
 think you could also produce a unique string at compile-time (by using
 __FILE__ and __LINE__, unless someone has a better idea), if the user
 does not provide one. Maybe he just wants an anonymous daemon, or
 doesn't care, whatever.

 Yes, the name is used in windows service manager (you can start/stop the
 daemon by control panel) and for default locations of .pid and .lock files.

OK.

 Auto generated name will prevent sending signals and could be ugly displayed
 in service manager. The feature is useful for simple daemons, I will play
 around with that idea to find out if it worth.

Great.


 I will add the approach in next release (it requires some more additional
 templates to wrap all the mess) thanks to arguments grammar has no
 ambiguities.

Yes, the grammar is simple, use it to simplify the life of your users.

 Is the idea that, if the delegate has two arguments, then the second
 is the signal that will be passed to it, and if it has only one
 argument, only the logger will be passed?

 Yes

OK.
IIRC, I read in your code that composed signals means the next
delegate must have the (logger, signal) {...} form.
Why?


 What if the user does not want a logger? Is a daemon always associated
 to a log file in OSes?

 It is a general rule as the stderr and stdout files are closed. At next
 version I want to use duck typing for logger (or sink approach same as
 toString uses) and add a feature to reopen stderr/stdout to another file.

OK.


 Concerning the DaemonClient template, could you not ask for Daemon to
 generate it on demand? Or is DaemonClient always used in another
 module?

 DaemonClient is designed to be used in another module, you can send signals
 with full Daemon template.

OK. I'd have thought that just having the name of the daemon would be
enough to send it signals.

 What happens when an unhandled signal is passed to a daemon?

 The event is logged down and ignored.

Is that the standard behavior for daemons in OSes?
You could have the daemon stopped, after logging the unhandled signal.
Or you could also block compilation if a daemon does not handle all signals...
Or have a 'catch-all' delegate, as std.concurrency.receive, which uses
a (Variant v) {...} delegate at the end.
See:
http://dlang.org/library/std/concurrency/receive.html

(btw, signals could also be types and you could have a handling syntax
similar to receive).


Re: Daemonize v0.1 - simple way to create cross-platform daemons

2014-08-31 Thread Philippe Sigaud via Digitalmars-d-announce
On Sun, Aug 31, 2014 at 11:36 PM, Meta via Digitalmars-d-announce
digitalmars-d-announce@puremagic.com wrote:
 I didn't know you could have an enum and extend it with a cast like this.

 This is not a good thing. Enums are supposed to denote a *closed*,
 enumerated set of items.

I agree.

 It's fine here (but IMO bad style) because the
 author expects there to be user-created values casted to Signal passed to
 functions/templates that expect a Signal, but this would wreak havoc on code
 that was expecting a valid enum value (by valid, I mean only one of the
 predefined enum values).

I was about to suggest final switch, until I saw this extension of
Signal. I wonder what happens to final switch in this case.


Re: Daemonize v0.1 - simple way to create cross-platform daemons

2014-08-31 Thread Philippe Sigaud via Digitalmars-d-announce
 I can (not must) have the form, the delegate params are tested independently
 from signal composition.

OK, good.

 Is that the standard behavior for daemons in OSes?

 Most signals are simply ignored (except termination ones).

I see.

 Some signals could be sent without any reason: sighup or interrogate in
 windows.
 Ignoring most signals is a better strategy, the exception could be done for
 terminating signals - their default handlers should set `shouldExit` flag to
 true.

OK, I didn't know that.

 http://dlang.org/library/std/concurrency/receive.html

 Good idea, it will be implemented.

Great!


Re: Clojure transducers

2014-08-31 Thread Philippe Sigaud via Digitalmars-d
 What is D's attitude toward this concept?

Hickey's original announcement is also interesting to read. Elegant, as always.

It seems to me that ranges and range algorithms in D already permit
this composition of actions, without the creation of intermediate
structures:

import std.algorithm;
import std.functional: pipe;

alias incsum = pipe!(
map!(x = x+1),
reduce!((x,y) = x+y)
);

alias filtermap = pipe!(
   filter!(x = x%2==0),
   map!(x = x+1)
  );

alias mapfilter = pipe!(
map!(x = x+1),
   filter!(x = x%2==0)
  );

void main() {
auto sequence = iota(10);
writeln(incsum(sequence)); // 55
writeln(filtermap(sequence)); // [1, 3, 5, 7, 9]
writeln(mapfilter(sequence)); // [2, 4, 6, 8, 10]
}


Re: How to build dlang.org dd files

2014-08-31 Thread Philippe Sigaud via Digitalmars-d-learn
 dmd -c -o- macros.ddoc doc.ddoc -Df{ddoc_filename}.html {ddoc_filename}.dd

 If someone knows of a more official syntax, please let me know.

I don't know of another syntax, but could you please put this
somewhere on the wiki?
Maybe in the cookbook section:

http://wiki.dlang.org/Cookbook


Re: alias and mixin

2014-08-31 Thread Philippe Sigaud via Digitalmars-d-learn
 It is basically just an annoying grammar limitation that does not allow to
 use mixin / __traits as an identifier.

The usual helper template:

```
alias helper(alias a) = a;
```

helps for aliasing __traits and anonymous function templates (x =
x+1), but I don't see an easy solution for mixin inside the current
language, apart from pushing the mixin outside.


Re: alias and mixin

2014-08-31 Thread Philippe Sigaud via Digitalmars-d-learn
 I recommend slightly more generic form:

 template Alias(T...)
 if (T.length == 1)
 {
 alias Alias = T[0];
 }

 it is quite helpful in templated code to be able to alias _anything_

That's what I use also, but didn't want another thread on the (T...)
if (T.length ==1) trick :)



 But yeah, no fun for mixins :(

Mainly, I slap them in my code, then slowly migrate them outwards (in
'head' position) until that compiles...


Re: literate programming in D

2014-08-30 Thread Philippe Sigaud via Digitalmars-d-learn

On Sat, Aug 30, 2014 at 1:37 AM, nikki wrote:
I wasn't too happy about it and I wrote my own little parse 
thingie and have

a literate version nice and meta and small and sloppy ;)

http://nikkikoole.github.io/docs/dokidokDOC.html

I use it to change my d sourcefile slightly (into valid 
markdown)
then I use a node module (ghmd) to make sortof sexy html from 
that.


Nice. Maybe you could strip the initial whitespaces in the code 
parts: due to blocks, your code lines are shifting to the right. 
If you document something that's inside a method inside a class, 
you're bound to have problems :)



Right now, you're documenting your code in a linear way. That's 
good, but for me, most of LP is based around the idea of naming 
snippets and referring to them in code, to be explained elsewhere:


```
Here is the main loop:

Main=
void main() {
Initialize Variables
Precompute State
foreach(i; 0..max) {
Do Computation
}
}

Before doing all this, we need to initialize the variables:

Initialize Variables= ...
```

Of course, snippets can refer to other snippets, recursively.

Do you have any plan to go there?


Re: literate programming in D

2014-08-30 Thread Philippe Sigaud via Digitalmars-d-learn

On Friday, 29 August 2014 at 23:58:19 UTC, Chris Cain wrote:
I used https://www.npmjs.org/package/literate-programming (+ 
pandoc) to do this when writing 
https://dl.dropboxusercontent.com/u/2206555/uniformUpgrade.pdf 
in markdown.


Do you remember if some snippets can be hidden in the final 
documented output (I don't find that in this package)?
I know the goal of LP is to explain your code, but I remember 
using that with other systems: that's useful when you don't want 
to show some plumbing (for a tutorial for example, where you want 
to concentrate on the main suject).




Re: getting the adress of a function by its name in string format

2014-08-30 Thread Philippe Sigaud via Digitalmars-d-learn
 instead I would like to use EAT_FOOD_DECISION and EAT_FOOD_BEHAVIOUR and
 get the functions?

 Is that possible somehow?

If all your functions had the same signature, you could use an
associative array  FunctionType[string] and initialize it:

FunctionType[string] myFuncs;
myFuncs[EAT_FOOD_DECISION] = EAT_FOOD_DECISION;

But it seems they have different types?


Re: Crazy code by Adam on SO

2014-08-29 Thread Philippe Sigaud via Digitalmars-d
 http://stackoverflow.com/questions/2329/d-finding-all-functions-with-certain-attribute

That's what a good part of his book is about, also. A nice read, one
of my favorite chapters of the D Cookbook.
Ideally, Adam should do a PR for Phobos to add some code-walking
ability like this.

I'm interested by any answer on one of his points: is there currently
a way to find function-local imports?


Re: Crazy code by Adam on SO

2014-08-29 Thread Philippe Sigaud via Digitalmars-d
On Fri, Aug 29, 2014 at 7:12 PM, H. S. Teoh via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 The mixin(import ...) line was mind-blowingly ingenious, I have to
 say.

I remember using the same 'module' trick a few years ago (that is,
getting a name with __traits and testing whether it begins with
module  or not) and, like Adam, being a bit ashamed by what I just
did :) While reading his book this summe, I was, like, Oh, then this
is what we all do.

Ideally, there should be a __traits(getModules) or
__traits(getImports, ...). I know, I know, where is the PR?.

Also, this helper!(__traits) just to avoid a hole in the alias syntax
is... what we all do here I suppose, but honestly the parser should
accept

alias member = __traits(getMember, ID, memberName);

as valid D code.


Re: Crazy code by Adam on SO

2014-08-29 Thread Philippe Sigaud via Digitalmars-d
On Friday, 29 August 2014 at 17:29:34 UTC, H. S. Teoh via 
Digitalmars-d wrote:



A lot of Adam's stuff are in that category.

(...)
I highly recommending studying how Adam's code achieves this. 
:-)


It's also a bit hypnotic. I wanted to do a quick test of his 
simpledisplay.d module, after reading one of his recipes. I 
fetched his github repo and... found myself one hour later, still 
reading a totally different module :)





Re: const after initialization / pointers, references and values

2014-08-21 Thread Philippe Sigaud via Digitalmars-d
On Wed, Aug 20, 2014 at 11:49 PM, Jakob Ovrum via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 Certainly the easiest, but I don't think it's always the best. If
 light-weightedness is desired, make the struct contain the reference,
 effectively making the struct a reference type

Well, yes. But the OP explicitly asked not to have to deal with pointers. So...


Re: const after initialization / pointers, references and values

2014-08-20 Thread Philippe Sigaud via Digitalmars-d
 After initialization there is no need to modify the data anymore.
 My first question is: can the data be changed to const once
 initialized?

You can have const or immutable data, that can be initialized once.
I tend to use pure functions to do that:


struct Node {
Node[] block;
uint num = 0;
}

Node makeDefaultNode() pure {
return Node(null, 1);
}

void main(){
immutable Node n = makeDefaultNode();

import std.stdio;
writeln(n);
writeln(typeof(n).stringof);// immutable(Node)
}

You can also use module constructors:

module foo;

immutable myDefault;

static this() {
myDefault = ...
}

/* rest of code */

I cannot comment much more. I use functions to initialize my immutable
values. I don't know much about module constructors.


 Related to that, how can the default initializer be changed to
 immutable?

In your example code, your default value can be marked immutable, if
you want it.
Just use:

immutable Node[] default_nodes = [
{num:3},
{block:[{num:4},{num:6},{block:[{num:5},{num:7}]}]},
// ...
];

 The second question is related to pointers, references and values
 I know that structs by default use value semantics, but as data
 is large I want to avoid data copying.
 But I would like to avoid use of pointers, so, is there a way of
 using reference semantics in the example code?
 Maybe is as simple as changing from struct Node to class
 Node, but seems intuitive that classes carry more overhead than
 structs.

If you want reference semantics but do not want to have pointers in
your code, yes classes are your best choice.


 How much overhead carries a class in comparison to a struct?

There is an overhead when calling functions, due to the virtual table.
But that's mainly when you construct hierarchies of classes, so that
the runtime can determine which method to call for each object. If you
don't need derived classes, then I guess using a final class is your
best bet. I think it discards the virtual table.

final class { ... }

I'd say: test it. Duplicate your module, change your structs to final
classes and compare the speed of the two modules.


Re: Variadic parameter of length 1

2014-08-20 Thread Philippe Sigaud via Digitalmars-d-learn
On Wed, Aug 20, 2014 at 5:34 PM, Dominikus Dittes Scherkl via
Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote:
 On Wednesday, 20 August 2014 at 15:26:14 UTC, monarch_dodra wrote:

 AFAIK, it's a historical workaround to accept T as either alias or not
 alias, as varargs have auto alias. EG:

 foo!int //OK
 foo!hello //OK too


 Ah, ok.
 And why historical? Is that not necessary anymore? What better solution is
 there today?

No better solution that I know of.

alias template parameters (alias a) match symbols (names, user-defined
types) whereas type parameter (T) match only pure types.

So when we need to match anything, we use (T...) if (T.length == 1)


Re: No Output with shebang.

2014-08-20 Thread Philippe Sigaud via Digitalmars-d-learn
 gdc just compiles the program to a.out. It doesn't run the
 resulting executable. You need to use something like rdmd instead
 of gdc. rdmd compiles to some temporary location and then runs
 the executable.


 Wow, that was fast. Thanks a lot!

Can compiler switches be used with the shebang notation? If yes, there
is certainly a GDC flag (-run?) that tells it to run the generated
executable.


Re: Cross-Platform D

2014-08-19 Thread Philippe Sigaud via Digitalmars-d
On Tuesday, 19 August 2014 at 11:14:17 UTC, Vladimir Panteleev 
wrote:

You realize you're replying to a decade-old post, right?


What about storing D files on BETAMAX tapes? Oh, wait.


Re: Why does D rely on a GC?

2014-08-19 Thread Philippe Sigaud via Digitalmars-d
 I won't look at it again for a different reason. They're the types that
 say A monad is just a monoid in the category of endofunctors, what's
 the problem?


 Sure, so one should point out that problem may be made out to be that the
 monoidal product [1][2] is underspecified for someone unfamiliar with the
 convention (in this case it should be given by composition of endofunctors,
 and the associator is given pointwise by identity morphisms). (But of
 course, the more fundamental problem is actually that this characterization
 is not abstract enough and hence harder to decipher than necessary. A monad
 can be defined in an arbitrary bicategory... :o) )

 What do /you/ think is the problem?

I remember finding this while exploring Haskell, some years ago:

http://www.haskell.org/haskellwiki/Zygohistomorphic_prepromorphisms

And thinking: Ah, I get it, it's a joke: they know they are considered
a bunch of strangely mathematically-influenced developers, but they
have a sense of humor and know how to be tongue-in-cheek and have
gentle fun at themselves. (My strange free association was: Zygo =
zygomatics muscle = smile  laughter = joke).

That actually got me interested in Haskell :)
But, apparently, I was all wrong ;-) It got me reading entire books on
category theory and type theory, though.


Re: iterate traits ?

2014-08-19 Thread Philippe Sigaud via Digitalmars-d-learn
 A foreach becomes compile-time whenever the aggregate is a purely compile-
 time construct such as a tuple.

Yeah, I think you transformed it into a runtime array by using [ ...
]. Tuples with compatible types can be 'downgraded' to arrays that
way. But there is no need to: tuples are iterable, indexable and
slice-able in D.

import std.stdio;

struct Vertex {float[3] position; float[3] normal;}

void main() {
foreach(e; __traits(allMembers, Vertex)) {
alias tt = typeof(__traits(getMember, Vertex, e)); // worksforme
writeln(tt.sizeof);

}
}


Re: @safe, pure and nothrow at the beginning of a module

2014-08-16 Thread Philippe Sigaud via Digitalmars-d-learn
 If I understand correctly Adam Ruppe's Cookbook, by putting

 @safe:
 pure:
 nothrow:

 at the beginning of a module, I distribute it on all definitions, right?
 Even methods, inner classes, and so on?

I read Adam's book again and I was wrong:

Chapter 7, p. 173:

You may add @safe: to the top of your module and aggregate
definitions to apply the annotation to all function that follows,
instead of writing it on each individual function.

So, first, he's talking only about @safe (though I suppose it works
the same for all annotations) and he says: *and aggregate
definitions*. We indeed need to put annotations inside aggregates to
affect their innards.

If that's true, I have a lot of annotation sprinkling to do.


Re: @safe, pure and nothrow at the beginning of a module

2014-08-16 Thread Philippe Sigaud via Digitalmars-d-learn
On Sat, Aug 16, 2014 at 1:30 PM, Artur Skawina via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 On 08/16/14 13:18, Philippe Sigaud via Digitalmars-d-learn wrote:
 We indeed need to put annotations inside aggregates to
 affect their innards.

 If that's true, I have a lot of annotation sprinkling to do.

 It's not true for @safe, but true for some other attributes.

 http://forum.dlang.org/post/mailman.125.1397731134.2763.digitalmar...@puremagic.com

Okay...

So @safe includes child scopes. I suppose @trusted and @system work in
the same way.

*but*

nothrow, @nogc and UDA's do not include child scopes. Putting them at
the beginning of a module will not affect methods in aggregates...

What's the situation for pure? (I don't have a D compiler handy right
now, or I would test it myself).


Re: @safe, pure and nothrow at the beginning of a module

2014-08-16 Thread Philippe Sigaud via Digitalmars-d-learn
Artur:
 @safe, @trusted, @system, shared, immutable, const, inout and `extern (...)`
 affect child scopes. `synchronized` does too, but in a rather unintuitive
 way; hopefully nobody uses this. ;)

Well, I also hope no one uses inout: at the module level?

 Other attributes, including 'pure' and 'nothrow' only affect symbols
 in the current scope.

There we are. Good to know, thanks.


Re: Automatic Inference for Both Key and Value Types of an Associative Array

2014-08-15 Thread Philippe Sigaud via Digitalmars-d
Kenji Hara:
 I implemented partial type deduction in AA keys.
 https://github.com/D-Programming-Language/dmd/pull/3615

 For example:
 auto[auto[$]] aa5 = [[1,2]:1, [3,4]:2];
 static assert(is(typeof(aa5) == int[int[2]]));

 int[int[][$]] aa15 = [[[1],[2]]:1, [[3],[4]]:2];
 static assert(is(typeof(aa15) == int[int[][2]]));

It's wonderful! I like it a lot.
As for Walter's question about the syntax, I quite like the [$]
thingie. '$' is already associated with 'length' in my mind.


Re: How to declare a parameterized recursive data structure?

2014-08-15 Thread Philippe Sigaud via Digitalmars-d
On Fri, Aug 15, 2014 at 9:13 PM, artemav via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 :) Wow, thanks for all replies. I realized too late that should write
 that's it.
 Hmm, It's also a good sign that D community is active.

Can I add something? ;)

You can also use a class, as they are reference types:

class node(T) {
T data;
node next;
}

Or use a dynamic array if you want to define a tree:

struct node(T) {
T data;
node[] children;
}


Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
 Quick test...

Ah, thanks a lot Jonathan. I kept telling me I should probably test it
on a simple case.
OK, the good news is, Appender works in these cases (I mean, that's
good news for Phobos).
Now, I just have to find out why it's slower in my case :)



 
 import std.array;
 import std.datetime;
 import std.stdio;

 enum size = 1000;

 void test1()
 {
 auto arr = appender!(int[])();
 foreach(n; 0 .. size)
 arr.put(n);
 }


I used ~= to append to an Appender. The examples use .put, but ~= is
documented so I considered the operator was just syntax sugar. I
didn't have a look at its implementation.


 void test2()
 {
 int[] arr;
 foreach(n; 0 .. size)
 arr ~= n;
 }

 void test3()
 {
 auto arr = new int[](size);
 foreach(n; 0 .. size)
 arr[n] = n;
 }

This one is simple and interesting. In my case I don't know the length
in advance (I'm doing some parsing and predicting the size of the
parse forest based on the input length is somewhat tricky), but I can
pre-allocate some, based on a simple heuristics.

 void test4()
 {
 auto arr = uninitializedArray!(int[])(size);
 foreach(n; 0 .. size)
 arr[n] = n;
 }

Oh, I didn't know this one.


 With size being 1000, I get

 178 ms, 229 μs, and 4 hnsecs
 321 ms, 272 μs, and 8 hnsecs
 27 ms, 138 μs, and 7 hnsecs
 24 ms, 970 μs, and 9 hnsecs

Same here, good.
Using ~= n instead of .put(n) gives me results consistently slightly
slower for Appender (170 ms - 190 ms, repeatedly, even going back and
forth between the two possibilities.
I created a test1prime to test that.


 With size being 100,000, I get

 15 secs, 731 ms, 499 μs, and 1 hnsec
 29 secs, 339 ms, 553 μs, and 8 hnsecs
 2 secs, 602 ms, 385 μs, and 2 hnsecs
 2 secs, 409 ms, 448 μs, and 9 hnsecs

Ditto. OK, that's good. Also, it's still slower with using Appender ~=
n instead of Appender.put. (18s instead of 15, 20% slower)
So, kids: don't do that.

 So, it looks like using Appender to create an array of ints is about twice
 as fast as appending to the array directly, and unsurprisingly, creating the
 array at the correct size up front and filling in the values is far faster
 than either, whether the array's elements are default-initialized or not.
 And the numbers are about the same if it's an array of char rather than an
 array of int.

Perfect. That also means my go-to method will still be using standard
arrays, but with pre-allocation.
I just feel stupid writing that, because it's obvious that reserving
things should give it better speed.


 Also, curiously, if I add a test which is the same as test2 (so it's just
 appending to the array) except that it calls reserve on the array with size,
 the result is almost the same as not reserving. It's a smidgeon faster but
 probably not enough to matter. So, it looks like reserve doesn't buy you
 much for some reason. Maybe the extra work for checking whether it needs to
 reallocate or whatever fancy logic it has to do in ~= dwarfs the extra cost
 of the reallocations? That certainly seems odd to me, but bizarrely, the
 evidence does seem to say that reserving doesn't help much. That should
 probably be looked into.

Yeah, I get a small boost of 5% compared to not reserving at size
1000, which completely disappears for longer arrays.
(No different for size 100_000).


 In any case, from what I can see, if all you're doing is creating an array
 and then throwing away the Appender, it's faster to use Appender than to
 directly append to the array.

Indeed.

 Maybe that changes with structs? I don't know.

I'm using classes, because what I'm pushing into the Appender are
graph nodes and I got fed up with tracing pointer to strucs
everywhere. Maybe I should change back to structs and see what it
does.


 It would be interesting to know what's different about your code that's
 causing Appender to be slower, but from what I can see, it's definitely
 faster to use Appender unless you know the target size of the array up
 front.

Good conclusion. Thanks for your help. My takeaway idea is that I'll
use arrays, but 'new T[](size)' them before. If that makes heavy
concatenation 10 times faster, it should have a positive effect (I'm
not of course waiting for anything near a 10x boost in my computation
time).



Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
 I wonder if using plain `Array` instead may be result in better performance
 where immutability is not needed.

Hmm, no:

module appendertest;

import std.array;
import std.datetime;
import std.stdio;
import std.container;

enum size = 1_000;

void test1()
{
auto arr = appender!(int[])();
foreach(n; 0 .. size)
arr.put(n);
}

void test1prime()
{
auto arr = appender!(int[])();
foreach(n; 0 .. size)
arr ~= n;
}

void test2()
{
int[] arr;
foreach(n; 0 .. size)
arr ~= n;
}

void test2prime()
{
int[] arr;
arr.reserve(size);
foreach(n; 0 .. size)
arr ~= n;
}

void test3()
{
Array!int arr;
foreach(n; 0 .. size)
arr ~= n;
}

void test3prime()
{
Array!int arr;
arr.reserve(size);
foreach(n; 0 .. size)
arr ~= n;
}

void test4()
{
auto arr = new int[](size);
foreach(n; 0 .. size)
arr[n] = n;
}

void test5()
{
auto arr = uninitializedArray!(int[])(size);
foreach(n; 0 .. size)
arr[n] = n;
}

void main()
{
auto result = benchmark!(test1, test1prime,
 test2, test2prime,
 test3, test3prime,
 test4,
 test5
)(10_000);

writeln(Appender.put   :, cast(Duration)result[0]);
writeln(Appender ~=:, cast(Duration)result[1]);
writeln(Std array  :, cast(Duration)result[2]);
writeln(Std array.reserve  :, cast(Duration)result[3]);
writeln(Array  :, cast(Duration)result[4]);
writeln(Array.reserve  :, cast(Duration)result[5]);
writeln(new T[]()  :, cast(Duration)result[6]);
writeln(uninitializedArray :, cast(Duration)result[7]);
}

Times:

Appender.put   :157 ms, 602 μs, and 3 hnsecs
Appender ~=:182 ms, 807 μs, and 1 hnsec
Std array  :256 ms, 210 μs, and 7 hnsecs
Std array.reserve  :244 ms, 770 μs, and 4 hnsecs
Array  :336 ms, 207 μs, and 3 hnsecs
Array.reserve  :321 ms, 500 μs, and 6 hnsecs
new T[]()  :28 ms, 496 μs, and 6 hnsecs
uninitializedArray :26 ms and 620 μs



Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
On Thu, Aug 14, 2014 at 11:33 PM, Joseph Rushton Wakeling via
Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote:
 On 14/08/14 19:16, Philippe Sigaud via Digitalmars-d-learn wrote:

 Do people here get good results from Appender? And if yes, how are you
 using it?


 An example where it worked for me:
 http://braingam.es/2013/09/betweenness-centrality-in-dgraph/

 (You will have to scroll down a bit to get to the point where appenders get
 introduced.)

I remember reading this and loving it! Any news on this? Do you have
new algorithms?


Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
 It is very different with better compiler though :

 $ ldmd2 -release -O a.d
 $ ./appendertest
 Appender.put   :378 ms, 794 μs, and 9 hnsecs
 Appender ~=:378 ms, 416 μs, and 3 hnsecs
 Std array  :2 secs, 222 ms, 256 μs, and 2 hnsecs
 Std array.reserve  :2 secs, 199 ms, 64 μs, and 5 hnsecs
 Array  :349 ms and 250 μs
 Array.reserve  :347 ms, 694 μs, and 1 hnsec
 new T[]()  :37 ms, 989 μs, and 8 hnsecs
 uninitializedArray :39 ms, 333 μs, and 3 hnsecs

 (size 10_000)

OK, same here, except std array gives me only 1.4 s, while the other
timings are about the same. (0.14 alpha2 : ldmd2 -O -inline).
Drat, that means testing on many different compilers. Oh well, let's
start small: pre-allocating, better algorithms, then I'll do real
speed instrumentation.



Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
On Fri, Aug 15, 2014 at 1:57 PM, Messenger via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 T[size] beats all of those on dmd head, though it is inarguably a
 bit limiting.

I confirm (even with 2.065). With ldc2 it's optimized out of the way,
so it gives 0 hnsecs :-)
Hmm, what about a sort of linked list of static arrays, that allocates
a new one when necessary?


Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
Well, I created a wrapper around a std.array.uninitializedArray 
call, to manage the interface I need (queue behavior: pushing at 
the end, popping at the beginning). When hitting the end of the 
current array, it either reuse the current buffer or create a new 
one, depending of the remaining capacity.


On the 'synthetic' benchmarks, it performs quite reasonably: half 
the time of  Array or Appender (twice faster), 5x faster than 
standard array, and 3-4x slower than uninitializedArray.


And... It does not change the timings in my code, it even makes 
things slower when pre-allocating to much. Only by pre-allocating 
only a few elements do I get back the original timings.


So, I guess I'm suffering from a bad case of premature 
optimization :)


I thought that, having lots of concatenation in my code, that'd 
be a bottleneck. But it appears than pre-allocation does not give 
me any speed-up.


Well, at least it got me thinking, testing LDC a bit more and 
learning things on Array and Appender ;)


Thank for your help guys, it's now time for the -profile switch 
again...




@safe, pure and nothrow at the beginning of a module

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn

So I'm trying to use @safe, pure and nothrow.

If I understand correctly Adam Ruppe's Cookbook, by putting

@safe:
pure:
nothrow:

at the beginning of a module, I distribute it on all definitions, 
right? Even methods, inner classes, and so on?


Because I did just that on half a dozen of modules and the 
compiler did not complain. Does that mean my code is clean(?) or 
that what I did has no effect?




Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn

On Friday, 15 August 2014 at 16:48:10 UTC, monarch_dodra wrote:
On Friday, 15 August 2014 at 14:40:36 UTC, Philippe Sigaud 
wrote:
Well, I created a wrapper around a 
std.array.uninitializedArray call, to manage the interface I 
need


Make sure you don't use that if your type has elaborate 
construction, or assumes a certain initial state (unless you 
are actually emplacing your objects of course).


Hmm, what's elaborate construction? They are classes and have 
constructors, of course. I assumed that this produced only null's 
in the array.



I thought that, having lots of concatenation in my code, 
that'd be a bottleneck. But it appears than pre-allocation 
does not give me any speed-up.


If you are using raw GC arrays, then the raw append 
operation will, outweigh the relocation cost on extension. So 
pre-allocation wouldn't really help in this situation (though 
the use of Appender *should*)



OK.


Re: @safe, pure and nothrow at the beginning of a module

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
In another module I marked as '@safe:' at the top, the compiler told
me that a class opEquals could not be @safe (because Object.opEquals
is @system).

So it seems that indeed a module-level '@safe:' affects everything,
since a class method was found lacking.

(I put a @trusted attribute on it).


Re: Appender is ... slow

2014-08-15 Thread Philippe Sigaud via Digitalmars-d-learn
On Fri, Aug 15, 2014 at 10:04 PM, John Colvin via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 compiler, version, OS, architecture, flags?

Compiler: DMD 2.065 and LDC 0.14
OS: Linux 64bits (8 cores, but there is no parallelism here)
flags: -O -release -inline (and -noboundscheck for DMD)


 Have you looked at the assembly to check that all the Appender method calls
 are being inlined?

I do not know how to look at the assembly, neither do I know how to
see if Appender method calls are being inlined.

I did spend some time with -profile and gained a nice 10% increase in
speed with that, fighting bottlenecks in my code.


Re: Appender is ... slow

2014-08-14 Thread Philippe Sigaud via Digitalmars-d-learn
 I don't know much about Phobos appender implementation details but the key
 thing with reusable buffer is avoid freeing them. AFAIR Appender.clear frees
 the allocated memory but `Appender.length = 0` does not, making it possible
 to just overwrite stuff again and again.

I call .clear() only at the beginning of the computation, to avoid any
strange effects with std.datetime.benchmark (using benchmark with
memoizing functions can lead to strange results if one does not take
care to flush any result between to calls.)
After that initial call to clear, I just append.

The thing is, it's not the first time it happens. For years, I tried
to use Appender to get faster code, to no avail.


btw, I saw your Dconf talk yesterday, nice content! And thanks for
talking about Pegged!
It might interest you to know that the code I'm trying to use Appender
on is a new engine for Pegged, based on GLL parsing, that should be
able to produce a parser for any grammar, even ambiguous ones.


Re: Appender is ... slow

2014-08-14 Thread Philippe Sigaud via Digitalmars-d-learn
 I've never really tried to benchmark it, but it was my understanding that
 the idea behind Appender was to use it to create the array when you do that
 via a lot of appending, and then you use it as a normal array and stop using
 Appender.

That's how I use it, yes.

 It sounds like you're trying to use it as a way to manage reusing
 the array, and I have no idea how it works for that.

There is a misunderstanding there: I'm using clear only to flush the
state at the beginning of the computation. The Appender is a class
field, used by the class methods to calculate. If I do not clear it at
the beginning of the methods, I keep appending new results to old
computations, which is not what I want. But really, calling clear is a
minor point: I'm interested in Appender's effect on *one* (long,
concatenation-intensive) computation.

 I've
 never actually benchmarked it for just creating arrays via appending. I'd
 just assumed that it was faster than just using ~=, because that's what it's
 supposedly for. But maybe I just completely misunderstood what the point of
 Appender was.

I don't know. People here keep telling newcomers to use it, but I'm
not convinced by its results. Maybe I'm seeing worse results because
my arrays are do not have millions of elements and Appender shines for
long arrays?


Re: Appender is ... slow

2014-08-14 Thread Philippe Sigaud via Digitalmars-d-learn
 There is a misunderstanding there: I'm using clear only to flush the
 state at the beginning of the computation. The Appender is a class
 field, used by the class methods to calculate. If I do not clear it at
 the beginning of the methods, I keep appending new results to old
 computations, which is not what I want. But really, calling clear is a
 minor point: I'm interested in Appender's effect on *one* (long,


 This is exactly what I propose to change - set `length` to 0 instead of
 calling `clear`. That way you will keep using same memory chunk simply
 abandoning its old state at the beginning of each computation.

You mean by using the shrinkTo method? (Appender does not have a
length, that's a bit of a bother btw).
I just did, it does not change anything. Too bad.

Heck, my code is simpler to read and use *and* faster by using a
bog-standard D array. I'll keep my array for now :)


Re: Appender is ... slow

2014-08-14 Thread Philippe Sigaud via Digitalmars-d-learn
 Thanks! Repeating what I have mentioned during DConf talk - have you ever
 considered proposing Pegged for Phobos inclusion? It feels like important
 bit of infrastructure to me.

At the time, it was considered (rightfully) far too slow and
memory-hogging. I think having a generic lexer and a standard D parser
in Phobos would already be a great step forward.


Re: Are Delimited strings and HereDoc strings just here to suck ?

2014-08-11 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Aug 11, 2014 at 10:09 PM, H. S. Teoh via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 On Mon, Aug 11, 2014 at 07:47:44PM +, Klaus via Digitalmars-d-learn wrote:
 I mean when writing a D lexer, you necessarly reach the moment when
 you think:

 Oh no! is this feature just here to suck ?


 The crazy variety of ways to write string literals in D, OTOH, *is* a
 bit over the top, as I found out myself when I also tried writing a D
 lexer.  :-P

Out of curiosity, how does a lexer deal with heredocs? It's a sort
of... user-defined token, right?


Re: Are Delimited strings and HereDoc strings just here to suck ?

2014-08-11 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Aug 11, 2014 at 10:58 PM, H. S. Teoh via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 In Flex, one way you can implement heredocs is to have a separate mode
 where the lexer is scanning for the ending string.  So basically you
 have a sub-lexer that treats the heredoc as three tokens, one that
 defines the ending string for the heredoc (which is never returned to
 the caller), one that contains the content of the heredoc, and the
 terminating token (also never returned to the caller).

Ah, a small, specialized sub-lexer. OK, I get it.


DConf 2014 talks slides

2014-08-10 Thread Philippe Sigaud via Digitalmars-d
I'm catching up on some Dconf 2014 videos (great job, guys!) and 
wondering whether the associated slides will be put on the 
website somewhere. There are some where I'd like to ponder the 
code and ideas. It's not easy to do that on a stopped Youtube 
stream :)


I know some links have been provided in the associated threads, 
but did all speakers give their slides to Andrei  co?



Alt question: Ali, what did you use to make your slides? I quite 
like the look of them and of the highlighted code.


(The ability to cram 26 slides in 10 minutes is a nice bonus)


Re: How to easily construct objects with multi-param constructors from lazy ranges?

2014-08-06 Thread Philippe Sigaud via Digitalmars-d-learn
 Yea, but that won't work for forward ranges. It only provides opIndex if the
 underlying range provides it. Since the chunk size is a runtime parameter it
 can't implement opIndex efficiently for non-random access ranges.

But in your case, your range is random-access, no?

Or else, you can always map array on the chunks...


 staticChunks was a bit of a misnomer. staticTake would be a better name. The
 range would contains a static array and pops that number of elements from
 the input range. Then, opIndex can easily be defined.

What about takeExactly?


Re: Help with porting grammar from PEGjs to D for dustjs project!

2014-08-06 Thread Philippe Sigaud via Digitalmars-d-learn
On Wed, Aug 6, 2014 at 9:09 AM, Uranuz via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 What I was thinking about is possibility to change ParseTree struct with
 user-defined version of it. And I was thinking about setting tree type as
 template parameter to grammar:

 grammar!(MyParseTree)(
 Arithmetic:
...
 );



That's already the case, look at

https://github.com/PhilippeSigaud/Pegged/blob/master/pegged/parser.d

on line 134, for example.

struct GenericPegged(TParseTree)
{
...
}

And then, the library alias a standard version (line 1531):

alias GenericPegged!(ParseTree).Pegged Pegged;

Which means the customer-facing Pegged parser is in fact a generic
parser specialized on ParseTree. But you can substitute your own parse
tree.

That's of course the same for all parsers: GenericXXX(TParseTree)
{...} and then alias XXX = GenericXXX!(ParseTree);


But you're right, it's not really documented and I don't have a
template checking whether TParseTree respect some static inferface.
This parameterization was asked by someone on github, but I don't
think they used it finally.

ParseTree is described here:

https://github.com/PhilippeSigaud/Pegged/wiki/Parse-Trees


Maybe we can continue this thread by private mail? I'm not sure people
on the D list are that interested by the internals of a library.


Re: Inner struct accessing host member

2014-08-06 Thread Philippe Sigaud via Digitalmars-d-learn
 hmmm static and private... other keywords to
 try, but offhand it's been a while i don't know if either would change the
 behavior. Could just be inner scope limitations. Might be other
 tags/modifiers...

  I feel helpless :(

No need to ;-) Thanks for your help, don't sweat it too much.

  I'm not sure if it would help, but sometimes if you reverse the logic you
 might get what you want by putting the data in B instead of A.

I have a lot of Bs (nodes in a graph). They compute some things and
when they get a result, they update A's field. Each A holds the entry
point to their inner graph of Bs and waits for the results.
So I don't see how I could invert it, really.

What  *could* do it to have the graph of Bs in thread and sending
results as messages to another thread, where A is waiting for them.

It's just... I'm so used to being able to mix and compose 'concepts'
in D: structs in functions, classes in classes in structs, functions
returning functions returning structs, etc. I'm used to begin able to
organise my code as I see the problem space.
But here, with a struct-in-a-struct, I hit a wall. Not fun, but not
problematic too...


Re: Help with porting grammar from PEGjs to D for dustjs project!

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn
 Is there multiline comments available inside PEGGED template?
 As far as I understand inline comments are set via # sign.

No, no multiline comment. That's based on the original PEG grammar,
which allows only #-comments.


Re: How to easily construct objects with multi-param constructors from lazy ranges?

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn
 Some range which takes an at compile time known number of elements from an
 input range and provides opIndex seems perfect to me, but as far as I know
 there's no such thing in Phobos.

There is chunks:

http://dlang.org/phobos/std_range.html#chunks


Re: static array in templated struct/class

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn
 http://pastebin.com/34sbffSa

Your problem comes from lengthSquared:

public auto lengthSquared = function () = val.reduce!((a,b) = a + b*b);

That's an unusual way to define a method. Any reason why you are using
a pointer to a function as a member? Do you need to be able to
redefine it at runtime?

I guess that in this case, the compiler cannot determine its return
type and/or its size?
I'd use:

public auto lengthSquared () { return val.reduce!((a,b) = a + b*b);}


Inner struct accessing host member

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn

I'd have thought that this would work:

struct A
{
int[] i;
B b;

struct B
{
void foo() { i ~= 1;}
}
}

void main()
{
A a;
a.b.foo();
}

But the compiler tells me 'need this for i of type int[]'.
Is there any way I can gain access on i inside B?


Re: Inner struct accessing host member

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn
On Tue, Aug 5, 2014 at 11:37 PM, Martijn Pot via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 Does this help :
 http://www.digitalmars.com/d/archives/digitalmars/D/learn/Nested_struct_member_has_no_access_to_the_enclosing_class_data_38294.html

Yes, that helps: that explains why it does not wor :).
I changed my code to use classes. It's a bit less handy, but it works.


Re: Inner struct accessing host member

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn
 why it does not wor :).

why it does not *work*, of course. Sigh.


Re: Inner struct accessing host member

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn

On Tuesday, 5 August 2014 at 22:14:23 UTC, abanstadya wrote:

programming Q, either youra newb or not, should rather be 
posted to 'http://forum.dlang.org/group/digitalmars.D.learn'. 
Your post appears on 
'http://forum.dlang.org/group/digitalmars.D' which is more 
related to the lang. design rather to programming Q. Take care 
next time bro.


This *is* D.learn, bro.


Re: Inner struct accessing host member

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn
On Tuesday, 5 August 2014 at 23:47:00 UTC, Artur Skawina via 
Digitalmars-d-learn wrote:



Is there any way I can gain access on i inside B?


Not directly, but as you ask for /any/ way -- yes:

   struct B
   {
 void foo() { outer.i ~= 1; }
 ref A outer() inout @property { return 
*cast(A*)(cast(void*)this-A.b.offsetof); }

   }

Note this will work only as long as you have just one B
instance in A and B is never created or copied outside of A.


OK. I have en entire graph, whose nodes are Bs inside A. So that 
might not be totally appropriate for me. Thanks anyway, I always 
forget about offsetof


Re: Inner struct accessing host member

2014-08-05 Thread Philippe Sigaud via Digitalmars-d-learn

Era:
 broken_b.foo(); //i_a is accessible invisibly because 
overridden or transformed assuming it would be converted or 
copied/moved as appropriate.


 return b; //if a is a local variable then b becomes invalid 
even though it's a struct.

 return i_b; //same as return b
 return broken_b; //same as above two cases.


I see. I didn't know one could create an A.B 'outside'. I saw 
inner types as Voldemort types, but that is true only for inner 
structs in functions.




 Now a current way to make it safe while still leaving it 
structs could be passing a reference to either the outer struct 
or the variable in question. For simplicity it would probably 
be the struct.

(...)
 Or less safe is to use a pointer and assign it when b 
instantiates to point back to A.. But if you pass B around 
without A and A goes out of scope... same problem...


 Maybe i'm over-thinking it.


I already tried to propagate a ref through A's methods, but that 
made a mess: I have lots of methods, which have all to transmit 
this ref, only for *one* of them being able to update it.


Thanks for you explanations :)
I'm now using classes and inner classes. I'm not fond of classes, 
but that's working correctly.


Re: Threadpools, difference between DMD and LDC

2014-08-04 Thread Philippe Sigaud via Digitalmars-d-learn
 Without going into much detail: Threads are heavy, and creating a thread is
 an expensive operation (which is partially why virtually every standard
 library includes a ThreadPool).

 I haven't looked into detail your code, but consider using the TaskPool if
 you just want to schedule some tasks to run amongst a few threads, or
 potentially using Fibers (which are fairly light-weight) instead of Threads.

OK, I get it. Just to be sure, there is no ThreadPool in Phobos or in
core, right?
IIRC, there are fibers somewhere in core, I'll have a look. I also
heard the vibe.d has them.


Re: Threadpools, difference between DMD and LDC

2014-08-04 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Aug 4, 2014 at 2:13 PM, Chris Cain via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 OK, I get it. Just to be sure, there is no ThreadPool in Phobos or in
 core, right?

 There is. It's called taskPool, though:

 http://dlang.org/phobos/std_parallelism.html#.taskPool

Ah, std.parallelism. I stoopidly searched in std.concurrency and core.*
Thanks!


Re: Threadpools, difference between DMD and LDC

2014-08-04 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Aug 4, 2014 at 3:36 PM, Dicebot via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 Most likely those threads either do nothing or are short living so you don't
 get actually 10 000 threads running simultaneously. In general you should
 expect your operating system to start stalling at few thousands of
 concurrent threads competing for context switches and system resources.
 Creating new thread is rather costly operation though you may not spot it in
 synthetic snippets, only under actual load.

 Modern default approach is to have amount of worker threads identical or
 close to amount of CPU cores and handle internal scheduling manually via
 fibers or some similar solution.

That's what I guessed. It's juste that I have task that will generate
other (linked) tasks, in a DAG. I can use a thread pool of 2-8
threads, but that means storing tasks and their relationships (which
is waiting on which, etc). I rather liked the idea of spawning new
threads when I needed them ;)




 If you are totally new to the topic of concurrent services, getting familiar
 with http://en.wikipedia.org/wiki/C10k_problem may be useful :)

I'll have a look. I'm quite new, my only knowledge comes from reading
the concurrency threads here, std.concurrency, std.parallelism and
TDPL :)


Re: Threadpools, difference between DMD and LDC

2014-08-04 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Aug 4, 2014 at 6:21 PM, Dicebot via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 vibe.d additions may help here:

 http://vibed.org/api/vibe.core.core/runTask
 http://vibed.org/api/vibe.core.core/runWorkerTask
 http://vibed.org/api/vibe.core.core/workerThreadCount

 task abstraction allows exactly that - spawning new execution context and
 have it scheduled automatically via underlying fiber/thread pool. However, I
 am not aware of any good tutorials about using those so jump in at your own
 risk.

Has anyone used (the fiber/taks of) vibe.d for something other than
powering websites?


Re: Threadpools, difference between DMD and LDC

2014-08-04 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Aug 4, 2014 at 6:38 PM, Russel Winder via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

 Are these std.concurrent threads or std.parallelism tasks?

 A std.parallelism task is not a thread. Like Erlang or Java Fork/Join
 framework, the program specifies units of work and then there is a
 thread pool underneath that works on tasks as required. So you can have
 zillions of tasks but there will only be a few actual threads working on
 them.

That's it. Many tasks, a few working threads. That's what I'm
converging to. They are not particularly 'concurrent', but they can
depend on one another.

My only gripes with std.parallelism is that I cannot understand
whether it's interesting to use the module if tasks can create other
tasks and depend on them in a deeply interconnected graph. I mean, if
I have to write lots of scaffolding just to manage dependencies
between task, I might as well built it on core.thread and message
passing directly. I'm becoming quite enamored of message passing,
maybe because it's a new shiny toy for me :)

That's for parsing, btw. I'm trying to write a n-core engine for my
Pegged parser generator project.



 Most likely those threads either do nothing or are short living
 so you don't get actually 10 000 threads running simultaneously.

 I suspect it is actually impossible to start this number of kernel
 threads on any current kernel

So, what happens when I do

void doWork() { ... }

Tid[] children;
foreach(_; 0 .. 10_000)
children ~= spawn(doWork);

?

I mean, it compiles and runs happily.
In my current tests, I end the application by sending all thread a
CloseDown message and waiting for an answer from each of them. That
takes about 1s on my machine.

 I have no current data, but it used to be that for a single system it
 was best to have one or two more threads than the number of cores.
 Processor architectures and caching changes so new data is required. I
 am sure someone somewhere has it though.

I can add that, depending on the tasks I'm using, it's sometime better
to use 4, 6, 8 or 10 threads, repeatedly for a given task. I'm using a
Core i7, Linux sees it as an 8-core.
So, well, I'll try and see.


Re: Threadpools, difference between DMD and LDC

2014-08-04 Thread Philippe Sigaud via Digitalmars-d-learn
 https://github.com/D-Programming-Language/phobos/pull/1910

Very interesting discussion, thanks. I'm impressed by the amount of
work you guys do on github.


Threadpools, difference between DMD and LDC

2014-08-03 Thread Philippe Sigaud via Digitalmars-d-learn

I'm trying to grok message passing. That's my very first foray
into this, so I'm probably making every mistake in the book :-)

I wrote a small threadpool test, it's there:

http://dpaste.dzfl.pl/3d3a65a00425

I'm playing with the number of threads and the number of tasks,
and getting a feel about how message passing works. I must say I
quite like it: it's a bit like suddenly being able to safely
return different types from a function.

What I don't get is the difference between DMD (I'm using 2.065)
and LDC (0.14-alpha1).

For DMD, I compile with -O -inline -noboundscheck
For LDC, I use -03 -inline

LDC gives me smaller executables than DMD (also, 3 to 5 times
smaller than 0.13, good job!) but above all else incredibly,
astoundingly faster. I'm used to LDC producing 20-30% faster
programs, but here it's 1000 times faster!

8 threads, 1000 tasks: DMD:  4000 ms, LDC: 3 ms (!)

So my current hypothesis is a) I'm doing something wrong or b)
the tasks are optimized away or something.

Can someone confirm the results and tell me what I'm doing wrong?


Threadpools, difference between DMD and LDC

2014-08-03 Thread Philippe Sigaud via Digitalmars-d-learn
I'm trying to grok message passing. That's my very first foray 
into this, so I'm probably making every mistake in the book :-)


I wrote a small threadpool test, it's there:

http://dpaste.dzfl.pl/3d3a65a00425

I'm playing with the number of threads and the number of tasks, 
and getting a feel about how message passing works. I must say I 
quite like it: it's a bit like suddenly being able to safely 
return different types from a function.


What I don't get is the difference between DMD (I'm using 2.065) 
and LDC (0.14-alpha1).


For DMD, I compile with -O -inline -noboundscheck
For LDC, I use -03 -inline

LDC gives me smaller executables than DMD (also, 3 to 5 times 
smaller than 0.13, good job!) but above all else incredibly, 
astoundingly faster. I'm used to LDC producing 20-30% faster 
programs, but here it's 1000 times faster!


8 threads, 1000 tasks: DMD:  4000 ms, LDC: 3 ms (!)

So my current hypothesis is a) I'm doing something wrong or b) 
the tasks are optimized away or something.


Can someone confirm the results and tell me what I'm doing wrong?



Re: Help with porting grammar from PEGjs to D for dustjs project!

2014-08-03 Thread Philippe Sigaud via Digitalmars-d-learn
Uranuz:
 http://akdubya.github.io/dustjs/

 So I need some help with rewriting grammar from PEGjs into PEGGED.

Is this the grammar?

https://github.com/akdubya/dustjs/blob/master/src/dust.pegjs

If so, then I think I can provide some help. But I don't get what
output you want (see below).

 Also I don't understand in PEGGED (I have not tried to use it yet) how to
 generate some logic from AST. Where should I describe it or should I walk
 around all nodes for somehow and generate code for them.

You can put semantic actions in the grammar (code between curly
brackets). dust.pegjs seems
to have that in their grammar definition also (all these { return
something } blocks)

Or you can walk the parse tree afterwards.

See the Pegged tutorial here:

https://github.com/PhilippeSigaud/Pegged/wiki/Pegged-Tutorial

More particularly:

https://github.com/PhilippeSigaud/Pegged/wiki/Using-the-Parse-Tree

The example explains (I hope) how to use a wiki grammar to parse wiki
text and output LaTeX code.


 Goal of this is to use dust template system as template engine at server
 side.

More concretely, what's the goal? A template as input and... what
should be output? If I understand correctly, dustjs produces
Javascript code. Is that what you want? Or do you want D code?

Also, did you have a look at vide.d and its Diet templates?


Re: Threadpools, difference between DMD and LDC

2014-08-03 Thread Philippe Sigaud via Digitalmars-d-learn
 This is correct – the LLVM optimizer indeed gets rid of the loop completely.

OK,that's clever. But I get this even when put a writeln(some msg)
inside the task. I thought a write couldn't be optimized away that way
and that it's a slow operation?

Anyway, I discovered Thread.wait() in core in the meantime, I'll use
that. I just wanted to have tasks taking a different amount of time
each time.

I have another question: it seems I can spawn hundreds of threads
(Heck, even 10_000 is accepted), even when I have 4-8 cores. Is there:
is there a limit to the number of threads? I tried a threadpool
because in my application I feared having to spawn ~100-200 threads
but if that's not the case, I can drastically simplify my code.
Is spawning a thread a slow operation in general?



Re: Help with porting grammar from PEGjs to D for dustjs project!

2014-08-03 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Aug 4, 2014 at 7:13 AM, Uranuz via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 I am real noob about grammar description languages so I need some
 explanation about it. As far as I understand expressions in curly bracers
 are used to modify syntax tree just in process of parsing instead of
 modifying it after?

Yes, that's it. Or at least that's the way Pegged does it. I'm not
such a specialist myself, I just dabbled in it to write Pegged.
As I understand it, many parsers do not produce a parse tree, they
only 'return' what their embedded action tell them to.

Personally, I have a slight preference to using the parse tree once
it's complete. a) Because that way I have access to all the
information (parent nodes, sibling nodes, even far way) whereas when
doing it with an action means you only have the local, current node
context and b) because it decouples steps that are in my mind
separated anyway: parsing, then producing a value out of the parse
tree. A bit like ranges in D, and Walter and his components
programming speech.


 How I could use PEGGED to map some code to these parsed expressions to
 generate code that will perform operations defined by this grammar? Should I
 walk around all the syntax tree and just append code to some string and mix
 it in then or are there some features for code generation?

You can insert semantic actions inside the grammar definition, as is
done by Dustjs, or you can have a function walking the tree
afterwards.
For D, since Pegged works at compile time, you can have your parse
tree at compile time. Use the walking function to generate D code (a
string) and mix it in.

enum parseTree = Grammar(input); // CT parsing
string codeMaker(ParseTree pt) { ... } // recursive walker

mixin(codeMaker(parseTree));

See https://github.com/PhilippeSigaud/Pegged/wiki/Using-the-Parse-Tree

If what you need is generating Javascript code, no need to do that at
compile-time: you can assemble the JS code as a string at runtime and
then write it to a file somewhere, I guess.

 Something that I was thinking about is comparision of resulting syntax tree
 to check if it was correctly implemented. It would be great if different
 gramar parsers will output result in common format (JSON or XML for example)
 and it will be possiple to compare them for equality. But different parsers
 have different internal format of tree so maybe creating some transformation
 is possible. With this feature it could be possible to say if parser is
 working correctly.

Different formats and also different languages. I don't see how you
can compare a parse tree that's a D object and another tree made by
dustjs: you never see the AST produced by dust, you only see the
resulting JS code.


Re: Type deduction on templated constructor.

2014-07-30 Thread Philippe Sigaud via Digitalmars-d-learn
 I expected such an answer and I do understand the decisions behind it. Yet,
 you gave me a really GOOD news! Having to write cast(ubyte) 1 was way too
 much verbose for my liking, while the new ubyte(1) is reasonable enough.

Why not use `1u`?


Re: Type deduction on templated constructor.

2014-07-30 Thread Philippe Sigaud via Digitalmars-d-learn
On Wed, Jul 30, 2014 at 11:46 AM, Philippe Sigaud
philippe.sig...@gmail.com wrote:
 I expected such an answer and I do understand the decisions behind it. Yet,
 you gave me a really GOOD news! Having to write cast(ubyte) 1 was way too
 much verbose for my liking, while the new ubyte(1) is reasonable enough.

 Why not use `1u`?

Ow! Ignore that. 1u is an uint, not an ubyte.


Re: Compile time regex matching

2014-07-15 Thread Philippe Sigaud via Digitalmars-d-learn
 I did, and I got it to work. Unfortunately, the code used to in the CTFE is
 left in the final executable even though it is not used at runtime. So now
 the question is, is there away to get rid of the excess baggage?

Not that I know of. Once code is injected, it's compiled into the executable.

   auto result = MyRegex(import(config-file.txt)); // compile-time parsing
   return writeln(\~result.matches[0]~\);;


   mixin(get_match());

I never tried that, I'm happy that works.

Another solution would be to push these actions at runtime, by using a
small script instead of your compilation command. This script can be
in D.

- The script takes a file name as input
- Open the file
- Use regex to parse it
- Extract the values you want and write them to a temporary file.
- Invoke the compiler (with std.process) on your main file with -Jpath
flag to the temporary file. Inside your real code, you can thus use
mixin(import(temp file)) happily.
- Delete the temporary file once the previous step is finished.

Compile the script once and for all, it should execute quite rapidly.
It's a unusual pre-processor, in a way.


Re: new properties for basic types

2014-07-14 Thread Philippe Sigaud via Digitalmars-d-learn
Halas, that's not what the OP wants. He needs properties on the *type*
itself: int.foo instead of foo!int.

So no, this is not possible.


Re: Compile time regex matching

2014-07-14 Thread Philippe Sigaud via Digitalmars-d-learn
 I am trying to write some code that uses and matches to regular expressions
 at compile time, but the compiler won't let me because matchFirst and
 matchAll make use of malloc().

 Is there an alternative that I can use that can be run at compile time?

You can try Pegged, a parser generator that works at compile-time
(both the generator and the generated parser).

https://github.com/PhilippeSigaud/Pegged

docs:

https://github.com/PhilippeSigaud/Pegged/wiki/Pegged-Tutorial

It's also on dub:

http://code.dlang.org/packages/pegged

It takes a grammar as input, not a single regular expression, but the
syntax is not too different.


  import pegged.grammar;

  mixin(grammar(`
  MyRegex:
  foo - abc* def?
  `));

  void main()
  {
  enum result = MyRegex(abcabcdefFOOBAR); // compile-time parsing

  // everything can be queried and tested at compile-time, if need be.
  static assert(result.matches == [abc, abc, def]);
  static assert(result.begin == 0);
  static assert(result.end == 9);

  pragma(msg, result.toString()); // parse tree
  }


It probably does not implement all those regex nifty features, but it
has all the usual Parsing Expression Grammars powers. It gives you an
entire parse result, though: matches, children, subchildren, etc. As
you can see, matches are accessible at the top level.

One thing to keep in mind, that comes from the language and not this
library: in the previous code, since 'result' is an enum, it'll be
'pasted' in place everytime it's used in code: all those static
asserts get an entire copy of the parse tree. It's a bit wasteful, but
using 'immutable' directly does not work here, but this is OK:

enum res = MyRegex(abcabcdefFOOBAR); // compile-time parsing
immutable result = res; // to avoid copying the enum value everywhere

The static asserts then works (not the toString, though). Maybe
someone more knowledgeable than me on DMD internals could certify it
indeed avoid re-allocating those parse results.


Re: Compile time regex matching

2014-07-14 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Jul 14, 2014 at 3:19 PM, Artur Skawina via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 On 07/14/14 13:42, Philippe Sigaud via Digitalmars-d-learn wrote:
 asserts get an entire copy of the parse tree. It's a bit wasteful, but
 using 'immutable' directly does not work here, but this is OK:

 enum res = MyRegex(abcabcdefFOOBAR); // compile-time parsing
 immutable result = res; // to avoid copying the enum value everywhere

static immutable result = MyRegex(abcabcdefFOOBAR); // compile-time 
 parsing

Ah, static!



 The static asserts then works (not the toString, though). Maybe
(snip diff)

I'll push that to the repo, thanks! I should sprinkle some const and
pure everywhere...

 [completely untested; just did a git clone and fixed the two
  errors the compiler was whining about. Hmm, did pegged get
  faster? Last time i tried (years ago) it was unusably slow;
  right now, compiling your example, i didn't notice the extra
  multi-second delay that was there then.]

It's still slower than some handcrafted parsers. At some time, I could
get it on par with std.regex (between 1.3 and 1.8 times slower), but
that meant losing some other properties. I have other parsing engines
partially implemented, with either a larger specter of grammars or
better speed (but not both!). I hope the coming holidays will let me
go back to it.


Re: new properties for basic types

2014-07-14 Thread Philippe Sigaud via Digitalmars-d-learn
 Hmm.
 So how do I use stuff like this:

 template defaultInit(T)
 {
 static if (!is(typeof({ T v = void; })))// inout(U)
 @property T defaultInit(T v = T.init);
 else
 @property T defaultInit();
 }

 (this is from std.traits - ok, it's private, but anyway)

It should be invoked as `defaultInit!SomeType`


 Because I have seen nowhere anything like defaultInit!T (or T.defaultInit)
 and don't understand why here the attribute @property is used.
 Why does it make a difference, and how?

@property allows you to call a function without the parenthesis (), to
imitate a field in a struct or class.
In this particular case, I don't know what defaultInit is used for. It
seems to compile to a forward declaration of a function, but I don't
know what for.

I cannot find it on my copy of std.traits. What DMD version are you using?


Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)

2014-07-08 Thread Philippe Sigaud via Digitalmars-d-learn
On Tue, Jul 8, 2014 at 7:50 AM, H. S. Teoh via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote quite a wall of text

Wow, what to add to that? Maybe you scared other from participating ;-)

* I'll second metaprogramming: the alliance between templates, CTFE
and mixins is really nice. It's *the* feature (or triplet of features)
I think of when Walter says that many D parts are kind of what for?
in isolation but really grow into something awesome by using one
another.

* I'd add static introspection to the mix: using static if,
__traits(...) and is(...), clunky as the syntax is (there, one 'ugly'
thing for you), is easy and very powerful: the idea to have code
selecting its flow or extracting information (is that a static array?
Does this aggregate have an '.empty' method?). This is the basis for
std.algorithm idiom of 'static interface' which allows us compile-time
duck typing, which I find very pleasing.

* unittests are nice of course, H. S. Teoh already said it
expressively enough :-)

* I'd add arrays and slice. They are wonderfully simple to use,
efficient, etc. I remember learning D by translating the Euler Project
problems from C++ to D and it was a joy.

Which brings me to another feature I like: ranges. The idea is nothing
new, but I find it quite well-realized in D, far easier than other
compiled languages alternatives and since they are pervasive in the
library, you can really plug components into one another nicely.

For example:
http://wiki.dlang.org/Component_programming_with_ranges#Case_Study:_Formatting_a_Calendar

* dub is good, and you can show code.dlang.org in your presentation.

* Bonus point: different compilers. I like that. I regularly use at
least two in parallel while developping (comparing results, speed,
etc). Kudos to all the guys involved!



As for the bad and ugly:

* it's frustrating not to have a big collection module in Phobos, but
then I didn't propose one, so I'll shut up.
* there are still some not so nice interaction between
const/shared/inout/ auto ref, though I rarely hit them these days
* The compiler still has some quirks: I find it strange you can put
unused qualifiers in many places.

But very honestly, it was already a joy to use a few years ago, and
it's becoming better and better.


Re: dependency graph

2014-07-06 Thread Philippe Sigaud via Digitalmars-d-learn
If you compile your project with the -deps flag, the compiler will
output import dependencies. With -deps=filename, the output will go
into filename.

From there, you'll have to parse and create the graph, though. Maybe
have a look into rdmd source, to see how the dependency extraction is
done there?


Re: What exactly module in D means?

2014-07-06 Thread Philippe Sigaud via Digitalmars-d-learn
On Sat, Jul 5, 2014 at 6:35 PM, Andre Tampubolon via
Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote:
 I've been reading the newsgroup for a while, and it seems that one of the
 reason folks like D is because it supports module.

 My question is: what does module mean?
 A quick google pointed my this page: http://dlang.org/module.html.
 Still cannot understand it, though :)

 How does it differ from the old C's #include?

Well, module are 'more first-class' in D than in C. By this, I mean
that they have an identity: a name, members, symbols. You can see them
as a enormous struct/class. You can use introspection to obtain the
symbols defined in a module, query their types, etc. Heck, in some
cases, module names can even by used as arguments for templates.

As others said, a D module is a unit of encapsulation: inside a
module, functions, structs and classes can freely call one other and
access their internal fields. Outside the module, only what's not
private is visible. Thus, you can create complex, interdependent
structures inside your module, but export only some parts for public
access. This way, you control a module 'interface', its external
frontier.

Importing a module in D means the public symbols defined in the module
become accessible in the importer. There is no need to import all
visible symbols in your current scope: you can restrict your import to
only one or two symbols, rename them, etc. That's much more powerful
than C when it comes to name clashes.

Different 'downstream' modules can import the same 'upstream' module,
and choose to import different symbols. No need to do a big 'import
everything in the current scope'.

symbols names are also defined on a per-module basis: two different
modules can have members with a similar name, without clash: just
prefix the names with the module name to differentiate them (or rename
one while importing).

Also, `import foo;` is a statement, you can put it everywhere a
statement is legit. That's a recent addition (ie, 1-2 year?), that
Andrei likes to call 'Turtles all the way down' and is quickly
becoming a D idiom: import a symbol near its use place: inside a
function, a method, even inside an if branch: that avoid scope
pollution and nicely documents where a symbol is necessary.


Re: How to test templates for equality?

2014-07-06 Thread Philippe Sigaud via Digitalmars-d-learn
Seeing his example, the OP wants a solution that works even for templates:

template Test1(T) {}

pragma(msg, instanceArgsOf!(Test1, Test1!int));

which fails because Test1!int is not a type (std.traits.isInstanceOf
fails also, for the same reason).
And is(symbol == Name!Args, Args...) does not work if Name!Args and
symbol are not types.

In this particular case, the only solution I know of is an awful hack:
using .stringof and __traits(identifier, x) and then parse the
strings:

Name!(int, double[string]) and Name(T, U[V], U, V)

and then the fun begins: in the general case, you must then equate the
arguments lists (recursively).

Philippe


Re: Trying to reproduce Node.js async waterfall pattern.. (Meta-programming)

2014-06-24 Thread Philippe Sigaud via Digitalmars-d-learn
 Yes, the final callback is always called, but if an error is passed to the
 callback by any of the main steps in the sequence ladder, it will
 immediately jump to the final callback and not execute further steps.

OK.


 What do you mean? The compiler does deduce the type of Funcs.


 If you look at where I call Waterfall() in main, you'll see I had to
 manually specify (Callback cb) instead of just (cb); since it didn't know
 that the Funcs... were of type AsyncFunc

you can use std.typetuple.allSatisfy with a helper template:

enum isAsyncFunc(T) = is(T == AsyncFunc);

... (Funcs...)(Funcs funcs) if (allSatisfy!(isAsyncFunc, Funcs))
{ ... }



 (cb) { cb(null, one);} is possible, but that means it's a function
 template, not a function.
 You can get this syntax by making the callbacks template arguments,
 which means they must be known at compile-time. Is that OK with you or
 do you need the possibility to define the callbacks at runtime?


 The goal was to do as much as possible at compile time.  Could you elaborate
 on this a bit.  I guess the answer is, yes, it's okay with me.

I mean, it's possible to get a (cb){ some code } syntax, but as that
define a function template, it has no real type: it cannot be a
runtime argument, only an alias template parameter. That means that
all callbacks must be defined in your code, none can come from user
input or runtime computation.




 I don't get it: none of your callbacks have a return type per se: they
 all return 'void'.
 Do you want callbacks that really return something?


 Yes, the callbacks at step0 should output a type in the result which is
 specific to step0, and then that type should be fed in as a secondary
 parameter to step1.

 I didn't get that far, as I was already stuck.

OK, I get it.



 thanks for your patience!

Well, we are there to explain :-)
I'll have try and code something. If I can get it to work, I'll post it there.


Re: Trying to reproduce Node.js async waterfall pattern.. (Meta-programming)

2014-06-23 Thread Philippe Sigaud via Digitalmars-d-learn
On Mon, Jun 23, 2014 at 9:39 PM, Christian Beaumont via
Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote:

 Each function is given a callback, that when called, steps the waterfall
 forward on to the next function to process.  If an error is passed to the
 callback (instead of null), then the waterfall stops processing and calls
 the final callback at the end of the chain.

Just to be sure: whether or not an error is passed to a callback, the
final callback is always called?
I mean, the last callback could also be called *only when something
fails*, a bit like a default case in a switch, or an error-handling
routine.


 1) I can't see any way to get the compiler to deduce the type of Funcs

What do you mean? The compiler does deduce the type of Funcs.

 I had an urge to somehow specialize the variadic Funcs... but I couldn't
 figure out any syntax to do that.

What do you mean by 'specialize'?

  Well, because of that, I have to
 repeatedly say (Callback cb) instead of (cb).

(cb) { cb(null, one);} is possible, but that means it's a function
template, not a function.
You can get this syntax by making the callbacks template arguments,
which means they must be known at compile-time. Is that OK with you or
do you need the possibility to define the callbacks at runtime?



 2) I can't see a path to flow the output type of the previous callback to
 the input TLastResult for the next... so it's stuck on string :(

I don't get it: none of your callbacks have a return type per se: they
all return 'void'.
Do you want callbacks that really return something?


 3) I had to use a specialization to deal with the head case; (the first
 function doesn't have an input from a previous result). Minor, but niggly.

You can test if func[0] takes one or two arguments:

import std.traits: isCallable, ReturnType;

static if (isCallable!(Func[0])  ReturnType!(Func[0]).length == 1)


Re: What is the correct way to forward method calls to the struct field?

2014-06-22 Thread Philippe Sigaud via Digitalmars-d-learn
On Sun, Jun 22, 2014 at 5:04 PM, monnoroch via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 There is also a problem: when i declare opDispatch to be private,
 i still have access to this forwarding from another package. Is
 it a bug or what?

I don't know. I never used private in conjunction with a template.
Let's hope someone more knowledgeable than me can answer this.


Re: What is the correct way to forward method calls to the struct field?

2014-06-22 Thread Philippe Sigaud via Digitalmars-d-learn
On Sun, Jun 22, 2014 at 5:02 PM, monnoroch via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 Thanks a lot!
 There is a problem though: when i pass incorrect parameters to
 such a method, it says, that S has no such field, which is a
 misleading error message.

You can test the mixin with static if, like this:

struct SomeT {
int foo(double d) { return 0;}
void bar(double d) { return;}
}

struct S {
  auto opDispatch(string name, Args...)(Args args) {
 static if (is(typeof(mixin((*iface). ~ name)(args
   return mixin((*iface). ~ name)(args);
 else
   pragma(msg, S. ~ name ~  cannot be called with arguments of
type  ~ Args.stringof);
}
SomeT** iface;
}

void main()
{
  SomeT st;
  SomeT* st_p = st;
  SomeT** st_p_p = st_p;
  S s = S(st_p_p);

  s.foo(3.14);
  s.foo(abc);
  s.bar(abc, 3.14);
}


Re: template mixins for boilerplate

2014-06-21 Thread Philippe Sigaud via Digitalmars-d-learn
Out of curiosity, why use a mixin template containing a string mixin
instead of, well, directly injecting a string mixin in your struct,
with a function?


Re: template mixins for boilerplate

2014-06-21 Thread Philippe Sigaud via Digitalmars-d-learn
On Sat, Jun 21, 2014 at 4:24 PM, Dicebot via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:
 On Saturday, 21 June 2014 at 13:45:14 UTC, Philippe Sigaud via
 Digitalmars-d-learn wrote:

 Out of curiosity, why use a mixin template containing a string mixin
 instead of, well, directly injecting a string mixin in your struct,
 with a function?


 Hiding non-hygienic implementation behind a more reliable interface.

In what way is a template more reliable than the equivalent function?
That's an honest question: I'm just looking at the code a few posts
upward:

mixin template Function(string name) {
mixin(public static int  ~ name ~ () { return other.module. ~
name ~; });
}

struct S {
  mixin Function!fctn1;
}

And this double-mixin construction seems needlessly complicated to me,
compared to:

string Function(string name) {
  return public static int  ~ name ~ () { return other.module.
~ name ~; };
}

struct S {
mixin(Function(fctn1));
}


  1   2   3   4   5   6   7   8   9   10   >