State of OpenGL bindings

2013-11-03 Thread Guilherme Vieira
Hi, all.

If I wanted to create an OpenGL project in D, what would be supported by
current bindings? Are the bindings out-of-date compared to the C library
versions or are they the same?

Thank you.


-- 
Atenciosamente / Sincerely,
Guilherme Prá Vieira

http://www.linkedin.com/in/n2liquid
http://www.linkedin.com/in/n2liquid
 http://www.linkedin.com/in/n2liquid


Re: Thin delegate adapter

2011-01-14 Thread Guilherme Vieira
On Thu, Jan 13, 2011 at 5:30 AM, Dmitry Olshansky dmitry.o...@gmail.comwrote:

 On 13.01.2011 2:16, Guilherme Vieira wrote:

 No sh*t..?! @__@ That's so cool! But is it smart enough to know the stack
 frame doesn't need to go to heap in this case? (since it returns a heap
 object referecing another heap object, i.e. can it untangle `b' from the
 stack?)


 Ehm, it can optimize certain cases but for the moment it doesn't.
 Still, it needs to store b somewhere, right? and delegate is 2 pointers in
 fact, so b should go on heap anyway. So it narrows down to if it can save
 only parts of the stack frame ...


Since it only uses something the size of a pointer (`b'), it might as well
do some trickery and use `b' as `this' and turn the delegate into (Switch.State
state) { this.toggled = cast(bool)(state); } (or something of similar
effect).

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Thin delegate adapter

2011-01-12 Thread Guilherme Vieira
Hi,

I'm wondering if a delegate adapter template like isn't handy for Phobos (it
may be especially useful for std.signal):

class Switch
{
enum State { ON, OFF }

void trigger()
{
switch (mState)
{
case State.ON: mState = State.OFF; break;
case State.OFF: mState = State.ON; break;
default: break;
}

if (watch !is null) watch(mState);
}

void delegate(State s) watch;

private State mState;
}

class ToggleButton
{
@property toggled(bool toggled)
{
writeln(ToggleButton.toggled(, toggled, ));
}
}

void main()
{
scope s = new Switch();
scope b = new ToggleButton();

s.watch = b.toggled; // error: invalid conversion
s.watch = adapt!(obj.toggled = cast(bool)(a), Switch.State)(b);

s.trigger(); // prints `ToggleButton.toggled(true)`
s.trigger(); // prints `ToggleButton.toggled(false)`
s.trigger(); // prints `ToggleButton.toggled(true)`
s.trigger(); // prints `ToggleButton.toggled(false)`
}


