imports and a data structure (any critique welcome)

Timon Gehr timon.gehr at gmx.ch
Fri Dec 27 05:25:50 PST 2013


On 12/27/2013 05:54 AM, Jonathan wrote:
> Thanks to everyone that has replied.
>
> @Timon Gehr:
> Thank you.  In reply to [1]: that is an interesting issue that I don't
> really understand right now.  Can you explain exactly where I invoke
> undefined behavior?  It was my understanding that structs are passed and
> returned by value, and the assignment
>    x = some struct
> makes a copy of some struct and stores it in x.  Perhaps I don't
> understand the type system of D?

The original code takes the address of variables that are allocated on 
the stack. Function-local variables (fortunately/unfortunately) have 
limited lifetime unless they are closed over. If their address is 
dereferenced after they have gone out of scope, you are accessing 
locations on the stack that may have been populated with new data of 
different type in the meantime. Eg. any usage of the '&' operator in the 
original code is wrong, because the addresses are part of the structure 
that the function returns.

> If a function returns T where T is
> some struct, does the function result in a struct?  I am having trouble
> finding these subtleties in the documentation (but I also acknowledge
> that this is probably my fault and not the documentation's).
> ...

The documentation can indeed be a little sparse. This may help you:
http://ddili.org/ders/d.en/index.html
(I have not read a lot of it, but it appears to put special focus on 
subtleties as it is targeted also at programming novices.)

> Does auto do a simple type inference to find out that Term* should be
> there?

No, auto is just a place holder used to show that what follows is a 
declaration. What is important to invoke type deduction is that there is 
no type specified. (It indeed is very simple, all it does is copying the 
type of the initializer.)

> Is there an advantage to using auto?
> ...

Less redundancy. Eg. I would have been able to remove the undefined 
behaviour faster if type deduction was already in use.

> I can't seem to put @safe: at the top of the file

Yes, I missed the union. (It is not generally a memory safe construct.)

> -- is it the same as compiling with -safe.

I think this compiler switch no longer exists.

> Is there a way to add this as a source annotation?
> ...

Yes, @safe: at the top of the file is the source annotation.

> Is ! an operator in e.g. ADT!q ...
> ...

It is notation for template instantiation.
http://dlang.org/template.html
http://ddili.org/ders/d.en/templates.html
http://ddili.org/ders/d.en/templates_more.html

> What is the mixin bit doing?

It imports the declarations within the template body into the current scope.

> Can you point me towards any tutorials, or  should I buy the book?
> ...

http://ddili.org/ders/d.en/mixin.html
http://dlang.org/template-mixin.html
I don't think the book discusses mixins in depth.

> @bearophile:
> Thank you for the welcome.  That is odd;

Maybe he just does not know a lot of Haskell programmers. :o)

> I find that D shares a
> philosophy closer to Haskell than many of the "lower level" languages
> like C.
> ...

I guess some missing type system features can turn off Haskell 
programmers. Most importantly, the type system is monomorphic. 
(Templates cover some use cases of a polymorphic type system.)

> So let me just say, I really do need to build a structure that can have
> a shared reference to a substructure.  I will be rewriting these terms,
> and the problem is that e.g.
>
>      f(t) -> g(t,t)
>
> I don't want to copy t, but store a reference to t, so that if t can be
> re-written, it will only be rewritten once.  However, this is really
> *not* an algebraic type since sharing is not algebraic, so I figured
> that this would not be a good solution.
>
> The object oriented approach would be really nice.  Since objects are
> passed by reference, I should get sharing for free.  The only reason I
> didn't use an object oriented approach off the bat is that I don't think
> I completely understand when to use a struct versus an object.

Objects are often used for convenient virtual function tables, for 
reference semantics, and sometimes to emulate closed sum types in a 
memory safe fashion. structs are typically used for more manual control 
and for implementing types with (part-wise) value semantics.

> Using
> structs seem to fit the story better, because the structure isn't really
> emitting any functionality, I just want to perform some functions to
> it.

Some might claim that the structure emits visitor functionality. :o)

> So using structs feel like a better fit.  Feel free to correct me
> here.  What are some of the drawbacks to using object.

They may waste some memory.

> How much more time overhead is there once the object is created?
> ...

Virtual function calls have some overhead compared to static function 
calls, but it is less bad on x86/x64 than on some other architectures. 
How performance-critical is your application?

> You are right, I probably look like an idiomless noob!  I totally am!
> Hopefully an understanding of the appropriate keywords to use and where
> will come (there is quite a lot of syntax in D). For now, can you tell
> me what I could do better about the switch statement

I don't know what he was targeting at, but convertNum could be written 
more compactly as:
char convertNum(int x){
     return "exyzfgh"[x<$?x:0];
}

> and what is wrong with (*term).node?

The explicit dereference is redundant. term.node suffices.


More information about the Digitalmars-d-learn mailing list