November 27, 2012
On Tuesday, 27 November 2012 at 14:05:37 UTC, Joseph Rushton Wakeling wrote:
> On 11/27/2012 01:16 PM, Joseph Rushton Wakeling wrote:
> ... so the real issue here seems to be that there's no canonical way (that I can find) to idup an _associative_ array.

I'm using a custom gdup that recursively copies fields and requires no support from nested structs. If a dup is provided by a struct it will be called. No guarantees, but have a look. https://github.com/patefacio/d-help/blob/master/d-help/opmix/mix.d

The following runs:

--------------------------
import std.stdio;
import std.typecons;
import std.conv;
import std.exception;
import opmix.mix;

alias Tuple!(uint, "id") Link;

struct Node
{
  uint id;
  Link[] links;

  void addLink(uint l)
  {
    links ~= Link(l);
  }

  immutable(Node) idup() pure const @property
  {
    auto linkCopy = to!(Link[])(links);
    immutable ilinks = assumeUnique(linkCopy);
    return immutable(Node)(id, ilinks);
  }
}


struct Network
{
  Node[uint] nodes;

  immutable(Network) idup() pure const @property
  {
    auto nodeCopy = nodes.gdup;
    immutable imnodes = assumeUnique(nodeCopy);
    return immutable(Network)(imnodes);
  }

  void add(uint i, uint j)
  {
    if((i in nodes) is null)
      nodes[i] = Node(i);
    if((j in nodes) is null)
      nodes[j] = Node(j);

    nodes[i].addLink(j);
    nodes[j].addLink(i);
  }

  void print()
  {
    foreach(k; nodes.keys)
      {
        write("[", k, "]");
        foreach(l; nodes[k].links)
          write(" ", l.id);
        writeln();
      }
    writeln();
  }
}

unittest {
  auto n1 = Node(1);

  n1.addLink(5);
  n1.addLink(6);
  writeln(n1.links);

  immutable n2 = n1.idup;
  writeln(n2.links);

  Network net1;
  net1.add(1,2);
  immutable Network net2 = net1.idup;
  writeln(net1);
  writeln(net2);
}

November 29, 2012
On 11/27/2012 05:31 PM, Dan wrote:
> I'm using a custom gdup that recursively copies fields and requires no support
> from nested structs. If a dup is provided by a struct it will be called. No
> guarantees, but have a look.
> https://github.com/patefacio/d-help/blob/master/d-help/opmix/mix.d

Thanks for that -- I'll look through it carefully.

My one caveat here is that in general I'm reluctant to rely too strongly on 3rd-party libraries at this stage of D's development.  That's particularly true where stuff like this is concerned -- which might well be best placed in the standard library itself.  Generic, broadly-applicable .dup and .idup commands would seem to be something that should be available in Phobos ...

... anyway, back to the specifics -- even though I could use opmix, I'd still really like to understand for myself how to solve the problems described in my previous emails -- in particular, how to effectively idup my struct containing the Node[uint] associative array _without_ relying on some external library.  My feeling is I'll learn more about D this way ... :-)

November 29, 2012
On Thursday, 29 November 2012 at 16:28:42 UTC, Joseph Rushton Wakeling wrote:
> My one caveat here is that in general I'm reluctant to rely too strongly on 3rd-party libraries at this stage of D's development.  That's particularly true where stuff like this is concerned -- which might well be best placed in the standard library itself.  Generic, broadly-applicable .dup and .idup commands would seem to be something that should be available in Phobos ...
>
> ... anyway, back to the specifics -- even though I could use opmix, I'd still really like to understand for myself how to solve the problems described in my previous emails -- in particular, how to effectively idup my struct containing the Node[uint] associative array _without_ relying on some external library.  My feeling is I'll learn more about D this way ... :-)

