Difference between revisions of "Programming in D for Java Programmers"

From D Wiki
Jump to: navigation, search
(Downcasting)
 
(Hello world example)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
== Hello World ==
 +
 +
Assuming you've [https://dlang.org/download.html downloaded a D compiler], a basic "hello world" program will look like this:
 +
 +
<syntaxhighlight lang="D" line>// hello.d
 +
import std.stdio;
 +
 +
void main(string[] args)
 +
{
 +
  writeln("Hello, world!");
 +
}</syntaxhighlight>
 +
 +
If you're using [[DMD]], you can run <code>dmd -run hello.d</code> to compile and execute the program.
 +
 +
There are two main differences from a [https://en.wikipedia.org/wiki/Java_(programming_language)#Hello_world_example "hello world" in Java].  First, there is no need for a <code>class</code>. In D, functions can exist at the top-level, inside a <code>class</code> or <code>struct</code> as a method, and even inside another function.  The only requirement (without abusing features of D) is that the <code>main</code> function is located at the top-level.
 +
 +
This isn't the only way to define <code>main</code>; the following will work as well:
 +
 +
* <syntaxhighlight lang="D" inline>void main() {}</syntaxhighlight>
 +
* <syntaxhighlight lang="D" inline>int main() { return 0; }</syntaxhighlight>
 +
* <syntaxhighlight lang="D" inline>int main(string[] args) { return 0; }</syntaxhighlight>
 +
 +
Using <code>void</code> as the return type means a successful run of the program exits with <code>0</code><ref>https://dlang.org/spec/function.html#main</ref>.
 +
 
== Downcasting ==
 
== Downcasting ==
 
The Java way
 
The Java way
Line 12: Line 36:
 
     /* use cat */
 
     /* use cat */
 
}</syntaxhighlight>
 
}</syntaxhighlight>
 +
 +
== Static Class Member Variables ==
 +
 +
In Java if you declare a member variable as <code>static</code> it will be stored in global storage for the entire program, allowing you to access the same reference from multiple threads.
 +
 +
<syntaxhighlight lang="Java" line>
 +
class Person {
 +
  public String firstName;
 +
 +
  public Person(String fname) {
 +
      this.firstName = fname;
 +
  }
 +
}
 +
 +
class ProgramState {
 +
  public static Person person;
 +
 +
  static {
 +
      person = new Person("Jessie");
 +
  }
 +
}
 +
 +
public class Program {
 +
 +
  public static void main(String[] args) throws Exception {
 +
      new ProgramState();
 +
      Thread secondThread = new Thread(new Runnable() {
 +
        @Override
 +
        public void run() {
 +
            ProgramState.person.firstName = "James";
 +
        }
 +
      });
 +
      System.out.println(ProgramState.person.firstName); // => Jessie
 +
      secondThread.start();
 +
      secondThread.join();
 +
      System.out.println(ProgramState.person.firstName); // => James
 +
  }
 +
}</syntaxhighlight>
 +
 +
A <code>static</code> member variable in D is local to the ''current thread only'', known as thread-local storage. Every thread you create will have a different version of your <code>static</code> member variables.
 +
To have the same behaviour as Java in D, you need to use the <code>__gshared</code> type qualifier.
 +
 +
<syntaxhighlight lang="D" line>import core.thread;
 +
 +
class Person
 +
{
 +
  string firstName;
 +
 +
  this(string fname) {
 +
      firstName = fname;
 +
  }
 +
}
 +
 +
class ProgramState
 +
{
 +
  __gshared static Person person;
 +
 +
  static this()
 +
  {
 +
      person = new Person("Jessie");
 +
  }
 +
}
 +
 +
void main()
 +
{
 +
  new ProgramState();
 +
  Thread secondThread = new Thread(() {
 +
      ProgramState.person.firstName = "James";
 +
  });
 +
  assert("Jessie" == ProgramState.person.firstName);
 +
  secondThread.start();
 +
  secondThread.join();
 +
  assert("James" == ProgramState.person.firstName, "firstName is not James");
 +
}</syntaxhighlight>
 +
 +
Removing the <code>__gshared</code> from the above snippet will result in the second assertion failing as <code>ProgramState.person.firstName</code> will be <code>"Jessie"</code>.
 +
 +
For an overview of the different forms of concurrency, see the [https://ddili.org/ders/d.en/concurrency_shared.html Data Sharing Concurrency] chapter in ''Programming in D'' which also explains one of D's preferred way of sharing variables between threads: <code>shared</code>.
 +
 +
== References ==
 +
 +
<references />
 +
 +
[[Category:Languages versus D]]

Latest revision as of 06:08, 27 August 2023

Hello World

Assuming you've downloaded a D compiler, a basic "hello world" program will look like this:

1 // hello.d
2 import std.stdio;
3 
4 void main(string[] args)
5 {
6    writeln("Hello, world!");
7 }

If you're using DMD, you can run dmd -run hello.d to compile and execute the program.

There are two main differences from a "hello world" in Java. First, there is no need for a class. In D, functions can exist at the top-level, inside a class or struct as a method, and even inside another function. The only requirement (without abusing features of D) is that the main function is located at the top-level.

This isn't the only way to define main; the following will work as well:

  • void main() {}
  • int main() { return 0; }
  • int main(string[] args) { return 0; }

Using void as the return type means a successful run of the program exits with 0[1].

Downcasting

The Java way

if (animal instanceof Cat)
{
    Cat cat = (Cat) animal;
    /* use cat */
}

The D way

if(auto cat = cast(Cat) animal)
{
    /* use cat */
}

Static Class Member Variables

In Java if you declare a member variable as static it will be stored in global storage for the entire program, allowing you to access the same reference from multiple threads.

 1 class Person {
 2    public String firstName;
 3 
 4    public Person(String fname) {
 5       this.firstName = fname;
 6    }
 7 }
 8 
 9 class ProgramState {
10    public static Person person;
11 
12    static {
13       person = new Person("Jessie");
14    }
15 }
16 
17 public class Program {
18 
19    public static void main(String[] args) throws Exception {
20       new ProgramState();
21       Thread secondThread = new Thread(new Runnable() {
22          @Override
23          public void run() {
24             ProgramState.person.firstName = "James";
25          }
26       });
27       System.out.println(ProgramState.person.firstName); // => Jessie
28       secondThread.start();
29       secondThread.join();
30       System.out.println(ProgramState.person.firstName); // => James
31    }
32 }

A static member variable in D is local to the current thread only, known as thread-local storage. Every thread you create will have a different version of your static member variables. To have the same behaviour as Java in D, you need to use the __gshared type qualifier.

 1 import core.thread;
 2 
 3 class Person
 4 {
 5    string firstName;
 6 
 7    this(string fname) {
 8       firstName = fname;
 9    }
10 }
11 
12 class ProgramState
13 {
14    __gshared static Person person;
15 
16    static this()
17    {
18       person = new Person("Jessie");
19    }
20 }
21 
22 void main()
23 {
24    new ProgramState();
25    Thread secondThread = new Thread(() {
26       ProgramState.person.firstName = "James";
27    });
28    assert("Jessie" == ProgramState.person.firstName);
29    secondThread.start();
30    secondThread.join();
31    assert("James" == ProgramState.person.firstName, "firstName is not James");
32 }

Removing the __gshared from the above snippet will result in the second assertion failing as ProgramState.person.firstName will be "Jessie".

For an overview of the different forms of concurrency, see the Data Sharing Concurrency chapter in Programming in D which also explains one of D's preferred way of sharing variables between threads: shared.

References