Carbon Language Tutorial with Syntax and Code Examples

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 fn keyword.
  • Variables are declared using var keyword.
  • Variable names should end with : eg: var x:
  • Constants are declared using let keyword.
  • Packages are declared using package keyword.
  • Comments are declared using two slashes //
  • auto can be used to automatically assign the variable type. It can be used in combination with let or var or 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

  • bool for boolean true or false
  • i8i16i32i64i128i256 for integer types.
  • u8u16u32u128u256 for unsigned integer types.
  • f16f32f64, and f128 for 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

  • String for byte sequence
  • StringView as a read-only reference for the utf-8 byte sequence.

Strings literals can be declared in two ways.

  1. Single Line: Use double quotation marks (“) for a single line.
  2. 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

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.