December 27, 2013
Let me just check my understanding:  If a function says it returns a thing of type T, it really does return something whose outermost shape is T; however, if it contains pointers to other things, and these were stack allocated, the pointers might be readdressed.

@Bearophile: in your example, why is the array heap allocated?  For arrays do you not need to use new?

From the documentation:
"BUGS:
Currently, Algebraic does not allow recursive data types."
... So maybe in the future, I can refactor to that.

It makes sense that union is not type safe.  If I have a struct like this

struct F {
  enum Case {case1, case2}
  Case case;
  int x;
  string y;
  this(int x_in)
  {
    x = x_in;
    case = case1;
  }
  this(string y_in)
  {
  y = y_in;
  case = case2;
  }
}

That seems like a bad practice leaving one of the fields uninstantiated.  Is this is a sign that I should be using an object oriented approach, or is there a way to clean this up.

I have to admit, I don't understand the mixin/template stuff right now.  However the mixin ADT thing seems pretty sexy, so it might be a good idea to learn enough to understand what is going on there.  The problem I have with this is if it ends up describing a struct in the background, will I have to keep a bunch of conventions straight in my head, or are there lots of utilities for working with this kind of thing (i.e. can I do a case operation, and recurse on subterms)?  Are templates considered a good practice in D?

Also, would

mixin ADT!q{ Term: Var char | Op char Term[] | Ptr Term*};

be considered valid.  If so, then it would allow me to create a term t get its pointer, p, and then have
  Op 'g' (Ptr p, Ptr p)
so that in rewriting g(t,t), I only need to rewrite t once.

Suppose a seasoned D programmer were thinking about this problem: would (s)he opt for an object oriented approach or the use of structs.  The main point of this data structure is to implement term rewriting.  There will probably be a lot of object creation -- especially in building and applying substitution lists.  I don't see any real benefit of one of the other for this application.

I tend not to worry too much about being performance critical i.e. cutting corners to shave off constants at the expense of losing safety ... I tend to prefer a simpler approach as long as I can guarantee that the big-O is the same -- however, I try to avoid even logarithmic "blowups" in comparable approaches ...
December 27, 2013
Timon Gehr:

> https://d.puremagic.com/issues/show_bug.cgi?id=11558

We are getting there :-)


> but implying that you are somehow ethically superior and that I am not human seems to go a little far. :o)

Sorry. In my opinion that kid of code is not very readable, spaces help to eye to chunk the code better.


> They hurt there because they add noise and don't help.

The parentheses in "(x < $) ? x : 0" are not necessary, but they help chunk the code, the first chunk is the condition. This is especially useful when that condition gets a little longer.

Bye,
bearophile
December 27, 2013
On 12/27/2013 05:08 PM, Jonathan wrote:
> Let me just check my understanding:  If a function says it returns a
> thing of type T, it really does return something whose outermost shape
> is T; however, if it contains pointers to other things, and these were
> stack allocated, the pointers might be readdressed.
> ...

Well, the it is returned as-is, but the value of something that contains indirections is in general only meaningful in the context of a corresponding heap, stack and static data segment. Here the stack is changed in a way that renders the pointers in the returned value meaningless, so type safety does not hold. (Outside of @safe code, type safety is conditional on the programmer making sure that code does not violate certain invariants.)

> @Bearophile: in your example, why is the array heap allocated?

This is just how the language feature works. The array literal allocates an array on the heap and gives you a slice to it. (If you assign such a literal to a static variable during compilation, it will actually be stored in the static data segment.)

> For arrays do you not need to use new?
> ...

You can also allocate a new array using new:

auto x = new int[](4); // allocate array of 4 elements

> ...
>
> It makes sense that union is not type safe.  If I have a struct like this
> ...
> }
>
> That seems like a bad practice leaving one of the fields
> uninstantiated.  Is this is a sign that I should be using an object
> oriented approach, or is there a way to clean this up.
> ...

The only way to clean it up is to hide it behind a type safe interface. (Besides concise syntax, that's all the ADT mixin template is doing essentially.)

> I have to admit, I don't understand the mixin/template stuff right now.
> However the mixin ADT thing seems pretty sexy, so it might be a good
> idea to learn enough to understand what is going on there.

It parses the given specification (q{this is a string}), generates D code as a string using the built-in D interpreter that the compiler comes with. ("Using CTFE".) Then the generated D code is "mixed in" and compiled.

> The problem
> I have with this is if it ends up describing a struct in the background,
> will I have to keep a bunch of conventions straight in my head, or are
> there lots of utilities for working with this kind of thing (i.e. can I
> do a case operation, and recurse on subterms)?

Well, it is implemented in D code, so that's up to you. The proof-of-concept implementation supports pattern matching.

> Are templates considered a good practice in D?
> ...

Yes, but mixins less so. (They are considered good if there is no other way to get what you want.)

> Also, would
>
> mixin ADT!q{ Term: Var char | Op char Term[] | Ptr Term*};
>
> be considered valid.  If so, then it would allow me to create a term t
> get its pointer, p, and then have
>    Op 'g' (Ptr p, Ptr p)
> so that in rewriting g(t,t), I only need to rewrite t once.
> ...

A full-blown ADT implementation probably would not tolerate mutable aliasing.

> Suppose a seasoned D programmer were thinking about this problem: would
> (s)he opt for an object oriented approach  or the use of structs.  The
> main point of this data structure is to implement term rewriting.  There
> will probably be a lot of object creation -- especially in building and
> applying substitution lists.  I don't see any real benefit of one of the
> other for this application.
>
> I tend not to worry too much about being performance critical i.e.
> cutting corners to shave off constants at the expense of losing safety
> ... I tend to prefer a simpler approach as long as I can guarantee that
> the big-O is the same -- however, I try to avoid even logarithmic
> "blowups" in comparable approaches ...

You should probably just go with classes then. (It's what I've done for a recent toy implementation of the calculus of constructions.)

December 27, 2013
On Friday, 27 December 2013 at 16:08:09 UTC, Jonathan wrote:
> Let me just check my understanding:  If a function says it returns a thing of type T, it really does return something whose outermost shape is T; however, if it contains pointers to other things, and these were stack allocated, the pointers might be readdressed.

The pointers remain exactly how they were, but stack allocated memory is released when the function that allocated it returns (that's just how the stack works, it's temporary scratch space for functions) so the pointers are left pointing to garbage.
1 2
Next ›   Last »