Yes, it urges to be polished. Particularly, it doesn't support multiple
arguments. I also wanted to place the argument type tuple somwhere else
(actually wanted to hide it completely, but I think that's not possible).

Feedback?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: Thin delegate adapter

2011-01-12 Thread Guilherme Vieira
On Wed, Jan 12, 2011 at 10:41 AM, Guilherme Vieira n2.nitro...@gmail.comwrote:

 Hi,

 I'm wondering if a delegate adapter template like isn't handy for Phobos
 (it may be especially useful for std.signal):

 class Switch
 {
 enum State { ON, OFF }

 void trigger()
 {
 switch (mState)
 {
 case State.ON: mState = State.OFF; break;
 case State.OFF: mState = State.ON; break;
 default: break;
 }

 if (watch !is null) watch(mState);
 }

 void delegate(State s) watch;

 private State mState;
 }

 class ToggleButton
 {
 @property toggled(bool toggled)
 {
 writeln(ToggleButton.toggled(, toggled, ));
 }
 }

 void main()
 {
 scope s = new Switch();
 scope b = new ToggleButton();

 s.watch = b.toggled; // error: invalid conversion
 s.watch = adapt!(obj.toggled = cast(bool)(a), Switch.State)(b);

 s.trigger(); // prints `ToggleButton.toggled(true)`
 s.trigger(); // prints `ToggleButton.toggled(false)`
 s.trigger(); // prints `ToggleButton.toggled(true)`
 s.trigger(); // prints `ToggleButton.toggled(false)`
 }


 Yes, it urges to be polished. Particularly, it doesn't support multiple
 arguments. I also wanted to place the argument type tuple somwhere else
 (actually wanted to hide it completely, but I think that's not possible).

 Feedback?

 --
 Atenciosamente / Sincerely,
 Guilherme (n2liquid) Vieira


Oops, missed the template itself:

template adapt(alias fun, Arg)
{
auto adapt(Object)(Object obj)
{
auto adaptImpl = new AdaptImpl!(fun, Object)(obj);
return adaptImpl.opCall!(Arg);
}
}

class AdaptImpl(alias fun, Object)
{
this(Object obj) { this.obj = obj; }
auto opCall(Arg)(Arg a) { return binaryFun!(fun, a, obj)(a, obj); }

private Object obj;
}


-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: Thin delegate adapter

2011-01-12 Thread Guilherme Vieira
Ah, I totally missed that. But what if `s' went out of the scope and the
scope ended? Wouldn't the scope reference (the one containing `b') be lost
and cause memory corruption?

E.g.:

Switch make_switch()
{
auto s = new Switch();
auto b = new ToggleButton();

s.watch = (Switch.State state) { b.toggled = cast(bool)(state); };


return s;
}


-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira

On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky dmitry.o...@gmail.comwrote:

 On 12.01.2011 15:41, Guilherme Vieira wrote:

 Hi,

 I'm wondering if a delegate adapter template like isn't handy for Phobos
 (it may be especially useful for std.signal):

class Switch
{
enum State { ON, OFF }

void trigger()
{
switch (mState)
{
case State.ON: mState = State..OFF; break;
case State.OFF: mState = State.ON; break;
default: break;
}

if (watch !is null) watch(mState);
}

void delegate(State s) watch;

private State mState;
}

class ToggleButton
{
@property toggled(bool toggled)
{
writeln(ToggleButton.toggled(, toggled, ));
}
}

void main()
{
scope s = new Switch();
scope b = new ToggleButton();

s.watch = b.toggled; // error: invalid conversion
s.watch = adapt!(obj.toggled = cast(bool)(a), Switch.State)(b);

s.trigger(); // prints `ToggleButton.toggled(true)`
s.trigger(); // prints `ToggleButton.toggled(false)`
s.trigger(); // prints `ToggleButton.toggled(true)`
s.trigger(); // prints `ToggleButton.toggled(false)`
}


 Yes, it urges to be polished. Particularly, it doesn't support multiple
 arguments. I also wanted to place the argument type tuple somwhere else
 (actually wanted to hide it completely, but I think that's not possible).

 Feedback?

 --
 Atenciosamente / Sincerely,
 Guilherme (n2liquid) Vieira

 How is it better then built-in language feature? This works just fine:
void main()
{
 //they can't be scope  and compiler enforces this (+ scope is deprecated)
 //actually, the orignal code is unsafe - what hapens if adapted delegate
 escapes current scope?
auto s = new Switch();
auto b = new ToggleButton();


s.watch = (Switch.State a){ b.toggled = cast(bool)a; };

s.trigger(); // prints `ToggleButton.toggled(true)`
s.trigger(); // prints `ToggleButton.toggled(false)`
s.trigger(); // prints `ToggleButton.toggled(true)`
s.trigger(); // prints `ToggleButton.toggled(false)`
}

 --
 Dmitry Olshansky




Re: Thin delegate adapter

2011-01-12 Thread Guilherme Vieira
No sh*t..?! @__@ That's so cool! But is it smart enough to know the stack
frame doesn't need to go to heap in this case? (since it returns a heap
object referecing another heap object, i.e. can it untangle `b' from the
stack?)

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


On Wed, Jan 12, 2011 at 11:49 AM, Dmitry Olshansky dmitry.o...@gmail.comwrote:

 On 12.01.2011 16:07, Guilherme Vieira wrote:

 Ah, I totally missed that. But what if `s' went out of the scope and the
 scope ended? Wouldn't the scope reference (the one containing `b') be lost
 and cause memory corruption?

 E.g.:

Switch make_switch()
{
auto s = new Switch();
auto b = new ToggleButton();

s.watch = (Switch.State state) { b.toggled = cast(bool)(state); };


return s;
}


  That's the main point of built-in delegates - the compiler detects them
 and places the enclosing stack frame on heap, so it's all sort of cool magic
 that just works :)

 --
 Atenciosamente / Sincerely,
 Guilherme (n2liquid) Vieira

 On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky 
 dmitry.o...@gmail.commailto:
 dmitry.o...@gmail.com wrote:

On 12.01.2011 15:41, Guilherme Vieira wrote:

Hi,

I'm wondering if a delegate adapter template like isn't handy
for Phobos (it may be especially useful for std.signal):

   class Switch
   {
   enum State { ON, OFF }

   void trigger()
   {
   switch (mState)
   {
   case State.ON: mState = State..OFF; break;
   case State.OFF: mState = State.ON; break;
   default: break;
   }

   if (watch !is null) watch(mState);
   }

   void delegate(State s) watch;

   private State mState;
   }

   class ToggleButton
   {
   @property toggled(bool toggled)
   {
   writeln(ToggleButton.toggled(, toggled, ));
   }
   }

   void main()
   {
   scope s = new Switch();
   scope b = new ToggleButton();

   s.watch = b.toggled; // error: invalid conversion
   s.watch = adapt!(obj.toggled = cast(bool)(a),
Switch.State)(b);

   s.trigger(); // prints `ToggleButton.toggled(true)`
   s.trigger(); // prints `ToggleButton.toggled(false)`
   s.trigger(); // prints `ToggleButton.toggled(true)`
   s.trigger(); // prints `ToggleButton.toggled(false)`
   }


Yes, it urges to be polished. Particularly, it doesn't support
multiple arguments. I also wanted to place the argument type
tuple somwhere else (actually wanted to hide it completely,
but I think that's not possible).

Feedback?

-- Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira

How is it better then built-in language feature? This works just fine:
   void main()
   {
//they can't be scope  and compiler enforces this (+ scope is
deprecated)
//actually, the orignal code is unsafe - what hapens if adapted
delegate escapes current scope?
   auto s = new Switch();
   auto b = new ToggleButton();


   s.watch = (Switch.State a){ b.toggled = cast(bool)a; };

   s.trigger(); // prints `ToggleButton.toggled(true)`
   s.trigger(); // prints `ToggleButton.toggled(false)`
   s.trigger(); // prints `ToggleButton.toggled(true)`
   s.trigger(); // prints `ToggleButton.toggled(false)`
   }

-- Dmitry Olshansky



 --
 Dmitry Olshansky




Struct constructors callable twice?

2011-01-12 Thread Guilherme Vieira
I've found this behavior while toying with opCall() in a struct:

import std.stdio;
struct Struct
{
this(int value) { writeln(Struct.this(, value, )); }
~this() { writeln(Struct.~this()); }
}
void main()
{
Struct s = Struct(1); // prints `Struct.this(1)`
s(2); // prints `Struct.this(2)`

s(3); // prints `Struct.this(3)`

} // prints `Struct.~this()`


Notice how the destructor is only called once. If there was an opCall
defined for Struct, its reconstruction would shadow it. It certainly looks
like a bug to me, but since I'm sure of nothing in D I decided to post it
here. Is it really a bug?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: Struct constructors callable twice?

2011-01-12 Thread Guilherme Vieira
Yes, it was meddling with that bug that I cooked this one.

I think Adam got it right: There should be no problem between an instance
opCall and a constructor. In your case, it seems, a static opCall was
clashing with the constructor. But it turns out a non-static opCall clashes
with a constructor that AFAIK shouldn't even be there (see my initial post).

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


On Wed, Jan 12, 2011 at 10:12 AM, bearophile bearophileh...@lycos.comwrote:

 See also:
 http://d.puremagic.com/issues/show_bug.cgi?id=4053

 Bye,
 bearophile


Re: How to convert Map to array?

2011-01-10 Thread Guilherme Vieira
It's easier to help if you provide sample code that produces the message. I
got that message today and fixed it, I just don't what was the problem.

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


On Mon, Jan 10, 2011 at 1:25 AM, Sean Eskapp eatingstap...@gmail.comwrote:

 I'm trying to use the array() function in std.array to convert a
 transformed
 array using map (std.algorithm) back to a dynamic array, from a Map. I keep
 getting a cryptic error object.except...@c:\Program Files
 (x86)\D\dmd2\windows\bin\..\..\src\phobos\std\
 algorithm.d(426): Cannot reduce an empty range w/o an explicit seed
 value..
 Am I misunderstanding how this is supposed to work?


Named tuple from struct

2011-01-08 Thread Guilherme Vieira
Is is possible to get a named tuple from a struct type?

E.g.:

struct S { int foo; string bar; }

S s;

S.tupleof t; // S.tupleof is a tuple type, as opposed to s.tupleof,
 // which yields a tuple instance

t[0] = 1;
t.bar = 2;


If not, I think it would be quite useful.

Even still, a way to describe tuple types as if it was a struct would also
be useful:

tuple StructLike
{
int foo;
string bar;
}

StructLike t;

t[0] = 1;
t.bar = 2;


-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: Patterns of Bugs

2011-01-06 Thread Guilherme Vieira
On Thu, Jan 6, 2011 at 6:25 PM, Robert Clipsham
rob...@octarineparrot.comwrote:

 On 06/01/11 19:38, Walter Bright wrote:

 http://www.drdobbs.com/blog/archives/2011/01/patterns_of_bug.html

 (dedicated to bearophile!)

 Anyone want to post it on reddit?


 It's too bad there doesn't seem to be an online repository of them. They
 would make for great research material for programming language designers.
 Every one you can design out of existence will incrementally improve the
 productivity of programmers.

 Perhaps someone here would like to volunteer for this? I guess some kind of
 moderated bugzilla would do the trick, it'd be awesome to have some table of
 languages and how many of the types bugs they prevent/kind of prevent as
 well.

 If no one else volunteers I guess I could hack something crude together, it
 would still need people to volunteer bugs for it, as well as sources/proof
 for each bug (links to changesets/projects that have encountered this issue
 etc).

 --
 Robert
 http://octarineparrot.com/


I loved the idea, but I personally dislike Bugzilla and I wonder if it would
work for something like that. Anyway a voting system would be mandatory.

In any case, isn't there something like this already?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: Is this a viable effort? The DRY principle, community-wide

2011-01-04 Thread Guilherme Vieira
On Tue, Jan 4, 2011 at 11:13 AM, spir denis.s...@gmail.com wrote:

 On Tue, 4 Jan 2011 02:30:24 -0200
 Guilherme Vieira n2.nitro...@gmail.com wrote:

  At times like this I wish people would really break their code in smaller
  parts in a way you could really just pick what you want from it.

 I guess this is a dream generations of programmers, language designers and
 computer scientist have run after. Say, Lego programming. Bulding bricks
 which are _really_ autonomous.
 Maybe there is a flaw in the implicite reasoning behind that vision: as a
 client, one wants the (library) building blocks they use to be autonomous,
 right; but at a higher-level the software one is designing is precisely
 using other software, thus creating a system of dependancies... which makes
 this new piece of code unusable in an autonomous manner by yet another
 client who would enjoy reusing it as a brick. The same applies to the
 (library) bricks: they have to use other building blocks which prevent them
 to be autonomous.

 This is how I see the point. And it gets even more unavoidable because of
 generality. For a brick to have any chance to meet one client's needs it
 must be as general/abstract as possible. This means for instance abstract
 away issues of OS idiosyncrasies, actual types, sizes and loads of other
 annoying aspects, think at how write*, map, or file opening work. To do
 this, using yet another bunch of tools is often necessary. The more a brick
 gets general and thus useful, the more chances it has _not_ to be
 autonomous. I guess.
 This, to the point that if Phobos (2) would be rewritten from scratch using
 everywhere D2's newer style (more general/abstract, as I see it), most of
 its modules would import a load of other modules such as algorithm,
 contracts, functional, range, possibly type*, traits, variant; which
 themselves import...

 I don't logically there can be a solution. I would like to try to define a
 minimal subset D lib functionality, say the standard toolkit. (I have one
 for my personal, a dozen elements systematically imported, and most commonly
 actually used, in every of my modules.) Then, make this a kind of
 auto-import (à la python) for user code, except if other wise stated; and
 see if it's enough, overkill, whatever.
 Then, struggle to make (other) lib modules depend on these toolkit
 elements, and only and them, as much as possible. (Even when it's not the
 best design/code solution.) Could such an approach work?


 Denis
 -- -- -- -- -- -- --
 vit esse estrany ☣

 spir.wikidot.com


Yes, I don't see how could each module not depend on each other, but that's
not the point. It would be a hierarchy, after all; there would have to be
dependencies. But I don't particularly care if a C++ library depends on
Boost, for example. Boost is behemoth, but it is well-modularized (you can
really pick just a pretty small subset of it) and, more importantly, it's so
widely accepted it's almost a standard library. So who cares?

On Tue, Jan 4, 2011 at 9:06 AM, Dmitry Olshansky dmitry.o...@gmail.comwrote:

 Sounds a lot like std lib. Maybe an incubator project for Phobos?
 (was discussed sometime ago) Also check scrapple on Dsource.


I don't think it could get into Phobos. I think of relatively bigger things,
too, such as cross-platform mouse, keyboard and gamepad input library done
right to be the definitive way of doing that on D. That just doesn't seem
fit for a true standard library, does it?

 For example, what do you do if you want to create a window just for
  use with OpenGL in a cross-platform way? You have to write different
  versions of the window creation procedure for the different systems
  you're targeting. Or you could use SDL, but if you really just want
  the window that's a waste. Right?


 For that particular case GLUT may fit just fine. Or GLAux.


I see GLUT solves the problem for OpenGL, but then we get to the granularity
point: the input library I told you above also needs a window. To make it
depend on GLUT would be stupid. And then we get back to the wheel
reinvention problem.

The only problem with it : people still can't invent the best way to do
 something, plus the matter of taste.


The best way of doing something is always a subjective matter. But, as
usual, one can define rules that, when fully respected, result in something
that can be tagged at least as pretty good. Make those rules
community-reviewed and you normalize people's needs. I'm pretty sure much of
D was decided this way.

Also, if you are really thorough in deciding how to break the pieces of the
system, then maybe people won't be too bothered if it's a bit off their
tastes.

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Is this a viable effort? The DRY principle, community-wide

2011-01-03 Thread Guilherme Vieira
I may sound daring or even foolish proposing this, but here goes nothing..
one of the things that bothers me about software development is that people
always tell you not to reinvent the wheel, but the libraries available are
generally not fine-grained enough, so you end up either using overkill
solutions to ridiculously small problems or actually reinventing the wheel.

For example, what do you do if you want to create a window just for use with
OpenGL in a cross-platform way? You have to write different versions of the
window creation procedure for the different systems you're targeting. Or you
could use SDL, but if you really just want the window that's a waste. Right?

At times like this I wish people would really break their code in smaller
parts in a way you could really just pick what you want from it.

So I thought, since D has such a compact community and the codebase is still
small, maybe you would like to attack the problem (dunno if many will
agree with me this is a problem, but then I'd like to know what they do in
the case I described) together.

I'd like to propose a community-written, community-reviewed hierarchy of
modules anybody could (and should :)) contribute to. Necessities would be
factored and layered before entering the actual hierarchy, though.

