www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to implement a function in a different D source file

reply Omar <zelux gmx.us> writes:
Hey, I'm very interested in this programming language, I already 
prefer it to C++ and if only i had adopted it years ago, but 
that's beside the point.

I read a bunch of tuts today and the only thing I'm really stuck 
on at the moment is how to actually implement a function in a 
different file.

the page here https://dlang.org/spec/function.html
suggests you can implement a function in a different file, and a 
different tutorial somewhere else (or maybe the same site or even 
same page idr) mentioned the endeavour of no-bodied-functions as 
a way of presenting a black-box type of interface.

But with the whole module namespace thing I'm a bit at a loss how 
to do this.
Say I have main.d ex.d and ex2.d and I want to import ex, and 
call a function it
declares, and implement the function in ex2.d and link the 
objects at the end so the linker is happy. I don't know how to do 
this and I can't find a straigh answer anywhere or any examples.

so ?
Nov 25 2019
next sibling parent mipri <mipri minimaltype.com> writes:
On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote:
 Hey, I'm very interested in this programming language, I 
 already prefer it to C++ and if only i had adopted it years 
 ago, but that's beside the point.

 I read a bunch of tuts today and the only thing I'm really 
 stuck on at the moment is how to actually implement a function 
 in a different file.

 the page here https://dlang.org/spec/function.html
 suggests you can implement a function in a different file, and 
 a different tutorial somewhere else (or maybe the same site or 
 even same page idr) mentioned the endeavour of 
 no-bodied-functions as a way of presenting a black-box type of 
 interface.

 But with the whole module namespace thing I'm a bit at a loss 
 how to do this.
 Say I have main.d ex.d and ex2.d and I want to import ex, and 
 call a function it
 declares, and implement the function in ex2.d and link the 
 objects at the end so the linker is happy. I don't know how to 
 do this and I can't find a straigh answer anywhere or any 
 examples.

 so ?
