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 withlet
orvar
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 booleantrue
orfalse
i8
,i16
,i32
,i64
,i128
,i256
for integer types.u8
,u16
,u32
,u128
,u256
for unsigned integer types.f16
,f32
,f64
, andf128
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 sequenceStringView
as 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