For example, right now I really wanted a cross-platform way of using OpenGL.
AFAIK, OpenGL usage is normalized across many systems and only its
initialization is platform-depedent (to begin with, there's WGL, GLX and
AGL; plus, you have very different ways of creating windows in those
systems, so you need to do a lot of work to really use OpenGL in a
cross-platform manner).

I would then engage into writing what's needed and, when done, I would send
it for the community to review. The modules would be fragmented, trying not
to compromise its usability in any possible use-case.

The core notion here is that D libraries could be the community's, not the
author's. I wonder if merging people's efforts can be a good idea. I mean,
you would avoid reinventing the wheel, you would avoid having many libraries
doing the same thing with different interfaces, essentially making two
user-libraries, each using one of the first ones, incompatible when in a
perfect world they really shouldn't be, etc.

So, what do you think?

   - Is it viable?
   - Would it be useful?
   - Improvements?


-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: memoize

2011-01-03 Thread Guilherme Vieira
On Tue, Jan 4, 2011 at 2:50 AM, Nick Sabalausky a...@a.a wrote:

 Andrei Alexandrescu seewebsiteforem...@erdani.org wrote in message
 news:ifu70u$2dv...@digitalmars.com...
 I just added a higher-order function memoize to std.functional which I
 think is pretty cool. See the docs here:
 
 
 http://d-programming-language.org/cutting-edge/phobos/std_functional.html#memoize
 
  I'm also thinking of adding that cutting-edge directory as a place for
  storing documentation for commits that are in flux but not officially
  released yet.
 
 
  Andrei

 Neat! This is a great example of why D kicks so much ass :)