I feel the same way - as I said there are no guarantees, I'm using it but it may not cover the majority of cases and it may be obviated by whatever solution Walter is cooking up for copy construction and copying of const reference types. Doing it yourself is the best way to learn. What I really like about D is that you can have what seems like a crippling issue (no way to copy const objects) and use features like mixin compile time recursion to have a potentially nice general solution. I also think the dup should be formalized, maybe not as a keyword but a strong convention supported by the language, maybe phobos. For example, in your code you have already written 2 idup functions. The code below works as well with no need to write those custom functions. Besides, it should be safer (assuming it works ;-) because you can add new fields and have less to update. BTW: if you are still working on this be aware you may eventually have some (unwanted?) data sharing going on since there are no postblits and you have reference types with aliasing.

Some descriptions of the code and its intentions are:

https://github.com/patefacio/d-help/blob/master/doc/canonical.pdf

Thanks
Dan

--------------------------------------------------------------------
import std.stdio;
import std.typecons;
import std.conv;
import std.exception;
import opmix.mix;

alias Tuple!(uint, "id") Link;

struct Node
{
  uint id;
  Link[] links;

  void addLink(uint l)
  {
    links ~= Link(l);
  }
}


struct Network
{
  Node[uint] nodes;

  void add(uint i, uint j)
  {
    if((i in nodes) is null)
      nodes[i] = Node(i);
    if((j in nodes) is null)
      nodes[j] = Node(j);

    nodes[i].addLink(j);
    nodes[j].addLink(i);
  }

  void print()
  {
    foreach(k; nodes.keys)
      {
        write("[", k, "]");
        foreach(l; nodes[k].links)
          write(" ", l.id);
        writeln();
      }
    writeln();
  }
}

unittest {
  auto n1 = Node(1);

  n1.addLink(5);
  n1.addLink(6);
  writeln(n1.links);

  immutable n2 = cast(immutable)n1.gdup;
  writeln(n2.links);

  Network net1;
  net1.add(1,2);
  immutable Network net2 = cast(immutable)net1.gdup;
  writeln(net1);
  writeln(net2);
}


November 30, 2012
On 11/27/2012 06:05 AM, Joseph Rushton Wakeling wrote:
> On 11/27/2012 01:16 PM, Joseph Rushton Wakeling wrote:
>> immutable(Node) idup() pure const @property
>> {
>> auto linkCopy = to!(Link[])(links);
>> immutable ilinks = assumeUnique(linkCopy);
>> return immutable(Node)(id, ilinks);
>> }
>
> Actually I'm being overly complicated here as with dynamic arrays I can
> simply do,
>
> immutable(Node) idup() pure const @property
> {
> return immutable(Node)(id, links.idup);
> }
>
> ... so the real issue here seems to be that there's no canonical way
> (that I can find) to idup an _associative_ array.

I've forced it pretty hard: :D

    immutable(Network) idup() pure const @property
    {
        Node[uint] nodesCopy;

        foreach (key, node; nodes) {
            immutable(Node) nodeCopy = node.idup;
            nodesCopy[key] = cast(Node)nodeCopy;
        }

        immutable imnodes = assumeUnique(nodesCopy);
        return immutable(Network)(imnodes);
    }

I hope it is safe. :p

Ali
December 05, 2012
On 11/30/2012 05:45 AM, Ali Çehreli wrote:
> I've forced it pretty hard: :D
>
>      immutable(Network) idup() pure const @property
>      {
>          Node[uint] nodesCopy;
>
>          foreach (key, node; nodes) {
>              immutable(Node) nodeCopy = node.idup;
>              nodesCopy[key] = cast(Node)nodeCopy;
>          }
>
>          immutable imnodes = assumeUnique(nodesCopy);
>          return immutable(Network)(imnodes);
>      }
>
> I hope it is safe. :p

You know, now I'm embarrassed, because I really should have come up with this myself. :-P

Actually, I think I did, but I was concerned that the returned result wouldn't actually be identical to the original, inasmuch as e.g. inserting the nodes one by one might cause everything to be in a different order to the original.  So I didn't have the confidence to try it out.

Of course, I could always test these things ...

Thanks very much for the suggestion!
1 2 3
Next ›   Last »