Prism Language Syntax
Prism is a probabilistic programming language that extends familiar JavaScript-like syntax with confidence-based operations and uncertainty handling. This guide covers all essential syntax elements of the language.
Basic Syntax Elements
Literals
Prism supports standard literal types with optional confidence annotations:
// Numbers
42
3.14
1e6
// Strings
"Hello, world!"
'Single quotes work too'
// String interpolation
name = "Alice"
greeting = `Hello, ${name}!`
// Booleans
true
false
// Null and undefined
null
undefined
// Arrays
[1, 2, 3]
["apple", "banana", "orange"]
// Objects
{name: "Bob", age: 30}
{x: 10, y: 20, z: 30}
Comments
// Single-line comment
/*
Multi-line comment
spanning multiple lines
*/
Variable Declarations
Prism supports both traditional assignment syntax and modern declaration keywords:
Basic Assignment
// Simple assignment
x = 10
name = "Alice"
isReady = true
// Compound assignments
count = 0
count += 1 // count = count + 1
count -= 1 // count = count - 1
count *= 2 // count = count * 2
count /= 2 // count = count / 2
count %= 3 // count = count % 3
// Confident compound assignments (preserve confidence)
balance = 1000 ~> 0.9
balance ~+= 100 ~> 0.8 // balance = balance ~+ (100 ~> 0.8)
balance ~-= 50 ~> 0.95 // balance = balance ~- (50 ~> 0.95)
balance ~*= 1.1 ~> 0.85 // balance = balance ~* (1.1 ~> 0.85)
balance ~/= 2 ~> 0.9 // balance = balance ~/ (2 ~> 0.9)
Declaration Keywords (const/let)
// Immutable bindings with const
const PI = 3.14159
const users = ["alice", "bob"] // Reference is immutable, contents can change
// Mutable variables with let
let counter = 0
let currentUser = null
// Block scoping
function example() {
const outer = "visible everywhere"
if (condition) {
let inner = "only visible in this block"
const temp = process(inner)
// inner and temp are scoped to this block
}
// inner and temp not accessible here
}
// const requires initializer
const name = "Alice" // ✓ Valid
// const age // ✗ Error: const declarations must have an initializer
// let allows optional initializer
let score // ✓ Valid, defaults to 0
let rating = 85 // ✓ Valid with explicit value
// Destructuring with const/let
const [a, b] = [1, 2]
let {name, age} = user
Operators
Arithmetic Operators
// Basic arithmetic
a + b // Addition
a - b // Subtraction
a * b // Multiplication
a / b // Division
a % b // Modulo
a ** b // Exponentiation
// Unary operators
-x // Negation
Comparison Operators
// Loose equality (with type coercion)
a == b // Equality with type coercion
a != b // Inequality with type coercion
// Strict equality (no type coercion)
a === b // Strict equality
a !== b // Strict inequality
// Relational operators
a < b // Less than
a > b // Greater than
a <= b // Less than or equal
a >= b // Greater than or equal
Type Coercion in Comparisons
Loose equality (==
) performs type coercion:
5 == "5" // true - number to string coercion
0 == false // true - number to boolean coercion
null == undefined // true - null equals undefined
"" == false // true - empty string is falsy
// Strict equality does not coerce
5 === "5" // false - different types
0 === false // false - different types
null === undefined // false - different types
Logical Operators
a && b // Logical AND
a || b // Logical OR
!a // Logical NOT
a ?? b // Nullish coalescing (returns b if a is null/undefined)
Type Operators
typeof x // Returns type as string
x instanceof Y // Checks if x is instance of Y
Control Flow
Conditional Statements
// Basic if statement
if x > 0 {
// positive case
}
// If-else statement
if temperature > 30 {
status = "hot"
} else {
status = "cool"
}
// Multiple conditions
if score >= 90 {
grade = "A"
} else if score >= 80 {
grade = "B"
} else if score >= 70 {
grade = "C"
} else {
grade = "F"
}
// Ternary operator
result = condition ? valueIfTrue : valueIfFalse
// Confident ternary operator (propagates confidence)
confident = condition ~? valueIfTrue : valueIfFalse
Loops
// For loop
for i = 0; i < 10; i = i + 1 {
// loop body
}
// For-in loop (iterating over arrays)
arr = [1, 2, 3, 4, 5]
for value in arr {
// process value
}
// For-in with index
for value, index in arr {
// process value and index
}
// While loop
while condition {
// loop body
}
// Do-while loop
do {
// loop body
} while condition
// Loop control
for i = 0; i < 100; i = i + 1 {
if i == 50 {
break // Exit loop
}
if i % 2 == 0 {
continue // Skip to next iteration
}
// process odd numbers
}
Functions
Prism supports both traditional named functions and modern lambda expressions:
Named Functions
// Basic function declaration
function calculateScore(data, weights) {
scores = data.map((item, index) => item * weights[index])
total = scores.reduce((acc, score) => acc + score, 0)
return total
}
// Function with confidence annotation
function riskAssessment(input) ~> 0.8 {
analysis = llm("Assess risk: " + input)
return analysis.score
}
// Function with rest parameters
function sum(...numbers) {
let total = 0
for num in numbers {
total = total + num
}
return total
}
// Function hoisting (can be called before declaration)
result = factorial(5) // Works due to hoisting
function factorial(n) {
if (n <= 1) {
return 1
}
return n * factorial(n - 1)
}
// Early returns
function validateUser(user) {
if (!user) {
return false
}
if (!user.email) {
return false
}
return true
}
Lambda Expressions
// Single parameter
double = x => x * 2
// Multiple parameters
add = (a, b) => a + b
multiply = (x, y, z) => x * y * z
greet = (first, last) => "Hello, " + first + " " + last + "!"
// No parameters
getRandom = () => Math.random()
// Multi-parameter lambdas with array methods
numbers = [1, 2, 3, 4, 5]
summed = reduce(numbers, (acc, val) => acc + val, 0)
product = reduce(numbers, (acc, val) => acc * val, 1)
// Nested multi-parameter lambdas
makeCalculator = (op) => (a, b) => {
if (op == "+") { return a + b }
if (op == "*") { return a * b }
if (op == "-") { return a - b }
return a / b
}
adder = makeCalculator("+")
result = adder(10, 5) // 15
// Expression-only lambda (traditional)
square = x => x * x
// Block-statement lambda (new!)
complexProcess = data => {
const filtered = data.filter(x => x > 0)
let processed = filtered.map(x => x * 2)
processed = processed.filter(x => x < 100)
return processed ~> 0.9
}
// Lambda with early returns
validator = input => {
if (!input) {
return false
}
if (input.length < 3) {
return false
}
return true
}
// Lambda with loops and complex logic
factorial = n => {
let result = 1
for i = 1; i <= n; i = i + 1 {
result = result * i
}
return result
}
// Rest parameters in lambdas
sum = (...numbers) => {
let total = 0
for n in numbers {
total = total + n
}
return total
}
// Destructuring parameters
extractCoords = ([x, y]) => {
const distance = Math.sqrt(x * x + y * y)
return {x, y, distance}
}
// Calling functions
result1 = double(5) // 10
result2 = add(3, 4) // 7
result3 = complexProcess([1,2,3]) // Processed array with confidence
result4 = sum(1, 2, 3, 4) // 10
Function Composition
// Pipeline operator
result = value |> func1 |> func2 |> func3
// Example
addOne = x => x + 1
double = x => x * 2
square = x => x * x
result = 5 |> addOne |> double |> square // ((5 + 1) * 2)² = 144
// Placeholder in pipelines
add = (a, b) => a + b
result = 10 |> add(5, _) // 15 (placeholder represents piped value)
Asynchronous Functions
Prism supports asynchronous programming with async/await for handling promises and asynchronous operations:
// Async function declaration
async function fetchData(url) {
response = await httpGet(url)
data = await response.json()
return data
}
// Async function with confidence
async function analyzeData(input) ~> 0.9 {
result = await llm("Analyze: " + input)
processed = await processResult(result)
return processed
}
// Calling async functions
data = await fetchData("https://api.example.com/data")
analysis = await analyzeData(data)
// Await with Promise values
promise = Promise.resolve(42)
value = await promise // 42
// Await passes through non-promise values
direct = await 100 // 100 (no waiting needed)
// Promise built-in functions
p1 = Promise.resolve("success")
p2 = Promise.reject("error") // Creates rejected promise
// Promise.all - wait for multiple promises
results = await Promise.all([
fetchData("/api/users"),
fetchData("/api/posts"),
fetchData("/api/comments")
])
// Mixing promises and values in Promise.all
mixed = await Promise.all([
Promise.resolve(1),
2, // Non-promise values are wrapped
Promise.resolve(3)
]) // [1, 2, 3]
// Delay/sleep functions
async function delayedOperation() {
console.log("Starting...")
await delay(1000) // Wait 1 second
console.log("...continued after delay")
await sleep(500) // sleep is an alias for delay
return "completed"
}
// Async in loops
async function processItems(items) {
for item in items {
result = await processItem(item)
console.log("Processed:", result)
}
}
// Error handling (when try/catch is available)
// async function safeOperation() {
// try {
// result = await riskyOperation()
// return result
// } catch (error) {
// console.error("Operation failed:", error)
// return null
// }
// }
Data Structures
Arrays
// Array creation
numbers = [1, 2, 3, 4, 5]
mixed = [1, "two", true, null]
nested = [[1, 2], [3, 4], [5, 6]]
// Array access
first = numbers[0] // 1
last = numbers[4] // 5
// Array properties and methods
arr = [1, 2, 3, 4, 5]
len = arr.length // 5
// Array methods with lambdas
doubled = arr.map(x => x * 2) // [2, 4, 6, 8, 10]
evens = arr.filter(x => x % 2 == 0) // [2, 4]
sum = arr.reduce((acc, x) => acc + x, 0) // 15
// Array methods with block-statement lambdas
processed = arr.map(x => {
const doubled = x * 2
return doubled > 5 ? doubled : 0
})
// String properties
text = "hello"
textLength = text.length // 5
// Spread operator
arr1 = [1, 2, 3]
arr2 = [4, 5, 6]
combined = [...arr1, ...arr2] // [1, 2, 3, 4, 5, 6]
Objects
// Object creation
person = {
name: "Alice",
age: 30,
city: "New York"
}
// Property access
name1 = person.name // Dot notation
name2 = person["name"] // Bracket notation
// Nested objects
data = {
user: {
profile: {
name: "Bob",
settings: {
theme: "dark"
}
}
}
}
// Property access chain
theme = data.user.profile.settings.theme
// Optional chaining
value = data?.user?.profile?.nickname // Returns undefined if any part is null/undefined
// Spread in objects
defaults = {theme: "light", fontSize: 16}
userPrefs = {theme: "dark"}
settings = {...defaults, ...userPrefs} // {theme: "dark", fontSize: 16}
Destructuring
Array Destructuring
// Basic array destructuring
[a, b, c] = [1, 2, 3]
// a = 1, b = 2, c = 3
// With rest element
[first, ...rest] = [1, 2, 3, 4, 5]
// first = 1, rest = [2, 3, 4, 5]
// Skipping elements
[, , third] = [1, 2, 3]
// third = 3
// In function parameters
sumFirst2 = ([a, b]) => a + b
result = sumFirst2([10, 20, 30]) // 30
Object Destructuring
// Basic object destructuring
{name, age} = {name: "Alice", age: 30, city: "NYC"}
// name = "Alice", age = 30
// With different variable names
{name: personName, age: personAge} = {name: "Bob", age: 25}
// personName = "Bob", personAge = 25
// With defaults
{name, role = "user"} = {name: "Charlie"}
// name = "Charlie", role = "user"
// Nested destructuring
{user: {name, email}} = {user: {name: "David", email: "d@test.com"}}
// name = "David", email = "d@test.com"
// Rest in objects
{a, ...others} = {a: 1, b: 2, c: 3}
// a = 1, others = {b: 2, c: 3}
Built-in Functions
Prism provides a rich set of built-in functions for common operations:
Output and Debugging
// Simple print function
print("Hello, World!")
print("Answer:", 42, "is", true) // Hello, World! Answer: 42 is true
// Console functions
console.log("Information message")
console.warn("Warning message")
console.error("Error message")
console.debug("Debug information")
// Confidence values in output
value = 100 ~> 0.85
print("Confident value:", value) // Confident value: 100 ~> 0.85
console.log("Analysis:", analysis) // Shows confidence levels
Array Operations
// Global array functions
numbers = [1, 2, 3, 4, 5]
doubled = map(numbers, x => x * 2) // [2, 4, 6, 8, 10]
evens = filter(numbers, x => x % 2 == 0) // [2, 4]
sum = reduce(numbers, (a, b) => a + b, 0) // 15
// Mathematical functions
values = [10, 20, 5, 30, 15]
maximum = max(...values) // 30
minimum = min(...values) // 5
Parameterized Primitives
Prism supports type-parameterized primitives for type-safe operations:
// Array operations with type parameters
numbers = [3, 1, 4, 1, 5]
sorted = sort<number>(numbers, (a, b) => a - b)
filtered = filter<number>(numbers, n => n > 2)
// Working with complex types
users = [
{name: "Alice", age: 30},
{name: "Bob", age: 25}
]
adults = filter<{name: string, age: number}>(users, u => u.age >= 18)
sortedByAge = sort<{name: string, age: number}>(users, (a, b) => a.age - b.age)
// Map with type transformation
squared = map<number, number>(numbers, n => n * n)
names = map<{name: string}, string>(users, u => u.name)
// Reduce with accumulator type
sum = reduce<number, number>(numbers, 0, (acc, n) => acc + n)
concatenated = reduce<string, string>(names, "", (acc, name) => acc + ", " + name)
// First-class function behavior
// Create confidence-wrapped functions
confidenceWrapper = confidence(0.8)
processor = x => x * 2
confidentProcessor = confidenceWrapper(processor)
result = confidentProcessor(10) // 20 ~> 0.80
// Create threshold filters
highConfidenceFilter = threshold(0.9)
data = [10 ~> 0.95, 20 ~> 0.7, 30 ~> 0.92]
filtered = highConfidenceFilter(data) // [10 ~> 0.95, 30 ~> 0.92]
// Create parameterized sorters
scoreSorter = sortBy("score", "desc")
users = [{name: "Alice", score: 85}, {name: "Bob", score: 92}]
sorted = scoreSorter(users) // Sorted by score descending
// Create grouping functions
categoryGrouper = groupBy("category")
items = [{name: "Apple", category: "fruit"}, {name: "Carrot", category: "vegetable"}]
grouped = categoryGrouper(items) // Grouped by category
Import/Export System
// Importing functions and values
import {sum, multiply, PI} from "./math.prism"
import * as utils from "./utilities.prism"
// Using imported functions
result1 = sum(10, 20)
result2 = multiply(5, PI)
result3 = utils.formatNumber(123.456)
// Export declarations
export const VERSION = "1.0.0"
export function calculateArea(radius) {
return PI * radius * radius
}
// Re-exports
export {PI, sqrt} from "./math.prism"
export * from "./constants.prism"
Advanced Features
Confidence Expressions
// Basic confidence annotation
value = "high quality data" ~> 0.95
// Accessing confidence
conf = ~value // 0.95
// Extracting value from confident expression
rawValue = <~ value // "high quality data"
Context Statements
// Define a context
context experiment {
// Code within experimental context
result = performExperiment()
}
// Context with shift
context production shifting to staging {
// Start in production context, shift to staging
data = fetchData()
}
Agent Declarations
// Simple agent
agent Assistant
// Agent with configuration
agent Expert {
confidence: 0.9,
role: "domain expert",
capabilities: ["analysis", "recommendation"]
}
Best Practices
-
Use meaningful variable names: Choose descriptive names that indicate the purpose of the variable
// Good
userAge = 25
isLoggedIn = true
// Avoid
x = 25
flag = true -
Choose appropriate variable declarations: Use
const
for immutable values,let
for mutable variables// Good - immutable constants
const API_URL = "https://api.example.com"
const users = [{name: "Alice"}, {name: "Bob"}]
// Good - mutable variables
let currentPage = 1
let isLoading = false
// Traditional assignment for dynamic/computed values
result = processData(input) -
Leverage destructuring: Use destructuring to extract multiple values cleanly
// Instead of
x = point.x
y = point.y
// Use
const {x, y} = point
// With const/let for immutability clarity
const [first, second, ...rest] = array -
Choose the right function style: Use named functions for reusable logic, lambdas for inline operations
// Named functions for complex, reusable logic
function calculateRiskScore(data) {
const weights = [0.3, 0.4, 0.3]
const scores = data.map((item, i) => item * weights[i])
return scores.reduce((a, b) => a + b, 0)
}
// Expression lambdas for simple transformations
double = x => x * 2
// Block-statement lambdas for moderate complexity
validator = input => {
if (!input || input.length < 3) {
return false
}
return /^[a-zA-Z0-9]+$/.test(input)
} -
Use pipeline operators for transformations: Chain operations for better readability
result = data
|> filter(x => x > 0)
|> map(x => x * 2)
|> reduce((a, b) => a + b, 0)
// With parameterized primitives
result = data
|> threshold(0.8)(_) // Filter high-confidence items
|> sortBy("score")(_) // Sort by score
|> map(x => x.value) // Extract values -
Use print/console for debugging: Leverage output functions during development
// Debug intermediate results
function processData(input) {
console.debug("Processing input:", input)
const filtered = input.filter(x => x > 0)
print("Filtered:", filtered.length, "items")
const result = filtered.map(x => x * 2)
console.log("Final result:", result)
return result
} -
Leverage parameterized primitives: Create reusable, configurable functions
// Create specialized functions for your domain
const highQualityFilter = threshold(0.9)
const prioritySorter = sortBy("priority", "desc")
const statusGrouper = groupBy("status")
// Use in processing pipelines
result = data
|> highQualityFilter(_)
|> prioritySorter(_)
|> statusGrouper(_) -
Comment complex logic: Add comments to explain non-obvious code
// Calculate confidence based on inverse distance weighting
confidence = 1 / (1 + distance * decayFactor) -
Use confidence annotations judiciously: Apply confidence values where uncertainty is meaningful
// Sensor reading with measurement uncertainty
temperature = 23.5 ~> 0.92
// User input with validation confidence
email = userInput ~> validationScore
// LLM responses with model confidence
analysis = llm("Analyze sentiment: " + text) ~> 0.85 -
Handle asynchronous operations properly: Use async/await for clean asynchronous code
// Good - clear async flow
async function fetchUserData(userId) {
user = await getUserById(userId)
profile = await getProfile(user.profileId)
preferences = await getPreferences(user.id)
return {user, profile, preferences}
}
// Good - parallel operations with Promise.all
async function fetchAllData(userId) {
[user, posts, comments] = await Promise.all([
getUserById(userId),
getUserPosts(userId),
getUserComments(userId)
])
return {user, posts, comments}
}
// Good - async with confidence
async function analyzeWithRetry(data) ~> 0.95 {
result = await llm("Analyze: " + data)
if (!result.success) {
await delay(1000)
result = await llm("Retry analysis: " + data)
}
return result
} -
Organize code with imports/exports: Structure larger projects with modules
// utils.prism - utility functions
export const formatCurrency = amount => "$" + amount.toFixed(2)
export function validateEmail(email) {
return /\S+@\S+\.\S+/.test(email)
}
// main.prism - main application logic
import {formatCurrency, validateEmail} from "./utils.prism"
function processOrder(order) {
if (!validateEmail(order.email)) {
return false
}
console.log("Total:", formatCurrency(order.total))
return true
}