Uh, yes. It looks like the kind of thing I would do, show to others and hear
they say Meh.. Whatever. I'm really exponentially developing a liking to
the D community, even though I didn't event get to code anything serious
yet.

This simply rocks. Keep it up, Andrei!

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: A (un)stable idea?

2011-01-03 Thread Guilherme Vieira
On Tue, Jan 4, 2011 at 3:07 AM, Heywood Floyd soul...@gmail.com wrote:



 Hi D!


 I'm quite new to D (been here for maybe half a year?) and I'm not sure if
 what I'm about to say is called for, so please forgive me if I'm crossing
 some line here. I just had a thought and I wanted to share it:


 I've noticed, during my time here, that D seems to suffer from quite a lot
 of frustration. This frustration in turn seems to stem from periodical
 annoying bugs and regressions etc. There are stories of dedicated developers
 abandoning the ship and things like that. I'm not really in a position to
 say if this is normal or not, but I think at least it's fair to say a lot of
 poeple are frustrated with D(?).

 At the same time, what's interesting is that these kinds of bugs can hardly
 be unique to D -- in fact, it would be really weird if these kinds of issues
 was not present in D! (I think so, at least.) Software is complex, and we
 all know bugs are part of the normal course of things. I'd go so far to say
 bugs are a natural part of software.

 So why all the frustration?

 This lead me to a thought: maybe, just maybe, one thing that causes so much
 frustration, is the fact that D doesn't really seem to have any testing /
 stable branches. Seems to me, and please correct me if I'm wrong, changes
 made to the trunk are released about once every month? And that's it. That's
 the latest version of D.

 This is very agressive. Isn't it? Seems to me, many people hold off the
 latest version of D, because it's so agressive.

 I think most non-trivial software projects keep one branch that is the
 sand box-branch where new features are tried out, and one branch where
 special care is taken to keep it stable. Now, this setup doesn't mean that
 the software will be bug free. The _key_ here is, that once you label a
 piece of software as testing or experimental, bugs are ok! In fact, bugs
 are to be expected! No one can complain! (And if they do, you say hey,
 chillax dude, it's experimental!)

 Also, most developers will be in different phases in their projects -- some
 are building on some project that is years old and the last thing they want
 is some new experimental feauture. Others are just playing around and don't
 mind getting all the latest bells and whistles. Testing/stable solves all
 that, while still allowing the software to evolve.

 Then of course, you have to actually keep the stable branch stable. I
 realize that simply dividing D(2) into two branches wouldn't achieve that.
 So I don't know. I guess this is more an idea for future version of D?

 That's it. I'm not quite going to finish my reasoning, because, yeah I
 don't know. Maybe this has been up before? Sorry in that case. I just wanted
 to give this idea some air: How about maybe having a testing/stable branch
 for D at some point in the future? I for one would like that, anyhow.


 (Fun thought experiment: Imagine Debian Linux abandoning their testing
 branch and just making all changes to trunk. Imagine _that_ mailing list.
 You can feel the frustration, can't you? :)


 Kind Regards
 /HF


 PS. I've too experienced some frustrating bugs with D, but it's still the
 only compiled language I can stand! *bow*


Shouldn't TDPL have set the safe subset of the language to use? Maybe it
only happens much when you cross that line?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: memoize

2011-01-03 Thread Guilherme Vieira
On Tue, Jan 4, 2011 at 4:05 AM, Andrew Wiley debio...@gmail.com wrote:



 On Mon, Jan 3, 2011 at 10:15 PM, Andrei Alexandrescu 
 seewebsiteforem...@erdani.org wrote:

 I just added a higher-order function memoize to std.functional which I
 think is pretty cool. See the docs here:


 http://d-programming-language.org/cutting-edge/phobos/std_functional.html#memoize

 I'm also thinking of adding that cutting-edge directory as a place for
 storing documentation for commits that are in flux but not officially
 released yet.


 Pretty sweet, but if I'm understanding this correctly, the memoized version
 of a pure function isn't pure, is it? Is there any way to get that to
 happen?


memoize uses a static variable. Are static variables considered global as
far as pure functions are concerned? If not, then I see no reason for it not
to be pure, or am I missing something?

Additionally, I don't understand this:

Technically the memoized function should be pure because memoize assumes it
 will always return the same result for a given tuple of arguments. However,
 memoize does not enforce that because sometimes it is useful to memoize an
 impure function, too.


Wouldn't memoizing an impure function be a.. bug? It would return the same
cached value when in fact it should have returned something else based on
external factors. When can that be desirable?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: memoize

2011-01-03 Thread Guilherme Vieira
On Tue, Jan 4, 2011 at 3:27 AM, Andrei Alexandrescu 
seewebsiteforem...@erdani.org wrote:

 On 1/3/11 11:01 PM, Guilherme Vieira wrote:

 On Tue, Jan 4, 2011 at 2:50 AM, Nick Sabalausky a...@a.a wrote:

Andrei Alexandrescu seewebsiteforem...@erdani.org
mailto:seewebsiteforem...@erdani.org wrote in message

news:ifu70u$2dv...@digitalmars.com...
 I just added a higher-order function memoize to std.functional which
 I
 think is pretty cool. See the docs here:
 
 

 http://d-programming-language.org/cutting-edge/phobos/std_functional.html#memoize
 
  I'm also thinking of adding that cutting-edge directory as a
place for
  storing documentation for commits that are in flux but not
 officially
  released yet.
 
 
  Andrei

Neat! This is a great example of why D kicks so much ass :)


 Uh, yes. It looks like the kind of thing I would do, show to others and
 hear they say Meh.. Whatever. I'm really exponentially developing a
 liking to the D community, even though I didn't event get to code
 anything serious yet.

 This simply rocks. Keep it up, Andrei!

 --
 Atenciosamente / Sincerely,
 Guilherme (n2liquid) Vieira


 Glad you folks like it. There's a little story behind this. I first read
 Dominus' book chapter years ago, around the time I'd decided to write TDPL.
 Back then I was thinking - it would just be so cool to be able to define
 generic memoization in D. I tried my hand at an implementation. But D had no
 tuples, no aliasing for functions, no good variadics, and even if you could
 find a way to pack parameters, associative arrays had plenty of related
 issues.

 I'd given up on that and forgot most about it, until today. It was nice to
 reckon that getting it done took about a dozen lines and about as many
 minutes. We really have come a very long way.

 Nevertheless, I found two issues: one, ParameterTypeTuple doesn't work for
 overloaded functions, and associative arrays don't work for ubyte[4] keys...
 still a ways to go.


 Andrei


Is there really need for ParameterTypeTuple? I figured this works:

template memoize(alias fun, uint maxSize = uint.max)

{

auto memoize(Args...)(Args args)

{

static typeof(fn(args))[Tuple!(typeof(args))] memo;

auto t = tuple(args);

auto p = t in memo;

if (p) return *p;

static if (maxSize != uint.max)

{

if (memo.length = maxSize) memo = null;

}

auto r = fun(args);

//writeln(Inserting result , typeof(r).stringof, (, r, ) for
 parameters , t);

memo[t] = r;

return r;

}

}


