Site icon Adaptive Business Logic

Mojo Programming Language | by Abhijeet Dwivedi | Nov, 2024

Mojo Programming Language | by Abhijeet Dwivedi | Nov, 2024

Functions in MOJO

Mojo supports two types of functions: def and fn functions. You can use either declaration with any function, including the main() function.

The fn function has somewhat stricter rules than the def function.

def greet(name):
return "Hello, " + name + "!"
fn greet2(name: String) -> String:
return "Hello, " + name + "!"
def main():
print("Hello, world!")

A struct in Mojo is similar to a class in Python: they both support methods, fields, operator overloading, decorators for metaprogramming, and so on. However, Mojo structs are completely static—they are bound at compile-time, so they do not allow dynamic dispatch or any runtime changes to the structure. (Mojo will also support Python-style classes in the future.)

struct MyPair:
var first: Int
var second: Int

fn __init__(inout self, first: Int, second: Int):
self.first = first
self.second = second

fn dump(self):
print(self.first, self.second)

A trait is like a template of characteristics for a struct. If you want to create a struct with the characteristics defined in a trait, you must implement each characteristic (such as each method). Each characteristic in a trait is a “requirement” for the struct, and when your struct implements each requirement, it’s said to “conform” to the trait.

And here’s how to create a struct that conforms to the trait:

@value
struct SomeStruct(SomeTrait):
fn required_method(self, x: Int):
print("hello traits", x)

Then, here’s a function that uses the trait as an argument type (instead of the struct type):

fn fun_with_traits[T: SomeTrait](x: T):
x.required_method(42)

fn use_trait_function():
var thing = SomeStruct()
fun_with_traits(thing)

In Mojo, a parameter is a compile-time variable that becomes a runtime constant, and it’s declared in square brackets on a function or struct. Parameters allow for compile-time metaprogramming, which means you can generate or modify code at compile time.

fn repeat[count: Int](msg: String):
for i in range(count):
print(msg)

This function has one parameter of type Int and one argument of type String. To call the function, you need to specify both the parameter and the argument:

fn call_repeat():
repeat[3]("Hello")
# Prints "Hello" 3 times

Code blocks such as functions, conditions, and loops are defined with a colon followed by indented lines. For example:

def loop():
for x in range(5):
if x % 2 == 0:
print(x)

Mojo is not yet a full superset of Python, but we’ve built a mechanism to import Python modules as-is, so you can leverage existing Python code right away.

from python import Python

fn use_numpy() raises:
var np = Python.import_module("numpy")
var ar = np.arange(15).reshape(3, 5)
print(ar)
print(ar.shape)

A variable is a name that holds a value or object. All variables in Mojo are mutable — their value can be changed. (If you want to define a constant value that can’t change at runtime.)

Mojo has two kinds of variables:

  • Explicitly-declared variables are created with the var keyword.
var a = 5
var b: Float64 = 3.14
  • Implicitly-declared variables are created with an assignment statement:
a = 5
b = 3.14

Both types of variables are strongly-typed: the variable receives a type when it’s created, and the type never changes.

var temperature: Float64 = 99
print(temperature)

#Output: 99.0

Variables declared with var are bound by lexical scoping. This means that nested code blocks can read and modify variables defined in an outer scope. But an outer scope cannot read variables defined in an inner scope at all.

For example, the if code block shown here creates an inner scope where outer variables are accessible to read/write, but any new variables do not live beyond the scope of the if block:

def lexical_scopes():
var num = 1
var dig = 1
if num == 1:
print("num:", num) # Reads the outer-scope "num"
var num = 2 # Creates new inner-scope "num"
print("num:", num) # Reads the inner-scope "num"
dig = 2 # Updates the outer-scope "dig"
print("num:", num) # Reads the outer-scope "num"
print("dig:", dig) # Reads the outer-scope "dig"

lexical_scopes()

#Output
num: 1
num: 2
num: 1
dig: 2

link

Exit mobile version