Re: imports in a Separate File?

2018-12-11 Thread Ron Tarrant via Digitalmars-d-learn
On Tuesday, 11 December 2018 at 15:39:18 UTC, Steven 
Schveighoffer wrote:


Use public imports in your header file. This will pretend that 
the symbols imported reside in the module itself.


i.e. inside importedStuff.d:

public {
   // 120 import statements
}

-Steve


Thanks, Steve. Works like a charm... but you knew that.


Re: imports in a Separate File?

2018-12-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 12/11/18 10:27 AM, Ron Tarrant wrote:
I ran across a code example 
(https://github.com/gtkd-developers/GtkD/blob/master/demos/gtkD/TestWindow/TestWindow.d) 
in which the first ~120 lines are mostly import statements.


And it got me wondering...

I tried to off-load a bunch of imports into a pseudo-header file — 
importedStuff.d — and then in the actual code file I just did:


import importedStuff;

but found myself swimming in undefined identifier errors.

Is there a way to do this so I wouldn't have to scroll 120 lines into a 
file before finding code? Or does this mean I still haven't caught onto 
what I was told the last time I was on this forum?


(And here's a grammar question, just for the heck of it: Why isn't forum 
spelled with an 'n,' like column?)




Use public imports in your header file. This will pretend that the 
symbols imported reside in the module itself.


i.e. inside importedStuff.d:

public {
   // 120 import statements
}

-Steve


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-09 Thread Ron Tarrant via Digitalmars-d-learn

Thanks everyone.


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-07 Thread Ron Tarrant via Digitalmars-d-learn

So, the upshot of it all seems to be that the -i's have it.


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-07 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Dec 07, 2018 at 07:01:18PM +, Adam D. Ruppe via Digitalmars-d-learn 
wrote:
> On Friday, 7 December 2018 at 17:41:47 UTC, Ron Tarrant wrote:
[...]
> > when I compile rather than compiling modules over and over
> > needlessly.
> 
> Oh, lots of us compile everything at once. It works quite well and is
> fast for many applications that you don't need to do anything more.

Yes, the D compiler is fast enough that for a small project, recompiling
everything vs. compile a single source file doesn't make a noticeable
difference in compilation time.

For larger projects, the general recommendation is to use the package as
your unit of recompilation, i.e., if you have your source tree structure
like this:

package1/
package1/mod1.d
package1/mod2.d
package2/
package2/mod1.d
package2/mod2.d

then when you recompile, if package1/* hasn't been touched, but
package2/mod2.d was changed, then recompile package2/* into a static
library, and relink your application.

The above example is greatly simplified, of course; generally, your
package subdirs would have 10+ source files or so before this sort of
per-package recompilation actually benefits compilation times.  In some
of my projects, where package subdirs are relatively small, I just lump
the source files inside together with everything else and just recompile
the whole thing at once.  IME, separately recompiling individual .d
files generally slows down compilation rather than speed it up -- the
linker has more work to do to resolve cross-references that the compiler
would have statically resolved had you passed all source files at once
instead.


> > Does D have the concept of makefiles? I haven't run across any
> > reference to such things so far.
> 
> Yes, you can use a makefile with D basically the same as with C. But
> you may find it actually builds slower than just dmd -i main.d

This is true for most small to medium-sized projects. For larger
projects, it does help to compile different packages separately (perhaps
in parallel if your build system supports that).

In my own projects, I actually use my build system more to resolve other
complex tasks than to individually compile D source files; I'd just
specify what amounts to `dmd *.d` in a single build rule, and most of
the rest of the build script is to handle other tasks, like generating
code from input data, preprocessing resource files, building/signing
packages, compiling code in other languages (Java, C, etc.),
installation to the staging area for testing, etc.. So ironically, most
of my build rules concern stuff other than compilation.  :-D


T

-- 
Stop staring at me like that! It's offens... no, you'll hurt your eyes!


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-07 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 7 December 2018 at 17:41:47 UTC, Ron Tarrant wrote:
Are you talking about a list of import statements here or is 
there another way/place I would list them?


On the dmd command line. So say your program has a.d and b.d, you 
would compile with `dmd a.d b.d`.


Or as you had some success with, the newer compilers let you just 
do `dmd -i a.d` and it finds the rest based on the import 
statements.



I'm not sure what you mean by 'library' in this statement.


For example, since you are using gtkd.lib, you don't have to 
include all of gtkd's source files. (The compiler needs to be 
able to FIND them, but you don't have to list them.)


If you were using a makefile, you may only list one file at a 
time to compile each separately, then link together all the 
generate .obj files as a separate step.


Just still trying to understand when it would be necessary to 
use a prefix and dot separator in an import statement.


The most practical answer is "always".

There's some exceptions that work for simple cases, but even then 
you put yourself at potential conflicts if some library author 
decided to pick the same name.


So you are really better off just always using some prefix and 
always listing the full name.


module myprojectname.mymodulename;

at the top of every file in your source tree. (Or you can use 
more dots if you want to further subdivide it, like 
"myprojectname.helper.whatever.mymodulename").


And when importing it, always list the full name, exactly the 
same as you listed it in the module definition.


import myprojectname.mymodulename;
import myprojectname.helper.whatever.mymodulename;


Every time you use it, from any location. Then it will work in 
all cases, whether compiling all at once (which I recommend btw), 
or using a makefile, or any other build system, even if you 
decide to bring in more libraries or your program grows beyond 
the super simple cases.


You can organize the subfolders based on those dot names (or do 
the dot names based on the subfolders if that is existing) and 
that will ease the process a bit more. But regardless of the 
folder layout and file locations, always use the full names and 
be sure they match in module and import statements.


when I compile rather than compiling modules over and over 
needlessly.


Oh, lots of us compile everything at once. It works quite well 
and is fast for many applications that you don't need to do 
anything more.


Does D have the concept of makefiles? I haven't run across any 
reference to such things so far.


Yes, you can use a makefile with D basically the same as with C. 
But you may find it actually builds slower than just dmd -i 
main.d


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-07 Thread H. S. Teoh via Digitalmars-d-learn
On Sat, Dec 08, 2018 at 06:48:46AM +1300, rikki cattermole via 
Digitalmars-d-learn wrote:
> On 08/12/2018 6:41 AM, Ron Tarrant wrote:
> > Does D have the concept of makefiles? I haven't run across any
> > reference to such things so far.
> 
> Make isn't a D specification application (it doesn't really specialize
> in any language) dmd, druntime and Phobos are all built using it.
> 
> Though for user code, dub is the package+build manager that is more
> commonly used.

You can surely use Makefiles to compile your D code.  DMD, druntime, and
Phobos use Makefiles. :-D

Though due to limitations with makefiles, I prefer to use SCons. I'd use
dub as a package manager, but I find its limitations as a build manager
too frustrating and a total deal-breaker for the kind of builds I need
to do, so I generally avoid using it as such.


T

-- 
Prosperity breeds contempt, and poverty breeds consent. -- Suck.com


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-07 Thread rikki cattermole via Digitalmars-d-learn

On 08/12/2018 6:41 AM, Ron Tarrant wrote:
Does D have the concept of makefiles? I haven't run across any reference 
to such things so far.


Make isn't a D specification application (it doesn't really specialize 
in any language) dmd, druntime and Phobos are all built using it.


Though for user code, dub is the package+build manager that is more 
commonly used.


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-07 Thread Ron Tarrant via Digitalmars-d-learn

On Friday, 7 December 2018 at 16:43:02 UTC, Adam D. Ruppe wrote:
That's wrong: the import name and the module name should always 
match, in full, including all the dot parts.


So if you "import app.modulename;", the other file must have 
"module app.modulename;"


Okay. I guess the instructions I saw were for an earlier version 
of D... or I misunderstood. (either is likely?)


Moreover, you should either 1) list all modules in your 
application


Are you talking about a list of import statements here or is 
there another way/place I would list them?



not in a library on the command line,


I'm not sure what you mean by 'library' in this statement.

or 2) if using the newest compiler versions, pass the -i flag 
so the compiler will automatically include them for you.


I tried this and it worked.

Just still trying to understand when it would be necessary to use 
a prefix and dot separator in an import statement.


The bottom line here is, I have an application (Corkboard) I 
wrote in PHPGtk years ago and I'm learning D by transposing it. 
I'd like to maintain the code organization I had in the original 
— subfolders, etc. At the same time, I'd like to put my big-boy 
pants on and make it look like I know what I'm doing when I 
compile rather than compiling modules over and over needlessly.


Does D have the concept of makefiles? I haven't run across any 
reference to such things so far.


Re: Imports and Subfolders and Links (Oh, My!)

2018-12-07 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 7 December 2018 at 16:39:34 UTC, Ron Tarrant wrote:

import subfolder.ModuleName;

And in the module files, the first statement is:

module ModuleName;


That's wrong: the import name and the module name should always 
match, in full, including all the dot parts.


So if you "import app.modulename;", the other file must have 
"module app.modulename;"



dmd -m64 -Lgtkd.lib main.d


Moreover, you should either 1) list all modules in your 
application not in a library on the command line, or 2) if using 
the newest compiler versions, pass the -i flag so the compiler 
will automatically include them for you.




Re: Imports

2017-10-05 Thread Ali Çehreli via Digitalmars-d-learn

On 10/05/2017 03:34 PM, Jiyan wrote:

> PS: is it spam to say thank you?

Thank you for asking! :p

I used to have strong feelings about this in the past. I still think 
it's spam; I don't expect any thanks from anyone and I think gratitude 
should be  implied.


Some people have different opinions: They say it makes them happy to see 
an explicit gratitude.


I don't care anymore especially because it's not very common anyway.

Ali



Re: Imports

2017-10-05 Thread Jiyan via Digitalmars-d-learn

On Thursday, 5 October 2017 at 12:35:26 UTC, Mike Parker wrote:

On Thursday, 5 October 2017 at 12:25:27 UTC, Mike Parker wrote:


[...]


Right. I had to go back and look at what I wrote in Learning D, 
which is the last (and only) time I played around with the 
default module behavior. I always use module statements (and 
you should too).


[...]


Thank you :)

PS: is it spam to say thank you?


Re: Imports

2017-10-05 Thread Mike Parker via Digitalmars-d-learn

On Thursday, 5 October 2017 at 12:25:27 UTC, Mike Parker wrote:



And actually, now that I think about it, this is probably one 
of those situations where the defualt fails. So yes, you'll 
need a module name.


Right. I had to go back and look at what I wrote in Learning D, 
which is the last (and only) time I played around with the 
default module behavior. I always use module statements (and you 
should too).


When you import dir.sub and the compiler finds it's missing in 
its imported module list, it will look in for the `dir/sub.d` 
from the current working directory. If it doesn't find it, you 
get an import error. If you do this:


dmd main.d ../dir/sub.d

Then sub.d can have any module statement you want -- you could do 
this:


module this.is.the.sub.module;

And it wouldn't matter, as long as main.d imported 
this.is.the.sub.module and not dir.sub. However, if sub.d has no 
module statement, the compiler isn't going to infer a package. 
It's going to be in the default package, so it's simply `sub` and 
not `dir.sub`. If you import dir.sub, the compiler will still 
look for a subdirectory named `dir`, but it won't find it.


This latter bit is your issue. dub is passing dir/sub.d to the 
compiler, but without a module statement the compiler treats it 
simply as `sub` and your `dir.sub` import fails.


Re: Imports

2017-10-05 Thread Mike Parker via Digitalmars-d-learn

On Thursday, 5 October 2017 at 12:18:57 UTC, Mike Parker wrote:

Regardless, every module should have a module name at the top. 
There are situations where the inferred package & module names 
can't work.


Ugh. Sorry, I mean for sourcePaths you have to pass `src` and 
not `dir`.


And actually, now that I think about it, this is probably one of 
those situations where the defualt fails. So yes, you'll need a 
module name.


Re: Imports

2017-10-05 Thread Mike Parker via Digitalmars-d-learn

On Thursday, 5 October 2017 at 12:17:23 UTC, Mike Parker wrote:

On Thursday, 5 October 2017 at 11:44:00 UTC, Jiyan wrote:

[...]


But as i see it with sourcePaths the directories are not 
influencing
the module names(in the directories except "source"), so 
"dir.sub"
will just have the name "sub" is there a way around that, 
except

naming every module like:

module dir.sub;


You have to pass the parent directory of dir rather than dir 
itself, e.g.:


- src
-- dir
--- sub.d

dmd -Isrc

Regardless, every module should have a module name at the top. 
There are situations where the inferred package & module names 
can't work.


Ugh. Sorry, I mean for sourcePaths you have to pass `src` and not 
`dir`.


Re: Imports

2017-10-05 Thread Mike Parker via Digitalmars-d-learn

On Thursday, 5 October 2017 at 11:44:00 UTC, Jiyan wrote:

[...]


But as i see it with sourcePaths the directories are not 
influencing
the module names(in the directories except "source"), so 
"dir.sub"

will just have the name "sub" is there a way around that, except
naming every module like:

module dir.sub;


You have to pass the parent directory of dir rather than dir 
itself, e.g.:


- src
-- dir
--- sub.d

dmd -Isrc

Regardless, every module should have a module name at the top. 
There are situations where the inferred package & module names 
can't work.


Re: Imports

2017-10-05 Thread Jiyan via Digitalmars-d-learn

On Thursday, 5 October 2017 at 00:28:32 UTC, Mike Parker wrote:

On Wednesday, 4 October 2017 at 16:31:35 UTC, Jiyan wrote:

[...]



If you have this directory tree:

- mylib
-- pack1
--- a.d
--- b.d
 pack2
- c.d

[...]


Thank you, i think i kinda got that :)

But as i see it with sourcePaths the directories are not 
influencing

the module names(in the directories except "source"), so "dir.sub"
will just have the name "sub" is there a way around that, except
naming every module like:

module dir.sub;


Re: Imports

2017-10-04 Thread Mike Parker via Digitalmars-d-learn

On Wednesday, 4 October 2017 at 16:31:35 UTC, Jiyan wrote:

Hey,

as i see it the -Ipath command for dmd just imports the files 
within a directory but it doesnt work for sub directories, so i 
can write something like:


import subdirectoryFromPath.file;

Also with dub this doesnt seem possible (sourcePaths seems to 
work as the -I command).


Is there a way to do what i want? Or am i doing something wrong?



If you have this directory tree:

- mylib
-- pack1
--- a.d
--- b.d
 pack2
- c.d

Then you would pass -Imylib to the compiler. In your code, you 
can write the following:


import pack1.a;
import pack1.pack2.c;

You don't import files or directories, just packages and modules. 
By default, package names correspond to directory names and 
module names correspond to file names, but they don't have to 
(it's best practice, though).


And by the way what is the difference from sourcePaths to 
importPaths?


sourcePaths where DUB can find additional files, outside of the 
default source directory, to pass to the compiler for 
compilation. importPaths will all be passed to the compile as -I. 
It seems you think that importing a module causes its source file 
to be automatically compiled. That doesn't happen.


imports are strictly for the compiler to know which symbols are 
available for the current module to use. It does not attempt to 
compile imported modules. Imported modules might be part of your 
program or they might be part of a precompiled library. In the 
latter case, they don't need to be compiled because they already 
are. So the compiler leaves it up to you to decide which modules 
need to be compiled.


Dub, by default, will make sure all modules in your source 
directory are compiled. It will also guarantee the compiler knows 
where to find them for imports. Sometimes, you might also want to 
import files from a library that isn't available from 
code.dlang.org. You can use importPaths to tell dub additional 
paths to give the compiler. If those files are part of a 
precompiled library you can link the library and you're done. If 
they aren't, you can use sourcePaths to tell DUB that all the 
source modules in the additional paths also need to be passed to 
the compiler for compiling and linking into the final executable.


Re: Imports incorrectly part of "allMembers" trait output?

2017-01-03 Thread ketmar via Digitalmars-d-learn

On Tuesday, 3 January 2017 at 06:23:01 UTC, bauss wrote:
It seems to be a bug that it takes std as there's no std as a 
part of object, not even as an import.


there is. think of it as "ephemeral namespace entity" (kind of 
alias to "name bin" that compiler created, the entity that 
exists, just has no corresponding D type). as i wrote ealier, it 
will be useful eventually to walk import chains in CTFE.


Re: Imports incorrectly part of "allMembers" trait output?

2017-01-03 Thread ketmar via Digitalmars-d-learn
given the way your code is written, "std" namespace *is* a 
member. it will be very useful when we'll fix other bugs and 
recursive `allMembers` scan will become possible. so while it 
came from namespaces implementation, i don't see this as a bug. 
it is little annoying, yes, 'cause you *have* to sort module ids 
out in your code. luckily, it is fairly easy, as module has no 
valid D type.


Re: Imports incorrectly part of "allMembers" trait output?

2017-01-02 Thread bauss via Digitalmars-d-learn

On Monday, 2 January 2017 at 18:56:40 UTC, Mike Bierlee wrote:

When compiling the following code with DMD 2.072.2:

class LeClass {
import std.stdio;
}

void main() {
foreach (memberName; __traits(allMembers, LeClass)) {
pragma(msg, memberName);
}
}

The following output is shown in the console:

std
toString
toHash
opCmp
opEquals
Monitor
factory

Note how "std" is part of the output of allMembers. Is this a 
bug or is this intended behavior? I don't think imports are 
necessarily members of a class. It also happens for static 
imports.


It seems to be a bug that it takes std as there's no std as a 
part of object, not even as an import.


However there is: __traits(derivedMembers, T) which should only 
give you members of your actual class and not anything inherited 
from base classes and/or object.


Re: imports && -run [Bug?]

2016-05-13 Thread zabruk70 via Digitalmars-d-learn

On Friday, 13 May 2016 at 06:33:40 UTC, Jacob Carlborg wrote:
Even better is to use "rdmd" which will automatically track and 
compile dependencies.


but i should warn about annoing bug with local import
http://forum.dlang.org/post/mailman.1984.1373610213.13711.digitalmar...@puremagic.com
https://issues.dlang.org/show_bug.cgi?id=7016


Re: imports && -run [Bug?]

2016-05-13 Thread Jacob Carlborg via Digitalmars-d-learn

On 2016-05-13 08:27, Andrew Edwards wrote:


I fail to see why the compiler would be less capable at this task than
rdmd. Since it is already build to accept multiple input files and knows
more about what's going on during compilation than rdmd will ever know,
in does not make sense that it should inferior in this regard: yet rdmd
takes one imput file and sorts out all dependencies.


There's no technical reason why the compiler is not doing this, as far 
as I know.


--
/Jacob Carlborg


Re: imports && -run [Bug?]

2016-05-13 Thread Jacob Carlborg via Digitalmars-d-learn

On 2016-05-13 08:10, tsbockman wrote:


According to the DMD compiler manual, the -run switch only accepts a
single source file:
 -run srcfile args...

After the first source file, any further arguments passed to DMD will be
interpreted as arguments to be passed to the program being run.


To elaborate, since the second file "inc" is not passed to the compiler, 
it will not compile that file, therefore you get linker errors. The 
solution is to pass all extra files before the -run flag.


Even better is to use "rdmd" which will automatically track and compile 
dependencies. Using rdmd it's enough to pass a single file to compile 
all dependencies and run the resulting binary: "rdmd mod".



Have you tried using DUB? It has lots of convenient features, including
a `run` command that supports multiple source files:
 http://code.dlang.org/docs/commandline#run


Dub is a great tool when a project grows larger than a few files.

--
/Jacob Carlborg


Re: imports && -run [Bug?]

2016-05-13 Thread Andrew Edwards via Digitalmars-d-learn

On 5/13/16 3:10 PM, tsbockman wrote:

On Friday, 13 May 2016 at 01:16:36 UTC, Andrew Edwards wrote:

command: dmd -run mod inc

output:

Undefined symbols for architecture x86_64:
  "_D3inc5printFZv", referenced from:
  __Dmain in mod.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
--- errorlevel 1

None of the variations of imports work when compiled with the -run
switch but all work perfectly well without it.


According to the DMD compiler manual, the -run switch only accepts a
single source file:
 -run srcfile args...

After the first source file, any further arguments passed to DMD will be
interpreted as arguments to be passed to the program being run.


Thanks, I guess I just expected it to work the same as rdmd does and 
didn't even bother trying to look in the manual regarding this.


I fail to see why the compiler would be less capable at this task than 
rdmd. Since it is already build to accept multiple input files and knows 
more about what's going on during compilation than rdmd will ever know, 
in does not make sense that it should inferior in this regard: yet rdmd 
takes one imput file and sorts out all dependencies.



Have you tried using DUB? It has lots of convenient features, including
a `run` command that supports multiple source files:
 http://code.dlang.org/docs/commandline#run


I've used dub before but it is not desired for what I'm trying to do. 
rdmd does the trick. Thank you.


Re: imports && -run [Bug?]

2016-05-13 Thread tsbockman via Digitalmars-d-learn

On Friday, 13 May 2016 at 01:16:36 UTC, Andrew Edwards wrote:

command: dmd -run mod inc

output:

Undefined symbols for architecture x86_64:
  "_D3inc5printFZv", referenced from:
  __Dmain in mod.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to 
see invocation)

--- errorlevel 1

None of the variations of imports work when compiled with the 
-run switch but all work perfectly well without it.


According to the DMD compiler manual, the -run switch only 
accepts a single source file:

-run srcfile args...

After the first source file, any further arguments passed to DMD 
will be interpreted as arguments to be passed to the program 
being run.


Have you tried using DUB? It has lots of convenient features, 
including a `run` command that supports multiple source files:

http://code.dlang.org/docs/commandline#run


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread bearophile

Jonathan:

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 can be shown with this function:

int*[] foo() {
int x;
int*[] arr = [x];
return arr;
}


Here the value 'x' is allocated on the stack, in the stack frame 
of the function foo(). arr is a heap-allocated array, so you can 
return it safely from foo. But arr contains a pointer to x, that 
points still to the stack frame of foo(). When foo() ends, the 
stack space used by the stack frame of foo gets reused for other 
purposes, so now the pointer inside the array arr points to data 
unrelated to the original x, essentially garbage.



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.


This is right. Bit the problem is different.


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


Right.



Is there an advantage to using auto?


It makes writing the code faster, the code less cluttered, and 
sometimes the type is obvious for the person that reads the 
code. Just don't abuse it.



I can't seem to put @safe: at the top of the file -- is it the 
same as compiling with -safe.  Is there a way to add this as a 
source annotation?


There is a writeln in the main, so you have to use:

void main(string[] args) @system {

But still the code doesn't compile:

temp.d(30): Error: field TermBody.terms cannot be accessed in 
@safe code because it overlaps with a pointer

...

So @safe can't be used here.



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


! is the not operator, but there it's used to instantiate a 
template.




What is the mixin bit doing?


It probably mixes-in (statically) some code generated at 
compile-time.



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


The book is useful if you want to get serious about learning D. 
Otherwise the online docs, Rosettacode and the book by a person 
that posts often in D.learn could suffice.



That is odd; I find that D shares a philosophy closer to 
Haskell than many of the lower level languages like C.


In D you can write functional-style code, look at Rosettacode D 
entries for many examples. (Also regarding your first post, D1 
language used to have literary programming built-in, as 
GHC-Haskell, but this feature was dropped in D2).




However, this is really *not* an algebraic type since sharing
is not algebraic,


If you share something that is immutable, and you assure there 
are no null pointers, then the fact that is shared is 
transparent, so why is it not algebraic?



 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.  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.  So 
using structs feel like a better fit.  Feel free to correct me 
here.  What are some of the drawbacks to using object.  How 
much more time overhead is there once the object is created?


Class instances have some overhead, +2 words of memory, plus a 
bit of time to initialize those fields. Class instances allocated 
on the heap are a bit simpler to use compared to structs handled 
by pointers.



You are right, I probably look like an idiomless noob!  I 
totally am!


Don't worry, you are going to learn.



(there is quite a lot of syntax in D).


D is a system language designed to be simpler to use, and it 
tries to be safer, and it tries to have many of the most useful 
tools. All this leads to a complex language. And the syntax 
reflects the varied semantics of all the things it contains. It's 
not just syntax sugar of the same bits of lambda calculus.



For now, can you tell me what I could do better about the 
switch statement


That switch can become an array. Or you can use enumerations with 
final switch, and so on.




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


D is a bit smarter than C, so term.node suffices.

Bye,
bearophile


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread Timon Gehr

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 

Re: imports and a data structure (any critique welcome)

2013-12-27 Thread bearophile

Timon Gehr:


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

void main(){
const expr = Op('f', [Op('g',[Var('x'), Var('y')]), 
Op('a',[]), Var('x')]);

}


Where is ADT defined? (And why isn't it a Phobos patch on GitHub?)



convertNum could be written more compactly as:
char convertNum(int x){
return exyzfgh[x$?x:0];


That's too much compact :-) Humans put a space around operators, 
and sometimes some parentheses don't hurt:


char convertNum(in int x) pure nothrow
in {
assert(x = 0);
} body {
return exyzfgh[(x  $) ? x : 0];
}

Bye,
bearophile


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread Marco Leise
Am Fri, 27 Dec 2013 13:45:10 +
schrieb bearophile bearophileh...@lycos.com:

 Timon Gehr:
 
  mixin ADT!q{ Term: Var char | Op char Term[] };
 
  void main(){
  const expr = Op('f', [Op('g',[Var('x'), Var('y')]), 
  Op('a',[]), Var('x')]);
  }
 
 Where is ADT defined? (And why isn't it a Phobos patch on GitHub?)
 
 
  convertNum could be written more compactly as:
  char convertNum(int x){
  return exyzfgh[x$?x:0];
 
 That's too much compact :-) Humans put a space around operators, 
 and sometimes some parentheses don't hurt:
 
 char convertNum(in int x) pure nothrow
 in {
  assert(x = 0);
 } body {
  return exyzfgh[(x  $) ? x : 0];
 }
 
 Bye,
 bearophile

Before you go _that_ far, just write:

  char convertNum(in size_t x) pure nothrow
  {
  return exyzfgh[(x  $) ? x : 0];
  }

:-)

-- 
Marco



Re: imports and a data structure (any critique welcome)

2013-12-27 Thread Timon Gehr

On 12/27/2013 02:45 PM, bearophile wrote:

Timon Gehr:


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

void main(){
const expr = Op('f', [Op('g',[Var('x'), Var('y')]), Op('a',[]),
Var('x')]);
}


Where is ADT defined?


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


(And why isn't it a Phobos patch on GitHub?)
...


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


That's too much compact :-)  Humans put a space around
operators,


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



and sometimes some parentheses don't hurt:


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


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread Jonathan
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 ...


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread TheFlyingFiddle

On Friday, 27 December 2013 at 00:23:58 UTC, Jonathan wrote:
I come from Haskell, so please excuse any functional 
programming idiosyncracies I have :)


In Haskell, I have a datatype for representing so called terms 
which looks like:


data Term = Var Char | Op Char [Term]

i.e. a Term is a variable (denoted by an Int) or an operation 
(whose name is also denoted by an int), applied to a list of 
its arguments.  For example,


f(g(x,y),a(),x) is represented by Op 'f' [Op 'g' [Var 
'x',Var 'y'],Op 'a' [], Var 'x]


Now, the reason I am writing in D is twofold.  First, I want to 
learn the D language, and second I really need pointers to 
reduce certain complexities in the operations (Haskell does not 
have observable sharing).


Could you please clarify the question? I did not understand what 
you wanted to ask.


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread TheFlyingFiddle

Found your other post nwm.


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread bearophile

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


Re: imports and a data structure (any critique welcome)

2013-12-27 Thread Timon Gehr

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.)




Re: imports and a data structure (any critique welcome)

2013-12-27 Thread John Colvin

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.


Re: imports and a data structure (any critique welcome)

2013-12-26 Thread Timon Gehr

On 12/27/2013 01:40 AM, Jonathan wrote:


Term makeExTerm(){
 Term var1 = Term(1);//x
 Term var2 = Term(2);//y
 Term var3 = Term(3);//z
 Term fxx = Term(4, [var1,var1]);//f(x,x)
 Term gfxxy = Term(5, [fxx,var2]);//g(f(x,x),y)
 Term hzg = Term(6, [gfxxy,gfxxy]);//h(g(f(x,x),y),g(f(x,x),y))
 return hzg;
}

Using the above, I wrote a test program,
...

Can anyone tell me what is going on?


You are taking the address of stack-allocated variables. [1]
Accessing the terms after the function has returned results in undefined 
behaviour. In the case where it worked you just were lucky.


You may allocate your terms on the heap using 'new':
---
Term* makeExTerm(){
auto var1 = new Term(1);//x
auto var2 = new Term(2);//y
auto var3 = new Term(3);//z
auto fxx = new Term(4, [var1,var1]);//f(x,x)
auto gfxxy = new Term(5, [fxx,var2]);//g(f(x,x),y)
auto hzg = new Term(6, [gfxxy,gfxxy]);//h(g(f(x,x),y),g(f(x,x),y))
return hzg;
}

void main(string[] args){
auto exTerm = makeExTerm();
string printable = termToString(exTerm);
writeln(printable);
exTerm.term.terms.Subterms[0].term.terms.Subterms[0] = new Term(219);
// it is now  (and should be) h(g(e,y),g(e,y))
string printable2 = termToString(exTerm);
writeln(printable2);
}
---

prints:
---
h(g(f(x,x),y),g(f(x,x),y))
h(g(e,y),g(e,y))
---

[1] This would be disallowed in the memory safe subset. You might want 
to put '@safe:' on top of your files.


Re: imports and a data structure (any critique welcome)

2013-12-26 Thread bearophile

Jonathan:

I come from Haskell, so please excuse any functional 
programming idiosyncracies I have :)


Welcome. You are the first Haskell programmer that I know willing 
to learn and try D :-)



In Haskell, I have a datatype for representing so called terms 
which looks like:


data Term = Var Char | Op Char [Term]

i.e. a Term is a variable (denoted by an Int) or an operation 
(whose name is also denoted by an int), applied to a list of 
its arguments.  For example,


f(g(x,y),a(),x) is represented by Op 'f' [Op 'g' [Var 
'x',Var 'y'],Op 'a' [], Var 'x]


In almost-theory D should allow code like:


import std.stdio, std.typecons, std.variant;

alias Term = Algebraic!(string, Tuple!(string, This[]));

void main() {
const expr = Term(tuple(f, [Term(tuple(g, [x.Term, 
y.Term])), Term(tuple(a, [])), x.Term]));

}


In practice std.variant module needs a This defined as struct 
This {}, plus another improvement to support recursive types 
better, so that code doesn't work.


That code also can't work because the second type of the 
tuple(a, []) literal is void[], so it's not compatible.


I am not sure a good enough library-defined Algebraic type can be 
defined.



Okay, so the first thing I need to do is represent this as a 
data structure in D.  My choices are to represent the structure 
as a class or as a struct.  I choose struct because it is 
simpler (in terms of what is going on), and because the entire 
program takes one struct and makes changes to it.


Raw pointers are like razors, they can be useful, but they should 
must also handled with a good amount of discipline and safeties 
added by you and your experience, otherwise you cut yourself 
often.


For a first version of your code you can try to use class 
instances instead, that are easer to handle (especially in 
garbage-collected language. But don't forget to add to functions 
all the pre-conditions to assert the class references are not 
null).


I see tons of things that can be improved in your code. Like the 
switch, (*term).node, the lack of immutable/const/pure/nothrow 
(you should be able to write good enough functional code in D), 
but better to think about the larger things first.


Bye,
bearophile


Re: imports and a data structure (any critique welcome)

2013-12-26 Thread Timon Gehr

On 12/27/2013 02:49 AM, bearophile wrote:


In almost-theory D should allow code like:


import std.stdio, std.typecons, std.variant;

alias Term = Algebraic!(string, Tuple!(string, This[]));

void main() {
 const expr = Term(tuple(f, [Term(tuple(g, [x.Term,
y.Term])), Term(tuple(a, [])), x.Term]));
}


In practice std.variant module needs a This defined as struct This {},
plus another improvement to support recursive types better, so that code
doesn't work.

That code also can't work because the second type of the tuple(a,
[]) literal is void[], so it's not compatible.

I am not sure a good enough library-defined Algebraic type can be defined.


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

void main(){
const expr = Op('f', [Op('g',[Var('x'), Var('y')]), Op('a',[]), 
Var('x')]);

}


Re: imports and a data structure (any critique welcome)

2013-12-26 Thread Jonathan

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?  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).


Does auto do a simple type inference to find out that Term* 
should be there?  Is there an advantage to using auto?


I can't seem to put @safe: at the top of the file -- is it the 
same as compiling with -safe.  Is there a way to add this as a 
source annotation?


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

What is the mixin bit doing?  Can you point me towards any 
tutorials, or should I buy the book?


@bearophile:
Thank you for the welcome.  That is odd; I find that D shares a 
philosophy closer to Haskell than many of the lower level 
languages like C.


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.  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.  So using structs feel 
like a better fit.  Feel free to correct me here.  What are some 
of the drawbacks to using object.  How much more time overhead is 
there once the object is created?


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 and what is wrong with (*term).node?