-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: memoize

2011-01-03 Thread Guilherme Vieira
On Tue, Jan 4, 2011 at 4:48 AM, Jonathan M Davis jmdavisp...@gmx.comwrote:

 On Monday 03 January 2011 22:17:52 Guilherme Vieira wrote:
  On Tue, Jan 4, 2011 at 4:05 AM, Andrew Wiley debio...@gmail.com wrote:
   On Mon, Jan 3, 2011 at 10:15 PM, Andrei Alexandrescu 
  
   seewebsiteforem...@erdani.org wrote:
   I just added a higher-order function memoize to std.functional which I
   think is pretty cool. See the docs here:
  
  
  
 http://d-programming-language.org/cutting-edge/phobos/std_functional.htm
   l#memoize
  
   I'm also thinking of adding that cutting-edge directory as a place for
   storing documentation for commits that are in flux but not officially
   released yet.
  
   Pretty sweet, but if I'm understanding this correctly, the memoized
   version of a pure function isn't pure, is it? Is there any way to get
   that to happen?
 
  memoize uses a static variable. Are static variables considered global
 as
  far as pure functions are concerned? If not, then I see no reason for it
  not to be pure, or am I missing something?

 pure functions cannot access mutable globals or static variables. If they
 could,
 they could end up returning a different result with the same parameters
 because
 the global or static variable changed.

  Additionally, I don't understand this:
 
  Technically the memoized function should be pure because memoize assumes
  it
 
   will always return the same result for a given tuple of arguments.
   However, memoize does not enforce that because sometimes it is useful
 to
   memoize an impure function, too.
 
  Wouldn't memoizing an impure function be a.. bug? It would return the
 same
  cached value when in fact it should have returned something else based on
  external factors. When can that be desirable?

 It's quite easy to have a function which you cannot actually make pure but
 which
 you know to be logically pure. For instance, if a function called a C
 function,
 it can't be pure unless you play some games with function pointers and
 casting
 and the like. So, really, any function which calls a C function can't be
 pure.
 However, it's pretty easy to have a C function which is logically pure. So,
 your
 D function is then logically pure, but it's not actually pure, so pure
 functions
 can't call it. But it would work just fine with memoize. Sure, it's
 definitely
 less safe to use impure functions with memoize, and it could cause bugs,
 but
 that doesn't mean that it shouldn't necessarily be disallowed. It just
 means
 that if the programmer wants to use memoize, they're going to have to be
 aware
 that it could cause bugs if the function in question should actually be
 returning a different value on future callls.

 - Jonathan M Davis


Ah, I was under the impression that @trusted was used to force purity.
Shame.. Sorry I mixed things up.

In any case, aren't those rules a bit too rigid? No matter how you look at
memoize, it should generate pure functions (since it exhibits pure nature,
are logically pure or whatever you call it). Would it be tough on the
compiler for it to actually find if a function is pure or not by a more
detailed analysis of its behavior?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: memoize

2011-01-03 Thread Guilherme Vieira
On Tue, Jan 4, 2011 at 5:28 AM, Jonathan M Davis jmdavisp...@gmx.comwrote:

 On Monday 03 January 2011 22:59:37 Guilherme Vieira wrote:
  Ah, I was under the impression that @trusted was used to force purity.
  Shame.. Sorry I mixed things up.
 
  In any case, aren't those rules a bit too rigid? No matter how you look
 at
  memoize, it should generate pure functions (since it exhibits pure
 nature,
  are logically pure or whatever you call it). Would it be tough on the
  compiler for it to actually find if a function is pure or not by a more
  detailed analysis of its behavior?

 @safe, @trusted, and @system have nothing to do with purity. If a function
 is
 marked as pure, then it's pure. If it's not, then it's not. End of story.
 Now,
 the concept of weakly pure functions was recently added, but all pure
 functions are still marked with pure. Strongly pure functions are pure
 functions
 where all of the parameters are immutable or implicitly convertible to
 immutable
 (so, immutable variables and value types). Weakly pure functions are pure
 functions whose parameters are not all immutable or implicitly convertible
 to
 immutable. Unlike strongly pure functions, they can alter their arguments.
 However, just like strongly pure functions, they cannot access globals or
 statics. Strongly pure functions can be optimized such that only one call
 to
 them is made in an expression because their return value will always be the
 same, and they cannot alter their parameters. Weakly pure functions cannot
 be
 optimized in that manner, but because they don't alter the global state,
 they
 can be safely called from strongly pure functions without violating the
 strongly
 pure function's purity.

 Pure is not logically pure for essentially the same reasons that const is
 not
 logically const. Making it logical instead of guaranteed eliminates the
 guarantees, and the compiler can no longer rely on those guarantees, making
 them
 _far_ less valuable.

 It is true that a memoized function must be logically pure, or you're going
 to
 get errors. However, if you were to force such functions to be pure, it
 would be
 highly limiting. And since memoize _can't_ be pure, it would make recursion
 with
 memoize impossible. True, allowing for memoized functions to be impure
 makes it
 so that the programmer must be more careful, but it's still quite useful -
 in
 fact more useful - that way. And since you _can't_ have memoize be pure
 anyway,
 it's not like you're losing any guarantees from the compiler like if you
 tried
 to make pure logically pure or const logically const.

 - Jonathan M Davis


