A specialized scripting language for AI and Machine Learning.
Project description
Mlscript v1.0.0-beta — Documentation
Part I: Introduction to mlscript
1. Overview
mlscript is a high-level, dynamically-typed, object-oriented scripting language engineered for high-performance numerical computation and machine learning. Its design is centered around a sophisticated dual-nature architecture that combines the expressive power and rapid development capabilities of a scripting language with the computational efficiency of a compiled, low-level backend. This hybrid model is the cornerstone of the language, offering a unique blend of productivity and performance.
The frontend of mlscript is implemented in Python, providing a familiar, flexible, and feature-rich environment for developers.1 This layer is responsible for parsing the source code and managing the high-level execution logic, including a comprehensive object model with advanced features such as multiple inheritance governed by the C3 Method Resolution Order algorithm.1 This approach allows users to write clear, concise, and powerful code for complex tasks without sacrificing the dynamic nature expected of a modern scripting language.
The power of mlscript is fully realized through its C++ backend, which handles all performance-critical operations. This backend is built using a modern C++17 toolchain and leverages best-in-class libraries for numerical computing and parallelization.1 At its core is the
Tensor object, a multi-dimensional array implemented using the highly optimized Eigen linear algebra library.1 All numerical operations, from simple element-wise arithmetic to complex matrix multiplications, are delegated to this compiled C++ layer. Furthermore, the backend is parallelized using OpenMP, enabling
mlscript to take full advantage of multi-core processors to accelerate computationally intensive tasks.1
This deliberate separation of concerns allows mlscript to provide an optimal environment for machine learning research and development. The user-friendly frontend simplifies the process of defining models and algorithms, while the high-performance backend ensures that training and inference operations execute with the speed necessary for handling large-scale datasets. The entire system is seamlessly integrated, allowing developers to move effortlessly between high-level scripting and low-level numerical computation.
2. Getting Started
This section provides the necessary information to build the mlscript language module from source and prepare it for use in a development environment.
2.1. Prerequisites
To successfully build mlscript, the following dependencies must be installed and configured on the build system. The build process relies on CMake to manage dependencies and generate the appropriate build files for the target platform.1
- C++17 Compliant Compiler: The mlscript C++ backend uses features from the C++17 standard. A modern compiler such as GCC, Clang, or MSVC that supports this standard is required.
- CMake (Version 3.15 or higher): The project uses CMake for its build system automation. The minimum required version is 3.15.
- Python and NumPy: A Python installation (including development headers) is necessary for building the Python bindings. The NumPy library is also required, as its C API headers are used for interoperability with the Tensor object. The build script will automatically locate the Python interpreter and NumPy include directories.
- OpenMP: The language's C++ backend is designed for parallel execution and requires the OpenMP library. The CMake configuration will fail if OpenMP is not found on the system.
- Eigen and pybind11: The source code for the Eigen and pybind11 libraries must be present within the third_party directory of the project's source tree. The build system is configured to compile these libraries directly from this location rather than relying on a system-wide installation.
2.2. Building from Source
The compilation process is managed by CMake and produces a Python extension module. This module can then be imported and used like any other Python package.
The build process can be summarized in the following steps:
-
Obtain the Source Code: Clone or download the mlscript source code repository.
-
Populate Dependencies: Ensure that the source code for Eigen and pybind11 is located in the third_party/eigen and third_party/pybind11 subdirectories, respectively.
-
Configure the Build: Navigate to the root directory of the source code in a terminal and run CMake to generate the build files.
Bash
cmake. -
Compile the Module: Execute the build command. On Linux or macOS, this is typically done with make.
Bash
makeAlternatively, the platform-agnostic CMake build command can be used:
Bash
cmake --build. -
Locate the Artifact: Upon successful compilation, the mlscript Python module (e.g., mlscript.so on Linux or mlscript.pyd on Windows) will be placed in the root source directory of the project.1 This is a deliberate configuration choice to make the module immediately available for use without requiring installation into a system or virtual environment directory.
Once built, the mlscript interpreter can be run, or the module can be imported into an interactive Python session from the project's root directory.
Part II: Language Fundamentals
3. Lexical Structure and Data Types
This section details the fundamental building blocks of the mlscript language, including its variable assignment rules and its set of primitive and compound data types.
3.1. Variables and Assignment
mlscript is a dynamically-typed language, meaning that the type of a variable is determined at runtime and does not need to be explicitly declared. Variables are created upon their first assignment. The assignment operation uses the single equals sign (=) operator.1
The left-hand side of an assignment must be a valid target, such as a variable name, an element of a collection (via index access), or an attribute of an object. The right-hand side can be any valid expression. The interpreter evaluates the right-hand side expression and binds its resulting value to the name on the left-hand side within the current scope.1
Example:
Code snippet
x = 10 // Assigns an integer to x
y = "hello" // Assigns a string to y
z = x + 5 // Assigns the result of an expression to z
3.2. Primitive Data Types
mlscript supports a standard set of primitive data types for representing numbers, boolean values, and text.
- Numbers: The language recognizes both integer and floating-point numerical literals. These are parsed into Number nodes in the Abstract Syntax Tree (AST) and are handled as standard numerical types during execution.1
- Integers: 1, 42, -100
- Floats: 3.14, -0.01, 1.0e-5
- Booleans: The boolean type has two literal values: true and false. These keywords are case-sensitive and are represented internally by BooleanLiteral nodes.1 They are used primarily in conditional logic.
- Strings: String literals are sequences of characters enclosed in either single (') or double (") quotes. They are represented by StringLiteral nodes in the AST.1
3.3. Data Structures
mlscript provides built-in support for several versatile data structures, which are created as standard Python objects at runtime.1
- Lists: A list is an ordered, mutable collection of items. List literals are defined by enclosing a comma-separated sequence of expressions in square brackets (``). The items in a list can be of any type.
- AST Node: ListLiteral 1
- Example: my_list = [1, "apple", true, ]
- Dictionaries: A dictionary is an unordered collection of key-value pairs. Dictionary literals are defined using curly braces ({}), with each pair consisting of a key expression, a colon (:), and a value expression. Keys are typically strings or numbers.
- AST Node: DictLiteral 1
- Example: my_dict = {"name": "Alice", "age": 30}
- Tuples: A tuple is an ordered, immutable collection of items. Tuple literals are formed by a comma-separated sequence of expressions, typically enclosed in parentheses (()). A single-element tuple must have a trailing comma (e.g., (5,)). An empty tuple is created with empty parentheses ().
- AST Node: TupleLiteral 1
- Example: my_tuple = (10, 20, "config")
4. Expressions and Operators
mlscript provides a rich set of operators for performing arithmetic, comparison, and membership checks. The order of evaluation for these operators is governed by a well-defined precedence hierarchy.
4.1. Arithmetic Operators
The language supports standard arithmetic operators for numerical computations. When used with Tensor objects, these operators perform element-wise operations delegated to the high-performance C++ backend.1
- +: Addition. Also used for string concatenation.
- -: Subtraction.
- *: Multiplication.
- /: Division.
The language also supports unary + and - operators for indicating the sign of a numerical literal or expression.1
4.2. Comparison and Membership Operators
These operators evaluate to a boolean value (true or false) and are primarily used in conditional statements.
- Comparison Operators:
- ==: Equal to
- !=: Not equal to
- <: Less than
- <=: Less than or equal to
- >: Greater than
- >=: Greater than or equal to
- Membership Operators:
- in: Returns true if an element is found within a sequence.
- not in: Returns true if an element is not found within a sequence.
The membership operators are supported for lists, strings, dictionaries (checking for key membership), and tuples.1
4.3. Operator Precedence
The precedence of operators determines the order in which they are evaluated in a complex expression. In mlscript, this hierarchy is not defined by an explicit table but is a natural consequence of the grammar's structure, which is implemented using a recursive descent parser.1 The parser's functions are called in a specific sequence (
comparison_expression -> expr -> term -> factor), which ensures that operators handled in later functions (like * and / in term) are evaluated before those in earlier functions (like + and - in expr).
The following table summarizes the operator precedence in mlscript, from highest to lowest.
Precedence | Operator | Description | Associativity |
---|---|---|---|
Highest | () | Grouping | N/A |
. `` () | Attribute Access, Indexing, Function Call | Left-to-Right | |
- + | Unary Minus, Unary Plus | N/A | |
* / | Multiplication, Division | Left-to-Right | |
+ - | Addition, Subtraction | Left-to-Right | |
in not in | Membership | Left-to-Right | |
Lowest | == != < > <= >= | Comparisons | Left-to-Right |
5. Statements and Control Flow
mlscript provides a comprehensive set of control flow statements for directing the execution path of a program, including conditionals for decision-making and loops for repetitive tasks.
5.1. Conditional Execution: if-elif-else
Conditional logic is implemented using the if, elif (else if), and else keywords. The structure allows for branching execution based on the evaluation of one or more boolean expressions.
An if statement begins with a condition. If this condition evaluates to true, the associated block of code is executed. It can be followed by zero or more elif clauses, each with its own condition, which are tested sequentially if all preceding conditions were false. An optional else clause at the end provides a block of code to be executed if none of the if or elif conditions are met.1
Example:
Code snippet
x = 20
if (x < 10) {
print("x is less than 10")
} elif (x > 10) {
print("x is greater than 10")
} else {
print("x is exactly 10")
}
5.2. Loops: while and for...in
mlscript offers two primary looping constructs: while for condition-based iteration and for...in for iterating over sequences.
-
while loop: The while loop repeatedly executes a block of code as long as its condition remains true. The condition is checked before each iteration.1
Example:
Code snippet
count = 0
while (count < 5) {
print(count)
count = count + 1
} -
for...in loop: The for...in loop iterates over the elements of a sequence, assigning each element to a loop variable in turn. The language supports iteration over lists, strings, tuples, and range objects. Attempting to iterate over an unsupported type will result in a runtime error.1
Example:
Code snippet
items = ["a", "b", "c"]
for item in items {
print(item)
}
5.3. Loop Control: break and continue
The execution of loops can be controlled with the break and continue statements.
- break: Immediately terminates the innermost enclosing while or for loop.
- continue: Skips the remainder of the current iteration and proceeds to the next iteration of the innermost enclosing loop.
mlscript provides an important robustness feature related to these statements. The parser validates their usage during the parsing phase, before the code is ever executed. It maintains an internal state to track whether it is currently inside a loop body. If a break or continue statement is found outside of a while or for loop, the parser will immediately raise a SyntaxError.1 This provides immediate feedback to the developer about misplaced control statements, preventing a class of errors that would otherwise only appear at runtime.
6. Functions
Functions are fundamental, first-class objects in mlscript. They are used to encapsulate reusable blocks of code, promoting modularity and organization.
6.1. Function Definition and Calls
Functions are defined using the fun keyword, followed by the function name, a list of parameters in parentheses, and a block of code in curly braces.1
- Parameters and Arguments: Functions can accept zero or more parameters. When the function is called, arguments are passed to these parameters.
- Default Arguments: Parameters can be assigned a default value. If a caller does not provide an argument for a parameter with a default value, the default is used instead. A key syntactic rule, enforced by the parser, is that all parameters without default values must appear before any parameters that have default values.1
- Return Values: The return statement is used to exit a function and optionally pass a value back to the caller. If a function reaches the end of its body without encountering a return statement, it implicitly returns a None value.1
Example:
Code snippet
fun greet(name, greeting = "Hello") {
return greeting + ", " + name + "!"
}
message = greet("World") // message is "Hello, World!"
message2 = greet("Alice", "Hi") // message2 is "Hi, Alice!"
6.2. Variable Scope
mlscript employs lexical (or static) scoping, which means that the scope of a variable is determined by its position within the source code. A variable defined inside a function is local to that function and is not accessible from the outside. A function can, however, access variables defined in its containing (enclosing) scopes.
This scoping mechanism is implemented through a scope_stack in the language's C++ evaluation engine.1 When a function is called, a new scope (a new map for storing variables) is pushed onto the stack. When a variable is accessed, the interpreter searches for it by starting with the topmost scope on the stack and working its way down through parent scopes until the variable is found or the global scope is reached. When the function returns, its scope is popped from the stack, and its local variables are destroyed.1 This robust implementation ensures that variable lifetimes are managed correctly and predictably.
Part III: Object-Oriented Programming
mlscript is a fully object-oriented language, providing a powerful and flexible class system for creating custom data types with associated behaviors. The object model supports key features such as inheritance, method overriding, and dynamic attribute access.
7.1. Classes and Instances
- Class Definition: Classes are defined using the class keyword, followed by the class name and a body enclosed in curly braces ({}). The class body is where methods are defined.1 A notable design choice in
mlscript is that class bodies are restricted to containing only method definitions (using the fun keyword). Unlike languages such as Python, mlscript does not permit class-level attributes or other arbitrary statements directly within the class body. Any attempt to include non-method statements will result in a SyntaxError during the parsing phase.1 This decision simplifies the object model by ensuring that all state is instance-level state, managed within the instance's methods. - Instance Creation: An instance of a class is created by calling the class as if it were a function, e.g., my_instance = MyClass().
- The init Method: When an instance is created, mlscript automatically looks for a method named init. If this method exists, it is called immediately after the instance is created, and any arguments passed during instantiation are forwarded to it. The init method serves as the class constructor and is the primary place to initialize the instance's state (its attributes).1
Example:
Code snippet
class Dog {
fun init(name, age) {
self.name = name
self.age = age
}
}
my_dog = Dog("Rex", 5)
print(my_dog.name) // Prints "Rex"
7.2. Attributes and Methods
- Methods: Methods are functions defined inside a class. The first parameter of every method is a reference to the instance on which the method is being called. By convention, this parameter is named self.1
- Attributes: Attributes are variables that belong to an instance. They are created, accessed, and modified using dot notation (e.g., instance.attribute). Attributes are typically created within the init method by assigning to self, but they can also be created in other methods. They are stored in a dictionary unique to each instance.1
Example:
Code snippet
class Counter {
fun init() {
self.value = 0
}
fun increment() {
self.value \= self.value \+ 1
}
fun get\_value() {
return self.value
}
}
c = Counter()
c.increment()
c.increment()
print(c.get_value()) // Prints 2
7.3. Inheritance
mlscript supports both single and multiple inheritance, allowing a class (the child class) to inherit methods from one or more other classes (the parent classes). Inheritance is specified using the inherits keyword after the class name.1
When a method is called on an instance, mlscript first searches for the method in the instance's own class. If it is not found, it searches through the parent classes in a specific, well-defined order. This search order is known as the Method Resolution Order (MRO). mlscript implements the same sophisticated C3 linearization algorithm for its MRO as Python.1 This ensures that in complex multiple inheritance hierarchies, the order in which methods are resolved is consistent, predictable, and avoids common pitfalls.
Example:
Code snippet
class Animal {
fun speak() {
print("The animal makes a sound")
}
}
class Cat inherits Animal {
fun speak() {
print("Meow")
}
}
c = Cat()
c.speak() // Prints "Meow"
7.4. Accessing Superclass Methods: super()
Within a method of a child class, it is often necessary to call the implementation of that same method from its parent class. This is achieved using the super() keyword. A call like super().method_name() will invoke the version of method_name found in the next class in the MRO.1
The implementation of super() in mlscript is robust and correctly handles complex inheritance scenarios. The interpreter maintains a method_context_stack that tracks the current instance (self) and the class where the currently executing method was defined. When super() is called, the interpreter uses this context to look up the instance's MRO, find the defining class, and then start its search for the method in the next class in the MRO.1 This ensures that
super() always does the right thing, even with multiple levels of inheritance or diamond-shaped inheritance patterns. Using super() outside of a class method will result in a runtime error.
Example:
Code snippet
class Person {
fun init(name) {
self.name = name
}
}
class Employee inherits Person {
fun init(name, employee_id) {
super().init(name) // Calls Person's init method
self.employee_id = employee_id
}
}
e = Employee("Jane Doe", 12345)
print(e.name) // Prints "Jane Doe"
print(e.employee_id) // Prints 12345
Part IV: Advanced Features
mlscript includes several advanced features that provide powerful mechanisms for error handling, resource management, and interoperability with the broader Python ecosystem.
8.1. Error Handling: try-catch-finally
mlscript provides a structured exception handling mechanism similar to that of other modern languages, using try, catch, finally, and throw keywords.
- try: A try block encloses a section of code where an exception might occur.
- catch (e): If an exception is thrown within the try block, execution immediately jumps to the corresponding catch block. The exception object that was thrown is bound to the variable specified in the parentheses (e.g., e).
- finally: An optional finally block contains cleanup code that is guaranteed to execute after the try and catch blocks, regardless of whether an exception was thrown or caught.
- throw: The throw statement is used to raise an exception. Any expression can be thrown as an exception value.
The interpreter implements this control flow using a custom MlscriptThrow exception internally. When a throw statement is executed, this exception is raised. The visit_TryCatch method then uses a standard try...except...finally structure to catch this signal, execute the catch block if present, and ensure the finally block is always executed.1
Example:
Code snippet
fun divide(a, b) {
if (b == 0) {
throw "Division by zero error"
}
return a / b
}
try {
result = divide(10, 0)
print("Result:", result)
} catch (error) {
print("Caught an exception:", error)
} finally {
print("Execution finished.")
}
8.2. Context Management: with
The with statement provides a convenient way to manage resources, ensuring that setup and teardown operations are always performed correctly. It simplifies the pattern of try...finally for resource management.
To be used with a with statement, an object must implement the context management protocol, which consists of two special methods:
- __enter__(): This method is called when execution enters the with block. Its return value is optionally assigned to a variable if the as keyword is used.
- __exit__(): This method is called when execution leaves the with block, either normally or due to an exception. It is responsible for releasing the resource.
The mlscript interpreter enforces this protocol at runtime, checking for the existence of __enter__ and __exit__ methods on the context object and calling them at the appropriate times.1 This feature is particularly important for the built-in
no_grad context manager.
8.3. Interoperability: import
mlscript provides a powerful and direct bridge to the vast ecosystem of Python libraries through its import statement. This allows developers to leverage existing Python code and packages for tasks that are not part of the mlscript core language, such as data visualization, file I/O, or web requests.
The syntax for importing is fixed: import <module_name> as <alias>. The module name must be a string literal, and an alias is required.1 At runtime, the interpreter uses Python's standard
importlib.import_module function to dynamically load the specified Python module. The imported module object is then bound to the specified alias name in the current mlscript scope, making its functions and classes available for use.1
Example:
Code snippet
import "numpy" as np
// Create a NumPy array using the imported module
a = np.array()
// Pass the NumPy array to the mlscript tensor constructor
t = tensor(a)
print(t)
Part V: The Core Numerical Engine
The heart of mlscript is its high-performance numerical engine, implemented in C++ and exposed to the scripting environment. This engine is centered around the Tensor object and a sophisticated automatic differentiation system.
9. The Tensor Object
9.1. Introduction
The Tensor is the central data structure for all numerical computation in mlscript. It represents a two-dimensional matrix of double-precision floating-point numbers. For maximum performance, the Tensor is not a pure script-level object; it is a C++ class that uses the highly optimized Eigen::Matrix library for its underlying data storage and mathematical operations.1 The interface to this powerful C++ object is exposed to the
mlscript environment via the pybind11 library, ensuring seamless and efficient interaction between the scripting frontend and the numerical backend.1
Beyond being a simple matrix, every Tensor object is also a potential node in a dynamically constructed computational graph, which is the foundation of mlscript's automatic differentiation capabilities.
9.2. Tensor Creation
Tensor objects can be created in two primary ways, providing flexibility and interoperability with other numerical libraries.
-
From mlscript Lists: The most direct way to create a Tensor is by calling the built-in tensor function with a nested list of numbers.
Code snippet
t1 = tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) -
From NumPy Arrays: mlscript is designed for seamless interoperability with NumPy. A Tensor can be created directly from a 2D NumPy array. This conversion is highly efficient as it leverages the C-level APIs of both NumPy and pybind11.1
Code snippet
import "numpy" as np
arr = np.ones((2, 3))
t2 = tensor(arr)
9.3. Indexing and Slicing
mlscript provides a rich and expressive syntax for accessing and modifying Tensor data, supporting a wide range of indexing and slicing operations that mirror the capabilities of libraries like NumPy.1
- Integer Indexing:
- To access a single scalar value, provide a tuple of row and column indices: scalar = t[row, col].
- To extract an entire row as a new 1xN Tensor, provide a single integer index: row_tensor = t[row]. Negative indexing is supported for rows, where -1 refers to the last row.
- Slice Indexing:
- Slicing is performed using the start:stop:step syntax. A slice can be used to select a range of rows: sliced_rows = t[1:3].
- Slices can be combined with integer indices in a tuple to select sub-regions of the tensor. For example, t[0, 1:3] selects elements from the first row and columns 1 and 2. t[0:2, 0:2] selects a 2x2 sub-matrix from the top-left corner.
9.4. Tensor Operations
All operations on Tensor objects are executed by the underlying C++ engine, ensuring high performance.1
- Element-wise Arithmetic: The standard arithmetic operators (+, -, *, /) perform element-wise operations when applied to two Tensor objects of the same dimensions.
- Scalar Operations: A Tensor can be multiplied by a scalar value, which applies the operation to every element in the tensor (e.g., t * 2.0).
- Matrix Multiplication: True matrix multiplication is performed using the built-in matmul function: result = matmul(t1, t2).
- Reduction: The .sum() method reduces the tensor to a single 1x1 Tensor containing the sum of all its elements.
A critical performance feature of the Tensor object is its implementation of Python's buffer protocol.1 This allows other Python libraries, most notably NumPy, to access the
Tensor's underlying C++ memory buffer directly without needing to copy the data. This zero-copy interoperability is essential for efficient data exchange in numerical workflows, preventing memory bottlenecks when moving data between mlscript and the broader Python scientific computing stack. Furthermore, the C++ implementation of certain operations, such as slicing, is parallelized using OpenMP, allowing the language to leverage multiple CPU cores to accelerate data manipulation tasks.1
10. Automatic Differentiation
Automatic differentiation (AD) is a cornerstone feature of mlscript, enabling the automatic computation of gradients for complex functions. This is essential for training machine learning models using gradient-based optimization algorithms. mlscript implements a reverse-mode AD system based on the dynamic construction of a computational graph.
10.1. The Computational Graph
mlscript does not require users to pre-define a static graph. Instead, a computational graph is built dynamically, on-the-fly, as Tensor operations are executed. Every Tensor object stores pointers to its parent Tensors (the operands that created it) and the operation that was performed.1 For example, when
C = A + B is executed, a new Tensor C is created that holds references to A and B and stores the operation type "+". This chain of references forms a directed acyclic graph (DAG) that represents the exact sequence of computations performed.
This graph construction is conditional. It only occurs when gradient tracking is enabled. This allows users to switch off the overhead of graph building when it is not needed, such as during model inference.
10.2. Gradient Computation: .backward()
The process of computing gradients is initiated by calling the .backward() method on a Tensor. Typically, this is done on a scalar Tensor that represents the final output of a function, such as the loss of a machine learning model.
When .backward() is called, the C++ engine performs the following steps 1:
- Topological Sort: It traverses the computational graph backwards from the starting Tensor to build a topologically sorted list of all nodes (Tensors) involved in the computation. This ensures that when gradients are propagated, a node's gradient is fully computed before it is used to compute the gradients of its own parents.
- Gradient Initialization: The gradient of the starting Tensor with respect to itself is initialized to 1.
- Backpropagation: The engine iterates through the sorted list in reverse order. For each Tensor in the graph, it applies the chain rule based on the operation that created it. For example, for a matrix multiplication C = matmul(A, B), it uses the incoming gradient of C to compute the gradients for A and B and adds them to the .grad attributes of A and B. This process continues until gradients have been accumulated for all "leaf" nodes in the graph (the original input Tensors).
10.3. Inspecting Gradients: .grad
After .backward() has been called, the computed gradient for any Tensor t in the graph is stored in its .grad attribute. This attribute is exposed as a read-only property that returns the gradient as a NumPy array, making it easy to inspect or use with external Python libraries.1 The
.grad attribute of a Tensor has the same dimensions as the Tensor itself.
10.4. Inference Mode: no_grad
For performance-critical situations where gradients are not required (e.g., model inference or forward passes), mlscript provides the no_grad context manager. Any code executed within a with no_grad: block will not build the computational graph. This significantly reduces memory consumption and computational overhead.
This feature is implemented through a clean, cross-language mechanism. The Python-level NoGradManager object, when entering the with block, calls a method on the C++ Evaluator object. This C++ method toggles a global boolean flag within a singleton AutodiffContext object.1 Every
Tensor operation in the C++ backend first checks the state of this global flag before attempting to record its parents and operation in the computational graph.1 This design provides a simple and efficient way to control the behavior of the entire automatic differentiation engine from the script level.
Example of a full AD workflow:
Code snippet
// Create input tensors
a = tensor([[2.0]])
b = tensor([[3.0]])
// Perform computations (builds the graph)
c = a * b
d = c + a
e = d.sum()
// Compute gradients
e.backward()
// Inspect the gradients
print(a.grad) // Gradient of e with respect to a
print(b.grad) // Gradient of e with respect to b
// Perform inference without tracking gradients
with no_grad:
result = a * b // This operation is not added to the graph
Part VI: Reference
11. Built-in Functions and Objects
mlscript provides a set of globally available functions and objects that form its standard library. These built-ins are immediately available in any mlscript program without needing to be imported.
- Functions:
- len(object): Returns the length (number of items) of an object. Applicable to lists, strings, dictionaries, and tuples. This is a direct mapping to the Python len function.
- range(...): Generates a sequence of numbers. It behaves identically to Python's range function.
- min(...): Returns the smallest item from an iterable or the smallest of two or more arguments.
- max(...): Returns the largest item from an iterable or the largest of two or more arguments.
- sum(iterable): Returns the sum of all items in an iterable.
- Objects and Factories:
- tensor(data): The factory function/constructor for creating Tensor objects from nested lists or NumPy arrays.
- matmul(t1, t2): A function that performs matrix multiplication on two Tensor objects. It is a convenient alias for the C++ backend's matmul implementation.
- no_grad: The context manager instance used with the with statement to disable automatic differentiation.
12. Language Keywords
The following identifiers are reserved keywords in the mlscript language and cannot be used as variable, function, or class names.
Keyword | Description |
---|---|
as | Used with import to create an alias for a module. |
break | Exits the innermost loop. |
catch | Defines a block to handle exceptions thrown in a try block. |
class | Defines a new class. |
continue | Skips to the next iteration of the innermost loop. |
elif | Defines a conditional "else if" block in an if statement. |
else | Defines a block to execute when if/elif conditions are false. |
false | The boolean literal for false. |
finally | Defines a cleanup block that always executes after try/catch. |
for | Defines a loop for iterating over a sequence. |
fun | Defines a new function. |
if | Defines a block for conditional execution. |
import | Imports an external Python module. |
in | Used in for loops and for membership testing. |
inherits | Specifies parent classes in a class definition. |
not | Used with in for negative membership testing (not in). |
Prints a value to the console. | |
return | Exits a function and returns a value. |
super | Accesses methods from a parent class. |
throw | Raises an exception. |
true | The boolean literal for true. |
try | Defines a block of code for exception handling. |
while | Defines a loop that executes as long as a condition is true. |
with | Used with context managers for resource management. |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
File details
Details for the file mlscript_lang-0.9.0-cp312-cp312-win_amd64.whl
.
File metadata
- Download URL: mlscript_lang-0.9.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 26.6 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.0 CPython/3.12.11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
f411bfd4bb152ef5e324dcfd8b2ced05d88db8c76e7e6c33b32b95852485a38e
|
|
MD5 |
e730fdc179786886398af34677213c94
|
|
BLAKE2b-256 |
5a3c57c505c67f67677018cc2cd00dfac1f9c225b3f3ead8da01fc9cf640d9e7
|
File details
Details for the file mlscript_lang-0.9.0-cp311-cp311-win_amd64.whl
.
File metadata
- Download URL: mlscript_lang-0.9.0-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 26.6 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.0 CPython/3.12.11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
7d51ac4d7228485f6546ecf1dfaeca2e496614100704212d0b7279936edb700a
|
|
MD5 |
39be9fca6156dc3a9b3f37e9d230cc10
|
|
BLAKE2b-256 |
338bdd1d68f570eae3d1cceeeb1b56fed1e05370da2939fe1e1dfd739a6698aa
|
File details
Details for the file mlscript_lang-0.9.0-cp310-cp310-win_amd64.whl
.
File metadata
- Download URL: mlscript_lang-0.9.0-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 26.6 kB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.0 CPython/3.12.11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
416055b38b11a7f2d3cba804d6bf995bbf6baa50fd741bfa0f3d149254e5fded
|
|
MD5 |
f485475a2988b406a94babec9cc36a43
|
|
BLAKE2b-256 |
059b4ad54356b2f3cb5a044b5768db02520f715545998ac7cc13734ca4d05ee0
|
File details
Details for the file mlscript_lang-0.9.0-cp39-cp39-win_amd64.whl
.
File metadata
- Download URL: mlscript_lang-0.9.0-cp39-cp39-win_amd64.whl
- Upload date:
- Size: 26.6 kB
- Tags: CPython 3.9, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.0 CPython/3.12.11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
18e0a1ff7f1e539fff1abdadab9880cd9b4b268259d2ca157affb05ed764d1f0
|
|
MD5 |
af43534dd53401dbe0fa4a2ed45a4133
|
|
BLAKE2b-256 |
8f235c015f26fb58b9fdfe28fa76f787bf231b530cd6437c5f376d4a37a4b9a6
|
File details
Details for the file mlscript_lang-0.9.0-cp38-cp38-win_amd64.whl
.
File metadata
- Download URL: mlscript_lang-0.9.0-cp38-cp38-win_amd64.whl
- Upload date:
- Size: 26.6 kB
- Tags: CPython 3.8, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.0 CPython/3.12.11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
5fdd03eedd356d8a81a6f90868f7bc158da91f1d7cb54c87fb31111a4f3f6809
|
|
MD5 |
4c55e155ffd1d2aa06dbbf393edade7a
|
|
BLAKE2b-256 |
1d2dc6e1bfbac5fc3f859177f82cffbbef2e1b6f0740b9730e7f52ca2721cd44
|