C3 AI Documentation Home

Lambdas

In the C3 Agentic AI Platform, lambda instances are also first-class objects. You can use lambda functions for short, simple tasks. Lambda functions are especially popular in functional programming patterns, such as mapping and filtering data in lists.

Lambdas

Lambdas can be field and parameters in Types. For example, in method declarations such as Collection#mapTo, you can see lambdas inside the declarations:

Type
mapTo: member function<T>(elementType: !ValueType, mapper: !lambda(e: E, index: !int): T): mixing Collection<T>

In the code snippet above, note the value of the mapper parameter.

The lambda keyword defines the shape of the function that is expected to be passed here. This is an example of strong typing since you know the expected number and types of its parameters and its return value.

If a lambda data value is required to be persisted or serialized so it can be sent to a different system (such as a client request going to the server), it is boxed as an instance of the Lambda Type. This is an Obj that contains the language and code of the lambda, allowing it to be turned back into something executable in the other environment.

Lambdas enable the use of higher-order functions, such as map, filter, and reduce, which operate on arrays and transform or process their elements. Here is an example that uses a lambda with map to double each element in an array:

Type
type MyType {
    
    doubleNumber: function(inputArray: ![double]): [double] js-server
}
JavaScript
function doubleNumber(inputArray) {
    var doubledNumbers = inputArray.map((number) => number * 2);
    // sample input [1, 2, 3, 4, 5]
    return doubledNumbers; // Sample Output: [2, 4, 6, 8, 10]
}

In this example, the lambda function (number) => number * 2 is passed to the map method, which applies the function to each element of the numbers array and returns a new array with the doubled values.

Use lambdas to define runtime behavior

Lambdas allow you to associate an instance to a particular implementation at runtime.

As an example, if you want to implement logic that computes the distance between two points, you could model it with the following type:

Type
type Point {
    x: int
    y: int
    
    distanceTo: member function(p1: !Point, p2: !Point): float
}

In the above implementation, all Point instances can invoke the distanceTo method. When two instances invoke the same method they use exactly the same logic.

However, sometimes you need the implementation to be dynamic, so that at runtime you can associate different instances with different implementations of the method. As an example, you want to keep invoking .distanceTo(), but for some points you want to return the Euclidean distance, and for others, the Manhattan distance.

In the following sections you use lambda fields to achieve this.

Create a Lambda field

To create a new lambda field, add a new field to your Type. Set your new field with the Lambda data type:

Type
type Point {
  x: int
  y: int

  distanceTo: Lambda<function(p1: !Point, p2: !Point): float>
}

Notice that the distanceTo resembles a method declaration, but is a field.

After you create an instance of a new Point type, you can access the field and assign a value to lambda field with that specific instance of the Point Type.

Create a Lambda instance

You can create Lambda instances using JavaScript, Python, or built-in C3 Agentic AI Platform methods. If you are using an execution environment like a Jupyter notebook or the C3 AI Console, you can create Lambda instances by reusing Python or JavaScript logic.

The only requirement is that a Lambda must be a pure function. The function needs to receive all the context required to execute the logic. This means you can create Lambda instances from C3 Agentic AI Platform static methods, but not member methods.

Create a Lambda instance from JavaScript

There are multiple ways to create a Lambda instance. One way is to create it by specifying the JavaScript implementation as a string:

JavaScript
// You could also use (p1, p2) => Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y)
var manhattanDistance = Lambda.fromJsSrc('function(p1, p2){ return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y); }')

point = Point.make({
    x: 0, 
    y: 0, 
    distanceTo: manhattanDistance
})

You can use this approach to create a Lambda instance implemented in JavaScript from a Python notebook, the C3 AI Console, or any other client environment.

If you are interacting with an application from a JavaScript environment, like the web console, you can create Lambda instances by reusing an existing JavaScript function definition:

JavaScript
// Or manhattanDistance = (p1, p2) => {...}
function manhattanDistance(p1, p2) {
  return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
}

point = Point.make({
    x: 0, 
    y: 0, 
    distanceTo: Lambda.fromJsSrc(manhattanDistance)
})

Create a Lambda instance from Python

You can also create a Lambda instance by specifying the Python implementation as a string, and a runtime environment:

JavaScript
// This example uses the no_libs_1_0_0, but you can use any runtime environment
var manhattanDistance = Lambda.fromPySrc('lambda p1, p2: abs(p1["x"] - p2["x"]) + abs(p1["y"] - p2["y"])', "py")

point = Point.make({ x: 0, y: 0, distanceTo: manhattanDistance })

You can use this approach to create a Lambda instance implemented in JavaScript from a Python notebook, the C3 AI Console, or any other client environment.

If you are interacting with an application from a Python environment, like a Jupyter notebook, you can create Lambda instances by reusing an existing Python function definition:

Python
def manhattanDistance(p1, p2):
    return abs(p1["x"] - p2["x"]) + abs(p1["y"] - p2["y"])

point = c3.Point(x=0, y=0, distanceTo=c3.Lambda.fromPyFunc(manhattanDistance, "py"))

Creating a Lambda instance from a Python function only works if the function can be serialized. If you cannot create a Lambda instance for a particular Python function, specify the function implementation as a string.

Create a Lambda instance from a C3 Agentic AI Platform method

You can also create a Lambda instance from an existing C3 Agentic AI Platform method, as long as that method is static. If you have a method that computes the Manhattan distance:

Type
type Point {
  x: int
  y: int

  distanceTo: Lambda<function(p1: !Point, p2: !Point): float>

  @py(env="py")
  manhattanDistance: function(p1: !Point, p2: !Point): float js-server | py-server

  @py(env="py")
  euclideanDistance: function(p1: !Point, p2: !Point): float js-server | py-server
}

You can create a Lambda instance with:

JavaScript
point = Point.make({
    x: 0, 
    y: 0, 
    distanceTo: Lambda.fromAction(Point, 'manhattanDistance')
})

Evaluate a Lambda field

After you associate an instance with a particular implementation by assigning a value to the lambda field, you can run the lambda function:

JavaScript
// Create a lambda instance
var manhattanDistance = Lambda.fromJsSrc('function(p1, p2){ return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y); }')

// You can evaluate the Lambda function directly. This will be computed server-side.
manhattanDistance.call(Point.make({x: 0, y:0}), Point.make({x:2, y:2}))

// Create a point that uses Manhattan distance
var manhattanPoint = Point.make({distanceTo: manhattanDistance})

// Run the logic associated with the lambda field
manhattanPoint.distanceTo.call(Point.make({x: 0, y:0}), Point.make({x:2, y:2}))

Since you are wrapping the function implementation in a Lambda, the logic always runs on the server even if you are working from the web console, Jupyter notebook, C3 AI CLI or any other client environment.

Use Lambda instances to run server-side computation

When using Lambda.call(), the computation is executed on a manager node on the C3 Agentic AI Platform cluster, so you can use Lambda instances as a way to run quick server-side computations:

JavaScript
var addOne = Lambda.fromJsSrc(function(x) { return x + 1};)

// Run the function on the C3 Agentic AI Platform cluster, returns 3
addOne.call(2)
Was this page helpful?