Thread overview
how to implement a function in a different D source file
Nov 26, 2019
Omar
Nov 26, 2019
mipri
Nov 26, 2019
mipri
Nov 26, 2019
Mike Parker
Nov 26, 2019
Elronnd
Nov 27, 2019
Omar
Nov 28, 2019
Paul Backus
Nov 30, 2019
Omar
November 26, 2019
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 ?
November 26, 2019
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


November 26, 2019
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

November 26, 2019
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.
November 26, 2019
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.
November 27, 2019
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 +/

November 28, 2019
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
November 30, 2019
ok, thanks for the replies everyone !

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