A Beginner's Crash Course on Dlang
A Beginner's Crash Course on Dlang
Unfortunately for us, it is hard to make a D repl. Luckily, @CodeLongAndPros and @StudentFires released a template for D repls. The example at the bottom uses the Dlang template.
This tutorial will give you the basics of D in one place.
I will be improving this tutorialta over time.
Also, I will be referring to Dlang as it's shorter term, D throughout this crash Course.
C# Dash tutorials
- Level 1 - Object Oriented Madness
- Level 2 - Math on Track
- Level 3 - Conditionalgeist
- Level 4 - Dry Methods
Scratch Tutorials
- Tutorial 1 - Introduction
- Tutorial 1.5 - Advice
- Tutorial 2 - Motion and Events blocks
- Tutorial 3 - Looks and Sound blocks
Change log (since posting)
NOTE: This does not count minor changes.
- Somewhere around Aug. 3-4, 2020: Fixed some typos, made a Unicode in D section, and updated the section on Classes.
- Aug. 6, 2020: Added a section on exception handling.
- Aug. 6, 2020: Split the "Important data types and variables" section into two sections.
- Aug. 7, 2020: Added a section on imports.
- Aug. 7, 2020: Updated the operators section and added a section on structs
- Aug. 19, 2020: Added a thing on loop labels to the Loops section
- Sep. 4, 2020: Changed name from "A Crash Course on Dlang" to "A Beginner's Crash Course on Dlang"
Anyways...
LET'S GET STARTED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
THE FIRST D TUTORIAL ON REPL.IT (over 600 lines of markdown)!!!!!
Basic Info
Thanks to @StudentFires for suggesting somethings to say here.
- D is a programming language that is similar to C and C++
- Full Unicode support
- Every regular line must end with a semicolon (unless, of course, it's just braces for functions and stuff)
- File extension is
.d
- Compiled language
- Multi-paradigm
- Garbage collected (similar to java)
- Has the signature sonic-the-hedgehoglike speed of C and C++ (slower unfortunately), except it's way easier to use
Image from dlang.org.
Image from tour.dlang.org.
Comments
A single line comment in D starts with //
. Multi line comments start with /*
and end with */
// Single line comment Anything after the // on the same line is not run. /* Multiline comment. Extends over multiple lines duh. You can use these to make code not run without deleting it. These are really cool. But it must always end with: */
How and when to use comments depend on who you ask. I say to use single line comments to sort of divide your code into sections and to use multiline comments to prevent errory/buggy code from being run. But it's your choice on how to use comments or to use them at all.
Companies usually put comments at the top of a file for copyright notices.
Hello World!
, Your first D program
You all know programming tradition.
We usually print something similar to Hello World!
in the console.
I follow programming tradition in this tutorial
To print something to the console, we use writeln
. Here is an example:
import std.stdio: writeln; void main() { writeln("Hello World!"); } /* The code above outputs the following: Hello World! */
Let's break that down.
The import
statement, in this case, imports writeln
from std.stdio
. You can have import statements anywhere in your code, but it's recommended that you have them at the top of the file.
void main()
acts as an entry point for the program
writeln
will print something to the console.
You also have write
that does not have any newlines.
Example:
import std.stdio: write; void main() { write("Now "); write("goodbye world..."); } /* The code above outputs the following: Now goodbye world... */
You also can print multiple things, including variables (explained later.)
Basic Data types
There are tons of data types in D, here are some basic ones:
bool
- A boolean value (either true or false)int
- A signed 32-bit integral valuefloat
- 32-bit floating point valuedouble
- 64-bit floating point valuechar
- UTF-8 code unit (character)
NOTE: String is a special array type. You can learn more about them here.
Variables
Variables are values stored under a name. Like C, C++, and C#, you have to define the data type for the variable.
It follows the following order:
<data_type> <variable_name> = <value>; // You can also define variables to be used later <data_type> <variable_name>;
Example:
int variable = 5;
Follow these rules when naming variables
- NEVER put spaces in variable names
- The variable name cannot start with a number
- Don't make it a D keyword
- Besides numbers and letters, only put underscores in variable names.
readln
, Capture user input
If you want to make your program interactive, then use readln
.
You usually store it in a string
variable.
Example:
import std.stdio: writeln, readln; // Yes, you can import multiple things easily by using a comma in between functions void main() { writeln("Enter your name."); string name = readln(); // Don't forget that you can print multiple things, including non-string and non-char variables, with a comma. writeln("Your Sithlord name is:\n\nDarth ", name); } /* Sample Output: Enter your name. Link Your Sithlord name is: Darth Link */
This is making good use of the string
type.
Arrays
Arrays are basically variables that store multiple pieces of data.
Each piece of data in an array is an index
. Indices start at zero and the index number increases by one for each index. That's how you can tell different pieces of data in an array apart.
There are two kinds of arrays, static and dynamic.
Static arrays
Static arrays cannot be changed.
This can be used as a list for every possible item that can be in the inventory
They are created like the following:
string every_item[5] = ["sword", "dagger", "shield", "healing potion", "poison bottle"]; // You can also print them like following writeln("Last of possible items are: ", every_item[4]); /* The code above outputs the following: Last of possible items are: poison bottle */
The array is static if you have a length inside the brackets
Dynamic arrays
Dynamic arrays can be changed after being run.
You can make one by removing the array length.
It's handy for a game inventory.
Example:
string inventory[] = ["sword", "shield", "healing potion"]; writeln("You have:\n", inventory[]); /* The code above outputs the following: You have: ["sword", "shield", "healing potion"] */
Those were one dimensional arrays. Now, I present to you multidimensional arrays...
What the h*** are multidimensional arrays?
D supports arrays in multiple dimensions.
Here, I will be discussing two dimensional arrays.
Two dimensional arrays are basically arrays with one-dimensional arrays
Think of a table (document kind not lua-version-of-array kind.)
Notice how tables have rows and columns?
Well that's basically what a two dimensional array is.
Look at the following table:
---------------- | 27 | 48 | 21 | ---------------- | 76 | 32 | 12 | ----------------
Well, let's organize that into a two dimensional array.
The syntax for a two dimensional array:
int twodee[<rows>][<columns>] = [ [/*add a value for each column in each row.*/]// Don't forget a comma at the end of a row that's not the last row. //do this for each row ]; //don't forget the semicolon
Anyways, let's look at what a two dimensional array version of that table would look like:
int table[2][3] = [ [27, 48, 21], [76, 32, 12] ];
This is pretty handy for a 2D platformer game.
Slices
One of the most pleasant features of the D language is its implementation of slices. Every time I use a programming language that isn't D, I find myself lamenting for D's slice syntax. Not only is it concise and efficient, but things 'just work' when you are dealing with slices.
Steven Schveighoffer, D Slices
This is a really good feature of D, slices.
Slices are little parts of an array stored in a new array.
They have the following syntax:
<data type>[] <slice_name> = [<first_value_in_new_array>..<first_value_NOT_in_new_array>];
Here is an example with the with a slice from the inventory example:
string[] part_of_inventory = inventory[1..3]; writeln(part);
Operators
The operators you would need are as following :
================================ ARITHMETIC ================================ + | Addition - | Subtraction * | Multiplication / | Division % | Division but returns the remainder of integral quotient ++ | Increment -- | Decrement NOTE: Put an increment/decrement before the variable to increase the value before the result is assigned. ================================ ARITHMETIC ASSIGNMENT ================================ += | Adds something to a certain value, then saves the result to variable -= | Subtracts something from a certain value, then saves the result to a variable *= | Multiplies something by a certain value, then saves the result to a variable /= | Divides something by a certain value, then saves the result to a variable %= | Divides something by a certain value, then saves the remainder to a variable ================================ COMPARING ================================ == | Equal to != | Not equal to > | greater than >= | greater than or equal to < | less than <= | less than or equal to is | has identity !is | doesn’t have identity NOTE: is and !is can be used to check whether a variable is null ================================ BOOLEAN LOGIC ================================ && | boolean AND || | boolean OR ! | boolean NOT.
Control flow
For now, our programs execute every line of code. That is impractical (unless you're recreating scratch animations in D.) So let's give our programs some conditional statements and loops.
if
, else if
, and else
- The most basic conditionals
if
, else if
, and else
are basic, but a fundamental part of programming. They can be seen in almost all programs, so you have to learn them.
**WARNING: **You need to import
strip
fromstd.string
to be able to compare strings from `readln.
if
statements start a block of code that only executes if the condition is true.
Example:
if (<condition evaluated>) { }
When you need to have multiple conditionals, you use else if
Here is an example:
import std.stdio: writeln, write, readln; import std.string: strip; void main() { writeln("Is quarantine boring? (y/n)"); string answer = strip(readln()); if (answer == "y" || answer == "Y") { writeln("Yep, you're right."); } else if (answer == "n" || answer == "N") { writeln("Well, good for you. Hope you have fun stuff to do while the rest of us be bored!"); } else { writeln("I don't understand that."); } } /* Sample output: Is quarantine boring? (y/n) y Yep, you're right */
Switch
statements, short conditions for one variable
Sometimes, regular conditionals can be impractical if:
- they're based on the same variable.
- there's a ton of them.
Introducing...
...switch
statements!
Switch statements have case
s, or stuff to execute if the statement is true.
They also need a default
case if none of the other cases are executed.
Every case ends with break
to stop it.
Here is the basic syntax:
switch (<variable>) { case case1: // add code here break; case case2: // add code here break; default: // add code here break; }
There's also goto
, which can be used to go to different cases.
There are three basic uses of goto
in switch statements:
goto case
- Goes to the next casegoto case (case_value)
- Goes to the case with that valuegoto default
- Goes to the default case
NOTE: You do not need to include a
break;
if you have a goto.
goto
s are also considered bad practice among most programmers, but sometimes they are an easy way to solve a problem. But be careful:
So now that you understand the syntax, let's look at a switch statement version of the above example:
import std.stdio: writeln, write, readln; import std.string: strip; void main() { writeln("Is quarantine boring? (y/n)"); string answer = strip(readln()); switch (answer) { case "y": writeln("Yep, you're right."); break; case "Y": goto case "y"; case "n": writeln("Well, good for you. Hope you have fun stuff to do while the rest of us be bored!"); break; case "N": goto case "n"; default: writeln("I don't understand that."); } }
Loops
Wanna repeat a bunch of code without having to copy and paste a ton?
Then use loops. They repeat code until a condition is false.
Loop keywords
There are two main loop keywords, continue
and break
continue
will immedietely continue to the next iteration of the loop
break
will stop the loop
while
loops
while
loops check if the condition is true. If it's true, then it executes the code inside the braces.
Example:
int counter = 0; while (true) { writeln(counter); counter++; if (counter >= 1000) { break; } } // This loop will iterate about 1000 times, printing numbers 0-999. When it is equal to or greater than 1000, the loop stops
do-while
loop
When using a regular while
loop, it's possible the loop will never iterate.
So you have the do-while
loop that checks the condition when the iteration is done.
Example:
int counter = 0; do { writeln(counter); counter++; if (counter >= 1000) { break; } } while (true); // Don't forget the semicolon!
for
loop
A for loop is complex but really useful.
It's a more concise version of the while
loop.
The for loop consists of three expressions:
- Expression 1: Thing to do before loop starts iterating
- Expression 2: Condition to check when each iteration is complete
- Expression 3: What to do when loop completes
Basic syntax:
for (<expr1>, <expr2>, <expr3>) { }
Now here's a more concise version of the while loop example:
for (int counter = 0; counter < 1000; counter++) { writeln(i); }
foreach
and foreach_reverse
We're moving on to the last types of loops, foreach
and foreach_reverse
.
foreach
is a loop that will iterate for each thing in something.
That thing is usually one element in an array.
That something is usually an array.
Here's an example of one with an array.
string webdevlangs[] = ["HTML", "CSS", "JavaScript", "WebAssembly (WASM)"]; foreach(string lang; webdevlangs) { writeln("- ", lang); } /* Output: - HTML - CSS - JavaScript - WebAssembly (WASM) */
You can also have range based foreach
loops
The ranges follow the following pattern:
<first_number_in_range> .. <first_number_NOT_in_range>
Same pattern for slices.
foreach_reverse
is basically the same, except it iterates in reverse order.
An example of foreach_reverse
:
foreach_reverse(int num; 1 .. 11) { writeln(num, "!"); } writeln("BLASTOFF!!!!!");
Labels
Labels are cool and concise.
They are basically making a variable for a loop.
But the syntax is different.
Example:
label_name: while (true) { // code }
The thing that makes it really useful is the fact that you can continue
or break
a label for a loop.
Syntax:
continue <loop_label>; break <loop_label>;
Functions
Functions are an essential part of programming.
writeln
is a function. readln
is a function, you name it. Everything that can be called with two parenthesis is a function.
But sometimes you need to define your own.
Actually, we already defined our own before. main
is a function.
It's just a special function because that's the program's entry point.
We will start looking at the basics of function, then about defining your own.
What are functions
Functions are snippets of code that can be called with parenthesis.
Functions have parameters
, or local variables inside the function.
When parameter values are assigned when the function is called, those values are called arguments
.
You don't have to assign it a value, the value will be assigned in the arguments.
But if you do, the parameter will have a default value if it is not given an argument.
Functions can also return values, allowing them to be used for variables.
You use the return
keyword to return a value.
Example:
return <value>;
Of course, you replace value
with the value or variable.
Defining your own Functions
Before you put the function name and the parameters, you put the return type. This can be anything.
If the function will not return anything, then put void
.
Then there's the name. Follow the same rules as if you are naming a variable.
Here is an example of a non-return function:
void printSquaredNumber(int number) { int squared_number = number * number; writeln(squared_number); }
That function will not return anything, but it will print the a squared number to the console.
Now for a function that will return something:
string prompt(string prompt_text = " >> ") { write(prompt_text); string input = readln(); return input; }
You can do that same thing with readln
and write
, but it's better to make it into a function, especially if yo are gonna have a lot of console input.
Exception Handling Basics
Exceptions are basically errors that happen while the program is running.
They can happen for all sorts of reasons. Let's say, for example, that you want to make a program that will take a number the user typed in and convert it to a double to get the cube root of it.
The program might throw an exception if the user typed in something that can't be converted to a double.
That would stop the program. We don't want that.
A basic and effective way to do this is a chain of try
-catch
-finally
blocks.
Each blocks' behavior is explained in the example below:
try { // Code that may have the danger of throwing an exception ) catch (exceptionName e) { // Code that runs if that exception is thrown } catch (otherExceptionName e) { /* Code to be run if other exception is thrown. And yes. You can have as many catch blocks as you need. */ } finally { // This block of code is runs after the try-catch blocks are run regardless if it threw an exception or not. } // You can also have "catch {}" to catch any exception.
The basic idea is that the program tries to run the code in the try
block.
If it throws an exception, then the code runs the matching catch
block for the exception.
Afterwords, the program runs the finally
block. It doesn't matter whether the program threw any exceptions or not.
Then the program keeps running (if there were no unhandled exceptions.)
Structs
Thanks to @CodeLongAndPros for suggesting this topic.
struct
s are one way you define your own data types.
They are usually made my combining a bunch of types.
Example:
// declaring the type struct pokedex_entry { int level; int exp; string name; string pokemon_type; } // using the type pokedex_entry Pikachu = pokedex_entry(23, 945, "Pikachu", "Electric");
Like in functions, you can assign default values for each combined type.
Example before but with default values:
struct pokedex_entry { int level = 47; int exp 55684; string name = "Cinderace"; string pokemon_type = "Fire";// it's from pokemon sword and shield btw }
To access a certain member of a function, you put the variable, a dot, and then the name of the variable member you would like to change.
// LEVEL UP! ++Pikachu.level;
TODO: explain
this
keyword in structs
Imports
Thanks to @CodeLongAndPros for suggesting this section.
The standard D runtime library is Phobos.
It has a bunch of things you can use in import
s.
The import
s starting with std
are usually regular modules.
The ones starting with ect
are usually from C or C++.
And finally, the ones starting with core
are usually low level.
There are many things in Phobos. Here, we will cover important parts and some of their important functions.
So now I will start talking about the important things.
std.stdio
I hope you know what this does by now, but there are more things I can discuss that I have not mentioned.
Other useful things:
file
- A struct for file manipulationwritef and writefln
- They are basically D's ways to do C'sprintf
std.math
This provides functions and constants for dealing with more complicated math than basic operations.
Important functions
sqrt
- Get square root of number.cbrt
- Get cube root of number.abs
- Get absolute value of number.floor
- Round down to the nearest integer.ceil
- Round up to the nearest integer.
std.random
Provides functions for generating random numbers.
Important functions:
uniform
- Generates a random number between two numbers. It auto-guesses the type, so if it's two integers, it generates two integers.dice
- Generates a number low number (like 0, 1, or 2) with specific probability. It can take at least two arguments. Two arguments mean either 0 or 1.choice
- Returns a random element from a range.
std.array
Array manipulation.
Important functions:
join
- Join elements of an array. Takes an optional second parameter to put after each element of array.replace
- Replace all occurrences of a specified subrange with a new thingreplaceFirst
- Replace the first occurrence of a specified subrange with a new thing.replaceLast
- Replace the last occurrence of a specified subrange with a new thing.
There are too many things in Phobos to mention in this tutorial. You can see all that Phobos has to offer here.
Classes
Now, we'll deal with classes.
Since D has support for OOP, you can use classes.
Example:
class sample { ...
But there's more to classes than that.
For another class to inherit from one another you put a colon then the class name.
You cannot inherit multiple classes.
Consider this example from the Dlang Tour:
class Foo { } // inherits from Object class Bar : Foo { } // Bar is a Foo too
Sometimes you need a reference for a class to use stuff from it. As usual, there is a way to do that.
They are called references.
Consider this example from the Dlang Tour.
Bar bar = foo; // bar points to foo
More about Unicode in D
D has full support for Unicode.
Unicode is an encoding scheme.
To understand what that is, we need to understand how a computer works.
At a basic level, computers use numbers to perform operations. So they need a way to turn that into basic text.
That's where encoding schemes come in. They turn those numbers into text.
Unicode is an example of an encoding scheme. It's also a global standard.
C/C++ strings and characters are just bytes essentially. But D strings and characters are Unicode characters
D supports UTF-8
, UTF-16
, and UTF-32
characters with different types of characters and strings.
----------------------------------------------- | Char type | String type | UTF character set | ----------------------------------------------- | char | string | UTF-8 | ----------------------------------------------- | wchar | wstring | UTF-16 | ----------------------------------------------- | dchar | dstring | UTF-32 | -----------------------------------------------
Conclusion
D is a great language. You can make lots of things with it.
It runs really fast, so it's good for video games and all sorts of stuff.
It's made to feel like C and C++, so it's easy to use if you come from one of those languages.
It's multi paradigm, so your D programs can be Object Oriented, imperative, structured, ect.
It has full support for Unicode, so you have a big character set to use.
So go to wherever you can code in Dlang, and have fun
Sources
- Welcome to D - Dlang tour | https://tour.dlang.org
- SirNigelCogs/Little-Park: A simple classic-style text adventure game written in D. | https://github.com/SirNigelCogs/Little-Park
- D Programming - Arrays - Tutorialspoint | https://www.tutorialspoint.com/d_programming/d_programming_arrays.htm
- D Slices - D Programming Language | https://dlang.org/articles/d-array-article.html
- Programming in D - switch and case | http://ddili.org/ders/d.en/switch_case.html
- D Programming - Operartors - Tutorialspoint | https://www.tutorialspoint.com/d_programming/d_programming_operators.htm
- Unicode in D - Dlang Tour | https://tour.dlang.org/tour/en/gems/unicode
- Phobos Runtime Library - D Programming Language | https://dlang.org/phobos/index.html
- Programming in D - Structs | http://ddili.org/ders/d.en/struct.html
string inventory[] = ["sword", "shield", "healing potion"];
writeln("You have:\n", inventory[]);
Odd, I always wrote it like this instead: ```d string[] inventory = ["sword", "shield", "healing potion"]; writeln("You have:\n", inventory);
Know if it's any different?
lmao, nice! You might want to mention that D is slower than C / C++, and that it's a garbage collected language, like Java.
@StudentFires yeah right
sorry for long delay
@nk1rwc Eh, idc
nice!
Scratch tutorial on repl.it? @DungeonMaster00
@anonymous360c its ded
will probably make an intermediate and advanced course now
apperantly the repl.it team will add D to the official list of languages if https://repl.it/language-requests/p/d gets enough upvotes.
Talk about memory allocation in D
think i fixed most of the major typos
This is great!
Perhaps a little more on classes, and struts, imports, and the this
operator?
@CodeLongAndPros ill improve this over time
@nk1rwc probably done by end of august tops
@nk1rwc (silently) raging against the machine when a bunch of revisions were lost even though i remember updating the post (pun intended)
@CodeLongAndPros That ought to be the next tutorial in the series. lmao
@nk1rwc Oh shoot, sorry, I helped setup the Bash, but later improved efficiency and control flow, it seems like the post wasn't updated to reflect that, go use the Repl I setup seperately from CodeLong at: https://repl.it/@StudentFires/Dlang-template.
@StudentFires its fine i improved this again
@nk1rwc Improved what? The Bash seem the same.
We all needed another C-Family Copycat didn't we?