Don't take me too seriously since I'm learning those things on-the-fly here
(I'm greedy). The const FAQ (
http://www.digitalmars.com/d/2.0/const-faq.html#logical-const) says D
doesn't support logical const because it would break transitivity, and they
deemed transitivity to be more important (Walter even thinks it's bad,
doesn't he?), so I understand why const in D is not logical const.

But in the case of memoize, aren't there things that can be done to the
language spec to allow it to be pure? Maybe by adding some language
construct, I dunno.

Or by analysis of behavior. Obviously, that wouldn't work for external C
functions, but at least memoize would be okay. Also, I'm to guess it would
be extremely hard to write a compiler that does this, but I'd just like to
confirm.

@Walter: would it be hard/impossible for the compiler to look at memoize and
tell it exhibits pure behavior and is, thus, pure?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: D for game development

2011-01-01 Thread Guilherme Vieira
On Fri, Dec 31, 2010 at 4:08 PM, Andrei Alexandrescu 
seewebsiteforem...@erdani.org wrote:

 A discussion to which I think some of us could add value:


 http://stackoverflow.com/questions/4516283/the-d-programming-language-for-game-development

 Andrei


Lambert's answer says the compilers are definitely not bug-free and all, but
is it really that bad? In a medium-sized project, do the compiler bugs
really get all too frequent or something, and if so, is it simple to find
workarounds?

Because I guess, quite frankly... if Derelict works, I have nearly no reason
to keep doing C++. In fact, the ease of meta and generative programming in D
makes me wonder if it's not much easier make the game engine in it.

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: D for game development

2011-01-01 Thread Guilherme Vieira
On Sat, Jan 1, 2011 at 3:22 PM, Jimmy Cao jcao...@gmail.com wrote:

 Right now I'm trying out the approach of making existing C++ 3D engines
 available for D.  SWIG is very instrumental in the process.
 I hope that after the 64-bit issues are worked out, some special attention
 can be applied to the D language issue(s) that make it harder for SWIG to
 effectively generate D code.


It's certainly a worthy effort. Having high-level libraries in D are a good
way of getting people to learn it faster by trying things they find fun
(such as making games).

But I think I'll take another route if I have the time to write games in D.
I don't think I would like to make a game using one of those anymore (I had
a sorta bad experience with Ogre in which it kept getting on my way, or
maybe I was just silly and disliked its style; in any case, I'd rather do
things from scratch now, since it's also good for learning).

In any case, two efforts are better than one. Much appreciated! I hope we
can help ourselves out. :)

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: Happy New Year!!!

2010-12-31 Thread Guilherme Vieira
On Fri, Dec 31, 2010 at 2:43 PM, Stanislav Blinov 
stanislav.bli...@gmail.com wrote:

 Somebody's already celebrating, somebody's only anticipating, but
 regardless

 HAPPY NEW YEAR, EVERYONE!!! HAPPY NEW YEAR, D!!!


Happy new year from Brazil :)

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: discrimination of constructors with same number of parameters

2010-12-30 Thread Guilherme Vieira
On Thu, Dec 30, 2010 at 9:24 AM, bearophile bearophileh...@lycos.comwrote:

 Jonathan M Davis:

  typedef is definitely on the way out, so that's not a solution,

 typedef is deprecated (because its semantics is not flexible enough and
 because it doesn't play well with object oriented language features), but I
 have a real need for something like it. Andrei has discussed about a
 Phobos-based typedef replacement (based on structs + alias this), but
 nothing concrete has come out yet. I hope to see something to solve problems
 like spir ones.


  and it would be a pretty fragile one IMHO anyway.

 Please, explain better.

 Bye,
 bearophile


As far as I know, typedef was a form of discriminated alias. I don't know
the reasons for its deprecation. It just occurred to me that D's typedefs +
templates could be quite handy in this case.

Consider:

struct semantic_wrapper(T)
{
this(T value) { this.value = value; }

T value;
}

typedef semantic_wrapper!(int) Position;
typedef semantic_wrapper!(size_t) Count;
typedef semantic_wrapper!(string) Filename;
typedef semantic_wrapper!(string) DirPath;

void func(Position pos) { ... }
void func(Count c) { ... }
void func(Filename fname) { ... }
void func(DirPath dir) { ... }

void main()
{
func(Position(1)); // calls first overload
func(Count(5)); // calls second
func(Filename(file.txt)); // third
func(DirPath(/dev/null)); // fourth

func(1); // fails
func(blah); // fails
}


Requires a little more typing, but sometimes it can be better than creating
a new function name (which can get extra-big, non-telling or both) or than
creating factory methods (which I personally dislike, although it's just a
matter of taste most of the time; sometimes you may want to instantiate from
inside a template and classes needing factories would not work, for example,
but one could argue on the validity of this anytime).

Just giving my 2 cents. Dunno if I missed some detail.

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: discrimination of constructors with same number of parameters

2010-12-30 Thread Guilherme Vieira
On Thu, Dec 30, 2010 at 12:18 PM, spir denis.s...@gmail.com wrote:

 On Thu, 30 Dec 2010 08:15:51 -0500
 bearophile bearophileh...@lycos.com wrote:

   But some language types (or machine types) can have very diverse
 _human_ semantics, and thus be used for various purposes which should, but
 cannot, be considered different:
 
  You may wrap your data in a struct.

 Yes, thank you for this hint. A kind of proxy struct? It can indeed be used
 everywhere performance is not critical. But a side issue is that it requires
 the 'alias this' hack, I guess, or forwarding every operation to the actual,
 but wrapped, element. What do you think

 Denis
 -- -- -- -- -- -- --
 vit esse estrany ☣

 spir.wikidot.com


Why is performance harmed by the use of a struct? Wouldn't it be
zero-overhead like C++'s std::auto_ptr?

Also, the alias this and the forward might be a real good solution. And a
mixin like Luger's might be jackpot, really. I just dislike the use in:

func2(Position(1)); // implicit conversion to int with alias this


I guess that can be actually a bug, not a feature :) Maybe one day the
function signature changes slightly and the problem is further disguised
because you're obviously passing the right Position here... when it's
actually an int count thing. The alias this thing is a good shorthand
when assigning, though:

