Carbon is an open-source programming language developed by Google as a successor to C++. At the time of writing this tutorial, Carbon language is an experimental project. There is no working compiler or toolchain. You can see the demo interpreter for Carbon on compiler-explorer.com.
Carbon Declarations
- Functions/Methods are declared using
fnkeyword. - Variables are declared using
varkeyword. - Variable names should end with
:eg:var x: - Constants are declared using
letkeyword. - Packages are declared using
packagekeyword. - Comments are declared using two slashes
// autocan be used to automatically assign the variable type. It can be used in combination withletorvaror as function return types.
Example code snippet:
package ExplorerTest api;
//fn is function declaration
//return type is i32 i.e. int.
fn Main() -> i32 {
//This is a comment.
var name: auto = "Muhammad Furqan Ul Haq"; // Auto Variable
let id: i32 = 57; // Integer Constant
var total_articles_published: i32 = 4500; // Integer Variable
Print(name); // Print "name" Auto Variable
Print(id); // Print "id" Constant
Print(total_articles_published); // Print "total_articles_published" Integer Variable
return 0; //Return value
}
Numeric Variables in Carbon
Variables in carbon language can be
boolfor booleantrueorfalsei8,i16,i32,i64,i128,i256for integer types.u8,u16,u32,u128,u256for unsigned integer types.f16,f32,f64, andf128for float types._can be used for digit separators. Eg: 1_000_000 is still an integer if declared without quotes.
package ExplorerTest api;
fn Main() -> i32 {
var a: i32 = 1;
var b: i32 = 2;
Print(a + b);
return 0;
}
Strings in Carbon
Strings can be declared using
Stringfor byte sequenceStringViewas a read-only reference for the utf-8 byte sequence.
Strings literals can be declared in two ways.
- Single Line: Use double quotation marks (“) for a single line.
- Multi-line string: For multi-line string declaration use (
""")
package ExplorerTest api;
fn Main() -> i32 {
var singleLine: String = "Hello world!";
var multiLine: String = """hello line 1
TipSeason demo line 2
TipSeason demo line 3
"""; //End of multi block
return 0;
}
Arrays in Carbon
Arrays are declared using array type and size. Syntax is [type; size] Eg: var xarray: [i32; 4] = (1,2,3,4);
package ExplorerTest api;
fn Main() -> i32 {
var xarray: [i32; 4] = (0, 1, 5, 6); // Integer array
var index: i32 = 1;
xarray[index] = 0;
Print("{0}", xarray[0]);
Print("{1}", xarray[0]);
return xarray[0] + xarray[1];
}
Conditional Statements (if…else) in Carbon
Combination of if , else can be used to control the conditional flow in Carbon.
if…else
if(condition) {
//doSomething
} else {
//doSomething
}
if…else-if…else
if(condition) {
//doSomething
} else if (condition) {
//doSomething
} else {
//doSomething
}
Example:-
package ExplorerTest api;
fn Main() -> i32 {
var x: i32 = 5;
if(x == 5) {
Print("{0} to word is FIVE", x);
} else {
Print("{0} is not known ", x);
}
return 0;
}
Loops in Carbon
For Loop
For loop can be declared using for (loop conditions) { } . At the time of writing this article, didn’t get a full working example. But here is the proposed syntax.
package ExplorerTest api;
fn Main() -> i32 {
var names: [String; 4] = ("a", "b");
for (var name: String in names) {
Console.Print(name);
}
return x;
}
While loop
While loop can be declared using while(condition){ }
package ExplorerTest api;
fn Main() -> i32 {
var x: auto = 5;
while (not (x == 0)) {
x = x - 1;
Print("{0} ", x);
}
return x;
}
Match multiple conditions similar to Switch
Carbon has match keyword which is similar to switch in C/C++. The syntax for match is
match(condition) {
case (condition) => {
//doSomething;
}
default => {
//doSomething;
}
}
Example
package ExplorerTest api;
fn Matcher(var num: i32) -> i32 {
var number: auto = 10;
match (number) {
case 5 => {
Print("Got 5");
return number;
}
case 10 => {
Print("Got 10");
return number;
}
default => {
Print("Default");
return number;
}
}
}
fn Main() -> i32 {
Matcher(5);
Matcher(10);
Matcher(2);
return 0;
}
Functions/Methods in Carbon
Functions can be declared using fn keyword. The syntax is fn MethodName(var param: type ... ) -> return type . For void or empty return types, you can ignore the part after ->
package ExplorerTest api;
//Integer return type
fn Sum(var a: i32, var b: i32) -> i32 {
return a + b;
}
//Empty or void return type.
fn PrintCount(var count: i32) {
Print("The count is {0}", count);
}
fn Main() -> i32 {
Print("Sum is {0}", Sum(4, 6));
PrintCount(10);
return 0;
}
Tuples in Carbon
Tuples represent values with multiple coordinates. They can be declared using parenthesis ( )
package ExplorerTest api;
fn Main() -> i32 {
var x: auto = (0, 1);
Print("{0}", x[1]);
return x[0];
}
Here (x,y,z) is a tuple with multiple coordinates. They can be accessed using the index.
Pointers in Carbon
There are no null pointers in Carbon. To represent a pointer that may not refer to a valid object, use the type Optional(T*) where T is the type.
* represents value. & represents address.
package ExplorerTest api;
fn Main() -> i32 {
var x: i32 = 5;
// changes x to 10
x = 10;
Print("---");
Print("x = {0}", x);
var y: i32* = &x;
// changes x to 7
*y = 7;
Print("---");
Print("x = {0}", x);
Print("y = {0}", *y);
var z: i32* = &*y;
// changes x to 0
*z = 0;
Print("---");
Print("x = {0}", x);
Print("y = {0}", *y);
Print("z = {0}", *z);
var w: i32 = *y;
return w;
}
Classes in Carbon
Class in carbon language can be declared using class keyword. Class can have members and methods. Here is an example of class implementation.
package ExplorerTest api;
class Sum {
var a: i32;
fn Add[me: Self](var num: i32) -> i32 {
var total: i32 = me.a + num;
return total;
}
}
fn Main() -> i32 {
var p1: Sum = {.a = 5};
var total: i32 = p1.Add(5);
Print("Total sum {0}" , total);
return 0;
}
Structs in Carbon
Structural types help you identify members using the name instead of their index/position. They are declared within curly braces var name: auto = {.name1 = value1, .name2 = value2, ... } and can be accessed using name.name1 etc.
package ExplorerTest api;
fn Main() -> i32 {
var point: auto = {.x_axis = 0, .y_axis = 1};
point = {.x_axis = 5, .y_axis = -5};
var result: i32 = point.x_axis * point.x_axis + point.y_axis * point.y_axis;
Print("Result : {0}", result);
return 0;
}
Generics in Carbon
Generics can be seen in many modern languages. They define a way to induce compile time type checks and help define cleaner type variables. They can be declared using the T parameter type as shown below.
package ExplorerTest api;
fn GenericExample[T:! Type](x: T) -> T {
return x;
}
fn Main() -> i32 {
Print("Integer generic type {0}", GenericExample(0));
Print(GenericExample("This is a string generic"));
return 0;
}
Memory safety in Carbon
Carbon language has a heavy focus on memory management especially when it comes to memory safety. At a very high-level, carbon language plans to achieve memory safety using
- Spatial Memory Safety
- Temporal memory safety
Here is a detailed tutorial on how memory safety is achieved in carbon along with goals and basics. Check Carbon language memory safety for secure memory management