First, here's exactly what you're asking for: $ cat ex1.d enum string admin = "Dave"; $ cat ex2.d import ex1; string greeting() { return "Hello, " ~ admin; } $ cat main.d import ex2; void main() { import std.stdio: writeln; writeln(greeting); } Three files that all import what they need, and can be compiled separately and then linked. $ dmd -c ex1 $ dmd -c ex2 $ dmd -c main $ dmd -ofmain main.o ex2.o ex1.o $ ./main Hello, Dave And dmd isn't cheating, as you can see by skipping the first two compiles: $ rm *.o $ dmd -c main $ dmd -ofmain main.o /usr/bin/ld: main.o: in function `_Dmain': main.d:(.text._Dmain[_Dmain]+0x5): undefined reference to `_D3ex28greetingFZAya' collect2: error: ld returned 1 exit status Error: linker exited with status 1 But you could also just compile everything together: $ rm *.o $ dmd -ofmain *.d $ ./main Hello, Dave If all of your code is in D, my received understanding is that this is a completely reasonable option. You could also use dub as your build system: Package recipe format (sdl/json) [json]: Name [main]: Description [A minimal D application.]: Author name [mipri]: License [proprietary]: MIT Copyright string [Copyright © 2019, mipri]: Add dependency (leave empty to skip) []: This'll create a new directory named 'main', and you can build and run a 'hello world' by running 'dub'. After moving some files around... $ cat source/movie/references/names.d module movie.references.names; enum string admin = "Dave"; $ cat source/movie/references/lines.d module movie.references.lines; string cantDoThat() { import movie.references.names: admin; return "I'm afraid I can't do that, " ~ admin; } $ cat source/app.d void main() { import movie.references.lines: cantDoThat; import std.stdio: writeln; writeln(cantDoThat); } Building and running it: $ dub Performing "debug" build using dmd for x86_64. main ~master: building configuration "application"... Linking... Running ./main I'm afraid I can't do that, Dave
Nov 25 2019
prev sibling next sibling parent reply mipri <mipri minimaltype.com> writes:
On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote:
 the page here https://dlang.org/spec/function.html
 suggests you can implement a function in a different file
...
 mentioned the endeavour of no-bodied-functions as a way of 
 presenting a black-box type of interface.
oh, that's what you were asking. Consider: $ cat interface/references.d module references; string greeting(); $ cat implementation/references.d module references; string greeting() { return "Hello, Dave"; } $ cat main.d import references; void main() { import std.stdio: writeln; writeln(greeting); } And trying to build it: $ dmd -c implementation/references.d $ dmd -Iinterface -c main.d $ dmd main.o references.o $ ./main Hello, Dave
Nov 25 2019
parent Mike Parker <aldacron gmail.com> writes:
On Tuesday, 26 November 2019 at 03:55:24 UTC, mipri wrote:
 On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote:
 the page here https://dlang.org/spec/function.html
 suggests you can implement a function in a different file
...
 mentioned the endeavour of no-bodied-functions as a way of 
 presenting a black-box type of interface.
oh, that's what you were asking. Consider: $ cat interface/references.d module references; string greeting(); $ cat implementation/references.d module references; string greeting() { return "Hello, Dave"; } $ cat main.d import references; void main() { import std.stdio: writeln; writeln(greeting); } And trying to build it: $ dmd -c implementation/references.d $ dmd -Iinterface -c main.d $ dmd main.o references.o $ ./main Hello, Dave
The idiomatic way to do that is to put the interface in a "D interface" file (.di) and the implementation in a .d file: foo/bar.di foo/bar.d Then, when importing foo.bar, the compiler will pick up the .di file automatically. And you can actually have the compiler generate the interface file for you from a source file with the -H option.
Nov 25 2019
prev sibling parent reply Elronnd <elronnd elronnd.net> writes:
On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote:
 the page here https://dlang.org/spec/function.html
 suggests you can implement a function in a different file, and 
 a different tutorial somewhere else mentioned the endeavour of 
 no-bodied-functions as a way of presenting a black-box type of 
 interface.
This is not a common pattern in d; the only reason it's used in c and c++ is that those languages don't have a real module system. However, the way it's done is with .di (d interface) files. Consider: test.di: module test; void print_stuff(); main.d: import test; void main() { print_stuff(); } test.d: module test; void print_stuff() { import std.stdio; writeln("I'm stuff"); } You can verify the compiler is reading from test.di by putting test.d in a different directory from main.d and test.di.
Nov 25 2019
parent reply Omar <zelux gmx.us> writes:
Oh I see, it seems like the answers I'm getting imply that you 
have the option of a pure interface or pure implementation but not
a mix. I see how I could elaborate more on what I was asking 
about.

As long as you only import the file but not try to compile the 
same module twice right ?
So just to be clear, in D you can't do something like.

/+ a.d +/
void func1 () { /+ do stuff +/ }
void func2 () { /+ do stuff +/ }
void func3 () ;

/+ b.d +/
void func_x1 () { /+ do stuff +/   }
void func3   () { /+ true stuff +/ }

this forks into a second question but I think still fits this 
thread as it could just be seen as another form of the same 
question.
Is there a way to define some functions in the body of a class 
definition, and define others outside of it in other places in the
source file ?
example

/+ top.d +/
import stuff = other_stuff ;

class system {
     int           a,b,c,d ;
     float         x,y,z   ;
     stuff.struct1 p,i,e   ;
     stuff.struct2 l,t,v   ;

     int           test           (int      CMD) { /+ do stuff +/ }
     int           maintenance    (stuff.struct) { /+ do stuff +/ }
     int           connect        ()                     ;
     stuff.struct3 eval           (stuff.op[] pipeline)  ;
     void          reset          (int node)             ;
     void          save           (stuff.struct_x state) ;
     void          exportFile     (string name)          ;
     void          loadFromStream ()                     ;
     void          loadFromFile   ()                     ;
}

/+ implement those 7 functions here or in other files +/
Nov 27 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 27 November 2019 at 23:32:34 UTC, Omar wrote:
 this forks into a second question but I think still fits this 
 thread as it could just be seen as another form of the same 
 question.
 Is there a way to define some functions in the body of a class 
 definition, and define others outside of it in other places in 
 the
 source file ?
No, there isn't. You have to define all of a class's methods in the class body. However, you can define free functions that can be called with the same syntax as methods using UFCS [1]. For example: import std.stdio; class C { void foo() { writeln("foo"); } } void bar(C c) { writeln("bar"); } void main() { C c; c.foo(); c.bar(); } The main limitation is that, because `bar` is really a free function and not a method, it will not be inherited by C's child classes, and therefore cannot be overridden. [1] https://dlang.org/spec/function.html#pseudo-member
Nov 27 2019
parent Omar <zelux gmx.us> writes:
ok, thanks for the replies everyone !

I think i might try fiddling around with mixins and see how i 
like that.
Nov 30 2019