int a = pos; // implicit conversion from Position to int instead of
int b = pos.base;


-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: discrimination of constructors with same number of parameters

2010-12-30 Thread Guilherme Vieira
On Thu, Dec 30, 2010 at 3:19 PM, Steven Schveighoffer
schvei...@yahoo.comwrote:

 On Thu, 30 Dec 2010 12:08:56 -0500, spir denis.s...@gmail.com wrote:

  On Thu, 30 Dec 2010 17:10:00 +0100
 Jérôme M. Berger jeber...@free.fr wrote:

  Steven Schveighoffer wrote:
  What I would suggest is static factory methods.  The issue with any
 kind
  of typedef (be it with the soon-to-be-deprecated typedef keyword or
 with
  a proxy struct), is that what does this mean?
 
  auto obj = new Foo([1, 2, 3], blah);
 
  Is blah a filename or a message?
 
 -- Error, Foo (int[], string) does not exist.


 Yes, you are right. Typedef-like solutions need core support by the
 language with a kind of hint to the compiler... playing the role of type in
 Jérôme's sample below.


 I expected a definition like this:

 typedef string filename;

 this(int[] x, string message);
 this(int[] x, filename file);

 Which would be more ambiguous in usage.  So your version (with two
 typedefs) is better.


   Whereas, if you use factory methods:
 
  auto obj = Foo.createWithFilename([1,2,3], blah); // blah is a
 filename
  auto obj = Foo.createWithMessage([1,2,3], blah); // blah is a
 message


 Factory methods are definitely convenient. The single objection is rather
 conceptual: it defeats the purpose of a major language feature, namely
 constructor; which happens to have a clear meaning from the modelling point
 of view.


 This doesn't mean much to me.  I don't see the benefit of using 'new' vs.
 using a static factory method.  What is the clear meaning that
 constructors have that factory methods do not?


   The code becomes crystal clear.  Reduce verbosity as you see fit ;)
 
 auto obj = new Foo ([1, 2, 3], Filename (blah));
 auto obj = new Foo ([1, 2, 3], Message (blah));


 Conceptually, I would prefere this -- at the use place. But if requires
 obfuscating the code at the definition point (with eg wrapper structs), is
 it worth it?

 If we could write eg:
typedef string Message;
auto obj = new Foo ([1, 2, 3], Message (blah));
 then I would be happy, I guess ;-)


 Wait, this isn't any different than using a wrapper struct...

 struct Message
 {
   string value;
 }

 struct Filename
 {
   string value;
 }

 class Foo
 {
   string message;
   string filename;
   int[] arr;
   this(int[] arr, Message m) {this.arr = arr; this.message = m.value;}
   this(int[] arr, Filename f) {this.arr = arr; this.filename = f.value;}
 }

 How is that obfuscation?

 I still prefer the factory method solution, as it doesn't add unecessary
 types.

 -Steve


There's an idiom I'm quite fond of. There are some classes you shouldn't be
instantiating yourself.

Take for example a SoundSource class, which represents a source of sound in
a 2D or 3D environment. It's obvious that it requires the SoundSystem to be
initialized when it's created, unless it used lazy initialization of the
sound system (which I dislike, since everytime you create an object it'll
have to check whether the system is initialized or not).

As such, it makes sense that the architecture guide client developers to
only instantiate after initializing the system. If you normally simply
*new*SoundSources yourself, it's not hard to forget the sound system
initialization. So I prefer to make the SoundSystem class a factory of
SoundSources (Ogre3D does such things a lot), and it's particularly damn
great to create template methods such as these:

class SoundSystem
{
Unique!(TSoundSource) createSource(TSoundSource, CtorArgs...)(CtorArgs
ctorArgs)
{
// reserves first argument for mandatory parameters, but leaves the
rest client-defined
return new TSoundSource(this, ctorArgs);
}
}

// later ...
sndSystem.createSource!(MySoundSource)(my, custom, parameters);


In this case, constructing the SoundSource required a SoundSystem as a
parameter, so yeah, you would need the thing to be able to instantiate
alright. But it surely gives margin to misuses: if you, as the library
developer, noticed that *any* SoundSource implementation should get the
SoundSystem upon construction from the caller (and not try to tell which
system to use by e.g. picking it from a singleton of the likes), then this
idiom is useful.

I find this kind of usage extremely expressive (in fact, I'd like to take
the moment the ask what the gurus think about it; I really have never seen
people doing this). It shows precisely how the library is meant to be used.

The least wrong things you can do, the better, so getting rid of the
possibility of instantiating things at the wrong times is certainly good.
And static factories succeed in making such things harder.

Yes, you could wrap classes in structs that would construct them using one
factory or another, but making useful idioms more and more cumbersome to use
is almost never a good idea:

struct MyObjectWithFileName // this
{ // is
this(string fname) { obj = MyObject.createWithFilename(fname); } // so
MyObject obj; // much
} // typing!


Re: Clay language

2010-12-27 Thread Guilherme Vieira
On Mon, Dec 27, 2010 at 4:35 PM, bearophile bearophileh...@lycos.comwrote:

 Through Reddit I have found a link to some information about the Clay
 language, it wants to be (or it will be) a C++-class language, but it's not
 tied to C syntax. It shares several semantic similarities with D too. It
 looks like a cute language:
 https://github.com/jckarter/clay/wiki/

 Some small parts from the docs:

 --

 In Clay this:
 https://github.com/jckarter/clay/wiki/Syntax-desugaring

 static for (a in ...b)
