Control Flow
Prism extends traditional control flow constructs with confidence-aware capabilities, enabling programs to make decisions based on uncertainty levels. This guide covers all control flow mechanisms, from basic conditionals to advanced uncertain branching.
Traditional Control Flow
If Statements
Standard if statements work as expected:
// Basic if
let status = "cool"
if temperature > 30 {
status = "hot"
}
// If-else
let result = "fail"
if score >= 60 {
result = "pass"
}
// If-else if-else chains
let grade = "F"
if score >= 90 {
grade = "A"
} else if score >= 80 {
grade = "B"
} else if score >= 70 {
grade = "C"
} else if score >= 60 {
grade = "D"
}
// Nested conditions
if user.isAuthenticated {
if user.hasPermission("admin") {
showAdminPanel()
} else {
showUserDashboard()
}
} else {
redirectToLogin()
}
Ternary Operator
For simple conditional expressions:
// Basic ternary
let status = temperature > 30 ? "hot" : "cool"
// Nested ternary (use sparingly)
let grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "F"
// With confident values
let result = (confidence > 0.8) ?
processHighConfidence(data) :
requestManualReview(data)
Pattern Matching
Use match to branch on structure with guards and confidence thresholds:
let outcome = match input {
0 => "zero",
[x, y, ...rest] => rest,
{type: "error", message} => message,
x if x > 10 => "large",
_ => "fallback"
}
For full pattern syntax, see the Pattern Matching guide.
Loops
For Loops
// Traditional for loop
for let i = 0; i < 10; i = i + 1 {
console.log(i)
}
// With break
for let i = 0; i < 100; i = i + 1 {
if i == 50 {
break
}
process(i)
}
// With continue
for let i = 0; i < 100; i = i + 1 {
if i % 2 == 0 {
continue // Skip even numbers
}
processOdd(i)
}
For-In Loops
Iterate over collections:
// Iterate over array values
let numbers = [1, 2, 3, 4, 5]
for num in numbers {
console.log(num * 2)
}
// With index
for value, index in numbers {
console.log(`Index ${index}: ${value}`)
}
// Iterate over object properties
let person = {name: "Alice", age: 30, city: "NYC"}
for key in person {
console.log(`${key}: ${person[key]}`)
}
// Destructuring in loops
let points = [{x: 1, y: 2}, {x: 3, y: 4}, {x: 5, y: 6}]
for {x, y} in points {
let distance = Math.sqrt(x * x + y * y)
console.log(`Distance: ${distance}`)
}
While Loops
// Basic while loop
let count = 0
while count < 10 {
console.log(count)
count = count + 1
}
// With complex condition
let temperature = readSensor()
let time = 0
while temperature > threshold && time < maxTime {
adjustCooling()
temperature = readSensor()
time = time + 1
}
// Infinite loop with break
while true {
let input = getUserInput()
if input == "exit" {
break
}
processInput(input)
}
Do-While Loops
Execute at least once:
// Basic do-while
let attempts = 0
do {
let success = tryOperation()
attempts = attempts + 1
} while !success && attempts < maxAttempts
// User input validation
do {
let value = promptUser("Enter a positive number:")
} while value <= 0
Uncertain Control Flow
Uncertain If Statements
Branch based on confidence levels:
// Basic uncertain if
let data = fetchSensorData() ~> 0.75
uncertain if data {
high {
// Executes when confidence >= 0.7 (default threshold)
storeInDatabase(data)
}
medium {
// Executes when 0.5 <= confidence < 0.7
validateAndStore(data)
}
low {
// Executes when confidence < 0.5
logForManualReview(data)
}
}
// With explicit threshold
let prediction = model.predict(input) ~> confidence
uncertain if prediction > 0.8 { // Custom threshold
high {
executeTrade(prediction)
}
medium {
alertTrader(prediction)
}
low {
// Do nothing - too uncertain
}
}
// With default branch (like switch statement default)
let analysis = llm("Analyze this") ~> customConfidence
uncertain if analysis {
high {
deploy()
}
medium {
review()
}
low {
reject()
}
default {
// Executes when confidence doesn't match any threshold
// Useful for custom confidence levels or edge cases
log("Unexpected confidence level: ${customConfidence}")
requestHumanIntervention()
}
}
// Conditional confidence checking
let result = complexCalculation() ~> calcConfidence
uncertain if result {
high {
let finalResult = result
}
low {
// Fallback calculation with different method
finalResult = simpleCalculation() ~> 0.9
}
}
Uncertain Loops
Loops that behave differently based on confidence:
// Uncertain for loop
uncertain for let i = 0; i < dataPoints.length; i = i + 1 {
high {
// Process with full algorithm
results[i] = complexAnalysis(dataPoints[i])
}
medium {
// Process with simplified algorithm
results[i] = quickAnalysis(dataPoints[i])
}
low {
// Skip or use default
results[i] = defaultValue
}
}
// Uncertain while loop with default
let attempts = 0
uncertain while (attempts < maxAttempts) ~> 0.9 {
high {
let result = tryRiskyOperation()
if result.success {
break
}
attempts = attempts + 1
}
medium {
result = trySafeOperation()
attempts = attempts + 1
}
low {
// Too uncertain, abort
result = abortWithDefault()
break
}
default {
// Handle unexpected confidence levels
log("Unexpected confidence in loop")
attempts = attempts + 1
}
}
Default Branch
The default branch in uncertain constructs acts like a switch statement's default case, executing when the confidence level doesn't match any of the standard thresholds:
// Use cases for default branch
uncertain if (apiResponse) {
high { processNormally() }
medium { validateFirst() }
low { reject() }
default {
// Handles edge cases like:
// - Custom confidence thresholds
// - Undefined confidence
// - NaN confidence values
// - Confidence calculation errors
handleUnexpectedCase()
}
}
// Adaptive threshold adjustment
let threshold = 0.7
uncertain if (measurement) {
high {
// Confidence >= threshold
accept()
}
default {
// Confidence < threshold but not low enough for 'low'
// Adjust threshold for next iteration
threshold = threshold - 0.1
retry()
}
}
// Data gathering pattern
uncertain if (prediction) {
high { execute() }
low { abort() }
default {
// Medium confidence - gather more data
let additionalData = gatherMoreInfo()
reanalyze(additionalData)
}
}
The default branch ensures your uncertainty-aware code can gracefully handle all possible confidence scenarios.
Confidence in Conditions
Using confident values in conditions:
// Confident comparison
let temp1 = 25 ~> 0.9
let temp2 = 26 ~> 0.85
if temp1 ~< temp2 {
// Comparison considers confidence
console.log("temp1 is less than temp2")
}
// Confidence extraction in conditions
let measurement = readSensor() ~> sensorConfidence
if ~measurement > 0.8 {
// Check if confidence is high enough
processMeasurement(measurement)
}
// Combining confident conditions
let condition1 = checkCondition1() ~> 0.9
let condition2 = checkCondition2() ~> 0.8
if condition1 ~&& condition2 {
// Both conditions true with combined confidence
proceed()
}
Advanced Control Flow Patterns
Confidence-Based State Machines
// State machine with confidence transitions
let currentState = "idle"
let confidence = 1.0
let processEvent = (event) => {
uncertain if event ~> confidence {
high {
// Confident state transitions
if currentState == "idle" && event.type == "start" {
currentState = "active"
} else if currentState == "active" && event.type == "complete" {
currentState = "done"
}
}
medium {
// Cautious transitions
if currentState == "idle" && event.type == "start" {
currentState = "pending_confirmation"
}
}
low {
// No state change on low confidence
logUncertainEvent(event)
}
}
}
Early Exit Patterns
// Confidence gates for early exit
let processData = (data) => {
// Check confidence at entry
if ~data < 0.5 {
return null // Too uncertain
}
// Progressive validation
let validated = validate(data)
if ~validated < 0.7 {
return fallbackProcess(data)
}
// Full processing only for high confidence
return fullProcess(validated)
}
// Multiple exit points
let analyzeReading = (reading) => {
// Quick confidence check
if ~reading < 0.3 {
return {status: "rejected", reason: "too uncertain"}
}
// Validate range
if reading < minValue || reading > maxValue {
return {status: "out_of_range", value: reading}
}
// Process based on confidence
uncertain if reading {
high {
return {status: "processed", result: complexAnalysis(reading)}
}
medium {
return {status: "processed", result: simpleAnalysis(reading)}
}
low {
return {status: "queued", reason: "needs review"}
}
}
}
Nested Uncertain Control Flow
// Nested uncertain structures
let mainProcess = (input) => {
let primaryResult = primaryModel(input) ~> 0.8
uncertain if primaryResult {
high {
// High confidence in primary
return primaryResult
}
medium {
// Try secondary model
let secondaryResult = secondaryModel(input) ~> 0.7
uncertain if secondaryResult {
high {
return secondaryResult
}
low {
return combineResults(primaryResult, secondaryResult)
}
}
}
low {
// Fallback to ensemble
return ensembleModel(input) ~> 0.9
}
}
}
Practical Examples
Sensor Reading Validation
// Multi-stage sensor validation with confidence
let validateSensorReading = (reading) => {
// Stage 1: Range check
let inRange = (reading >= minTemp && reading <= maxTemp) ~> 0.95
// Stage 2: Rate of change check
let changeRate = abs(reading - lastReading) / timeInterval
let validChange = (changeRate < maxChangeRate) ~> 0.9
// Stage 3: Cross-validation with other sensors
let nearbyAvg = getNearbySensorAverage()
let deviation = abs(reading - nearbyAvg)
let consistent = (deviation < threshold) ~> 0.85
// Combined validation
let valid = inRange ~&& validChange ~&& consistent
uncertain if valid {
high {
updateReading(reading)
let lastReading = reading
}
medium {
// Additional verification needed
if confirmWithRedundantSensor(reading) {
updateReading(reading)
lastReading = reading
}
}
low {
// Reject reading, use interpolation
let interpolated = (lastReading + nextExpected) / 2
updateReading(interpolated ~> 0.7)
}
}
}
Adaptive Algorithm Selection
// Choose algorithm based on data confidence
let processDataAdaptively = (data) => {
let dataQuality = assessQuality(data) ~> 0.85
uncertain if dataQuality {
high {
// Use sophisticated ML model
let model = loadComplexModel()
let result = model.process(data)
// Verify result confidence
if ~result > 0.9 {
return result
} else {
// Even complex model uncertain, try ensemble
return ensembleProcess(data)
}
}
medium {
// Use robust statistical methods
let cleaned = robustClean(data)
result = statisticalAnalysis(cleaned)
return result ~> 0.7
}
low {
// Use simple heuristics
for rule in simpleRules {
if rule.matches(data) {
return rule.result ~> 0.5
}
}
return defaultResult ~> 0.3
}
}
}
Retry Logic with Confidence Decay
// Retry with decreasing confidence
let reliableOperation = (params) => {
let maxRetries = 5
let initialConfidence = 0.95
let decayFactor = 0.15
for let attempt = 0; attempt < maxRetries; attempt = attempt + 1 {
let confidence = initialConfidence * (1 - decayFactor * attempt)
let result = attemptOperation(params) ~> confidence
uncertain if result {
high {
// Success with high confidence
return result
}
medium {
// Partial success, maybe retry
if attempt < maxRetries - 1 {
wait(retryDelay * (attempt + 1))
continue
}
return result // Accept medium confidence on last try
}
low {
// Failed, definitely retry
if attempt < maxRetries - 1 {
adjustParams(params)
wait(retryDelay * (attempt + 1))
continue
}
return null ~> 0.1 // Give up
}
}
}
}
Decision Tree with Confidence
// Medical diagnosis decision tree
let diagnose = (symptoms) => {
// Check primary symptom
if symptoms.fever ~> 0.9 {
uncertain if symptoms.fever > 38.5 {
high {
// High fever with high confidence
if symptoms.cough ~> 0.8 {
return "possible flu" ~> 0.85
} else if symptoms.rash ~> 0.9 {
return "possible infection" ~> 0.8
}
}
medium {
// Moderate confidence in fever
return "monitor temperature" ~> 0.6
}
low {
// Uncertain about fever
return "recheck temperature" ~> 0.4
}
}
}
// Check secondary symptoms
uncertain if symptoms.fatigue ~> 0.7 {
high {
if symptoms.jointPain ~> 0.8 {
return "possible arthritis" ~> 0.75
}
}
low {
return "general checkup recommended" ~> 0.5
}
}
return "no clear diagnosis" ~> 0.3
}
Best Practices
-
Use uncertain control flow for genuine uncertainty: Don't overuse uncertain if/loops
// Good - actual uncertainty in data
uncertain if sensorReading {
high { processNormally() }
low { requestCalibration() }
}
// Avoid - no real uncertainty
uncertain if userAge > 18 {
high { allowAccess() } // This is just a regular condition
} -
Set appropriate confidence thresholds: Customize based on your domain
// Medical application - high threshold
uncertain if diagnosis > 0.9 {
high { recommendTreatment() }
low { requireSecondOpinion() }
}
// Recommendation system - lower threshold
uncertain if suggestion > 0.6 {
high { showToUser() }
low { skipSuggestion() }
} -
Handle all confidence levels: Always provide low confidence handling
uncertain if data {
high {
process()
}
medium {
validateAndProcess()
}
low {
// Don't leave empty - handle uncertainty
logForReview()
useDefault()
}
} -
Combine confidence checks efficiently: Avoid redundant checks
// Good - single confidence evaluation
result = complexCalculation() ~> confidence
uncertain if result {
high { useResult() }
low { recalculate() }
}
// Avoid - multiple evaluations
if ~result > 0.7 {
if ~result > 0.9 {
// ...
}
} -
Document confidence decisions: Explain threshold choices
// Investment decision - 0.85 threshold chosen based on
// historical accuracy of predictions above this level
uncertain if prediction > 0.85 {
high {
invest(amount * 0.8) // 80% position size
}
medium {
invest(amount * 0.3) // 30% position size
}
low {
// No investment below 50% confidence
logMissedOpportunity()
}
}