c;

 is equivalent to:

 {
ref a = first element of b;
c;
 }
 {
ref a = second element of b;
c;
 }
 /* ... */

 I have an enhancement request about this for D:
 http://d.puremagic.com/issues/show_bug.cgi?id=4085

 

 The part about Safer pointer type system is very similar to what I did ask
 for D, and it looks similar to what Ada language does (for Clay this is just
 a proposal, not implemented yet, but Ada is a rock-solid language):
 https://github.com/jckarter/clay/wiki/Safer-pointer-type-system

 

 This is something that I want for D too, it's important:

 Jonathan Shapiro (of BitC) makes an excellent argument that, in a systems
 language, it is often undesirable to depend on the whims of an ill-specified
 optimizer to convert abstract code into efficient machine code. The BitC
 specification thus includes the idea of guaranteed optimizations, to allow
 code to be written in a high-level style with predictably low or nonexistent
 runtime cost (link). [...] Because Clay seeks to support systems programming
 with high-level abstraction, certain patterns should be guaranteed to be
 optimized in a certain way, instead of being left to the whims of LLVM or a
 C compiler. Additional optimizations should not be prevented, however. [...]
 It should be possible to specify that one or more of these optimizations is
 required, and have the compiler raise an error when they cannot be applied
 for some reason.

 https://github.com/jckarter/clay/wiki/Guaranteed-optimizations

 Bye,
 bearophile


+1 for static for and guaranteed optimizations. Can we put it in the
wishlist?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Re: Creating an array of unique elements

2010-12-27 Thread Guilherme Vieira
On Mon, Dec 27, 2010 at 12:14 PM, Guilherme Vieira n2.nitro...@gmail.comwrote:

 Ah, yeah. I think you're right. Set is exactly what I need, and the fact
 that it works with hashes is even better. A pity D still doesn't have it,
 since it looks very useful, but thanks for your response. I'll take a look
 at your implementation later.

 Is there any prevision for sets in core D or Phobos?

 --

 Atenciosamente / Sincerely,
 Guilherme (n2liquid) Vieira


 On Mon, Dec 27, 2010 at 11:39 AM, spir denis.s...@gmail.com wrote:

 On Mon, 27 Dec 2010 05:22:14 -0200
 Guilherme Vieira n2.nitro...@gmail.com wrote:

  Right now I'm wondering how's the best way to create a dynamic array
 object
  which will only accept unique elements (i.e., elements != from the
  existing elements in the array).

 (Take my words with precaution because I don not know D very well myself.)

 Hello Guilherme. If I understand your purpose correctly, what you're
 trying to define is a set, not an array, in the common sense of the terms in
 programming. To ensure uniqueness, you'd need to check whether the element
 exits already, which can only be very slow using an array (O(n)): you need
 to traverse the array element per element. Sets instead are build using data
 structures that allow this check to be far faster, by looking up a given
 element in a more clever way.

 There is no builtin Set type in D yet. The simplest way (and maybe the
 best) would be use associative arrays where keys would be actual elements
 and values just fake. (e in set) would tell you what you need. Depending on
 your requirements, trying to put an existing element would just put it again
 with no change, or should throw an error. In the latter case, you need to
 check it yourself or build a wrapper type (struct or class) around builtin
 associative arrays.

 For instance:
Existence[Element] set;
Element[] elements = ['a','c','e'];
Element[] values = ['a','b','c','d','e'];
foreach (element ; elements)
set[element] = EXISTS;
// Note: 'in' actually return a pointer to element.
foreach (value ; values)
writeln(cast(bool)(value in set));

 Note: I have a Set type in stock at
 https://bitbucket.org/denispir/denispir-d/src/b543fb352803/collections.d,
 but wonder whether it's really necessary given the above. But you can have a
 look to see how it's done (this would give you some hints about language
 methods called 'opSomething', see TDPL's index).


 Denis
 -- -- -- -- -- -- --
 vit esse estrany ☣

 spir.wikidot.com


Eek..! sorry for top-posting.

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira


Creating an array of unique elements

2010-12-26 Thread Guilherme Vieira
Hi, guys. — said the shy newcomer.

I've started reading The D Programming Language just yesterday and I'm
making my first attempts to dig into D now. I must say I'm loving the
language beyond recognition. I never thought there was a language out there
that had everything I ever wanted in C++ (I even considered developing my
own language before knowing D!).

Right now I'm wondering how's the best way to create a dynamic array object
which will only accept unique elements (i.e., elements != from the
existing elements in the array).

I wanted a class that kept all the functionality of an array (e.g. being the
right range types so that they can be passed to std.format.formatValue and
trigger the right specialization) for maximum integration with the standard
library. I thought about writing a class template privately containing an
array and redirecting everything but the assignment/insertion operations to
it. All ways of placing an object that was already there should throw an
exception, but everything else should work the same.

Doing it this way is a lot of work for a simple thing, so some sort of
internal alert in me tell me I might just be doing-it-wrong. I want to
know what your ideas are.

I want some way to achieve this sort of thing:

import myproject.helpers.UniqueArray;

void main()
{
auto a0 = [1, 2, 3];

// I'm not yet sure how to go about the constructor, since:

auto a1 = UniqueArray!(int)(a0[1 .. $]); // error: should not be able to
internally hold reference to
 // a raw array since this could
be used to break the unique
 // elements contract promise
of UniqueArray
 // copy of elements can be
considered, but I'd rather
 // have clients copy the array
themselves so that they
 // know it is happening

auto a2 = UniqueArray!(int)(a0[1 .. $].dup); // should be fine if D had
some sort of non-const
 // rvalue reference
support, but I think it does not;
 // am I wrong?

auto a3 = UniqueArray!(int)(a0[1 .. $].idup); // semantically pleasing
at first sight, but
  // suboptimal: the
constructor would have to copy
  // the passed array again
to get rid of immutability

auto a4 = bestOptionOutOf(a1, a2, a3); // (:

a4[1 .. $] = [3, 4, 5]; // ok: would first construct a UniqueArray out
of the rvalue (thus ensuring
// uniqueness of elements) and then would work
like a usual slice
// assignment

a4 ~= 5; // throws exception: 5 is already in the array!
a4 ~= 6; // ok: 6 is not there

writeln(a4); // ok, output: [2, 3, 4, 5, 6]
 // could just implement UniqueArray.toString() for this to
work, but making UniqueArray
 // properly model the ranges an array models solves this
problem and others at the same
 // time

auto a5 = a4.dup; // all properties of an array, such as dup here,
should hold and overall
  // the object should behave as one would expect from
an array

int[] a6 = a5; // error: obviously shouldn't work since a6 could then be
used to break the
   // UniqueArray contract

}


What do you think?

-- 
Atenciosamente / Sincerely,
Guilherme (n2liquid) Vieira