tags:
- control-flow
- if-else
- while
- loops
- ternary
Control Flow¶
Control flow statements determine the order in which code executes. EverSharp provides conditional statements and loops.
If Statement¶
Basic If¶
Example:
If-Else¶
Example:
If-Else-If Chain¶
if (condition1) {
// Execute if condition1 is true
} else if (condition2) {
// Execute if condition2 is true
} else if (condition3) {
// Execute if condition3 is true
} else {
// Execute if all conditions are false
}
Example:
score = 85;
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else if (score >= 70) {
grade = "C";
} else if (score >= 60) {
grade = "D";
} else {
grade = "F";
}
Single-Line If¶
Braces are optional for single statements:
if (isActive) status = "Active";
if (count > 0) $Log("Items found");
if (premium > maxPremium) premium = maxPremium;
Note: While allowed, braces are recommended for clarity.
Nested If¶
if (age >= 18) {
if (hasLicense) {
if (!hasSuspension) {
canDrive = true;
} else {
canDrive = false;
}
}
}
Better with logical operators:
Condition Requirements¶
The condition must evaluate to a boolean:
// CORRECT: Boolean conditions
if (age > 18) {
}
if (isActive) {
}
if (count == 0) {
}
if (name != null) {
}
// ERROR: Non-boolean conditions
// if (count) { } // ERROR: number not boolean
// if (name) { } // ERROR: string not boolean
// if (object) { } // ERROR: object not boolean
While Loop¶
Basic While¶
Example:
Infinite Loop¶
Note: EverSharp has no break statement, so use with caution.
Loop with Complex Condition¶
attempts = 0;
maxAttempts = 3;
success = false;
while (attempts < maxAttempts && !success) {
success = tryOperation();
attempts++;
}
Manual Array Iteration¶
items = [10, 20, 30, 40, 50];
index = 0;
while (index < items.Length) {
$Log(items[index]);
index++;
}
Better alternative: Use array methods
Exit Statement¶
Immediate Script Termination¶
The exit statement immediately terminates the entire script execution, regardless of where it's called:
Example - Basic Exit:
Exit in Conditionals¶
if (error) {
$Log("Critical error detected");
exit;
}
$Log("Continuing..."); // Not reached if error is true
Exit in Loops¶
i = 0;
total = 0;
while (i < 10) {
total = total + i;
if (i == 5) {
exit; // Terminates entire script, not just loop
}
i = i + 1;
}
Exit vs Return¶
Key Differences:
| Feature | return |
exit |
|---|---|---|
| Scope | Exits current function | Exits entire script |
| Value | Can return a value | No return value |
| Usage | Functions only | Anywhere in script |
Example:
function validate(data) {
if (data == null) {
exit; // Terminates entire script
}
return true; // Returns from function only
}
result = validate(myData);
$Log("After function"); // Not reached if exit was called
When to Use Exit¶
Good use cases:
- Critical validation failures
- Unrecoverable error conditions
- Safety limits exceeded
- Early termination based on business rules
Example - Safety Check:
Throw Statement¶
Error Handling with Throw¶
The throw statement immediately terminates script execution and raises a runtime error with a custom message:
Example - Basic Throw:
counter = 0;
counter = counter + 1;
throw "Something went wrong";
counter = counter + 100; // Never executed
Throw with Dynamic Messages¶
You can use any expression that evaluates to a value:
age = -5;
throw "Invalid age: " + age;
// Error: Invalid age: -5
errorCode = 404;
throw errorCode;
// Error: 404
value = -10;
throw value < 0 ? "Negative value" : "Positive value";
// Error: Negative value
Throw in Conditionals¶
if (age < 0) {
throw "Age cannot be negative";
}
if (premium > maxPremium) {
throw "Premium exceeds maximum: " + premium;
}
Throw in Loops¶
i = 0;
total = 0;
while (i < 10) {
total = total + i;
if (i == 5) {
throw "Error at iteration " + i; // Terminates entire script
}
i = i + 1;
}
Throw in Functions¶
function validateAge(age) {
if (age < 0) {
throw "Age cannot be negative: " + age;
}
if (age > 150) {
throw "Age is unrealistic: " + age;
}
return true;
}
// This will throw an error
result = validateAge(-5);
$Log("After validation"); // Not reached
Throw vs Exit vs Return¶
Key Differences:
| Feature | return |
exit |
throw |
|---|---|---|---|
| Scope | Exits current function | Exits entire script | Exits entire script |
| Value | Can return a value | No return value | Error message |
| Error | No | No | Yes |
| Usage | Functions only | Anywhere in script | Anywhere in script |
| Detection | N/A | Normal termination | Adds error to Errors list |
Example Comparison:
function processData(data) {
// Return - exits function normally
if (data == null) {
return null;
}
// Exit - terminates script normally
if (data.critical && !data.valid) {
$Log("Critical data invalid, stopping");
exit;
}
// Throw - terminates script with error
if (data.value < 0) {
throw "Data value cannot be negative: " + data.value;
}
return process(data);
}
When to Use Throw¶
Good use cases:
- Input validation errors
- Business rule violations
- Invalid state detection
- Constraint violations
- Data integrity issues
Example - Validation Pattern:
function calculatePremium(age, coverage) {
// Validate inputs
if (age < 18) {
throw "Applicant must be 18 or older";
}
if (age > 100) {
throw "Age exceeds maximum: " + age;
}
if (coverage <= 0) {
throw "Coverage amount must be positive";
}
if (coverage > 10000000) {
throw "Coverage exceeds maximum: $10,000,000";
}
// Calculate premium
basePremium = coverage * 0.001;
ageFactor = age > 65 ? 1.5 : 1.0;
return basePremium * ageFactor;
}
Error Detection in Host Application¶
When using EverSharpRunner, thrown errors can be detected:
var runner = new EverSharpRunner();
runner.Run(@"
age = -5;
throw ""Invalid age: "" + age;
");
if (runner.HasErrors) {
foreach (var error in runner.Errors) {
Console.WriteLine($"Error: {error}");
// Output: Error: Invalid age: -5
}
}
No Break or Continue¶
EverSharp does not support break or continue statements.
Workarounds¶
Instead of break:
// Using flag
found = false;
index = 0;
while (index < items.Length && !found) {
if (items[index] == target) {
found = true;
} else {
index++;
}
}
// Better: Use .Find()
item = items.Find((x) => x == target);
Instead of continue:
// Using conditional
index = 0;
while (index < items.Length) {
if (items[index] % 2 == 0) {
// Process even numbers
process(items[index]);
}
index++;
}
// Better: Use .Filter()
items.Filter((x) => x % 2 == 0).ForEach((x) => process(x));
No For Loop¶
EverSharp does not have a for loop.
Alternatives¶
Use while:
Use array methods (preferred):
// Instead of for loop
numbers = [1, 2, 3, 4, 5];
// Map
doubled = numbers.Map((x) => x * 2);
// Filter
evens = numbers.Filter((x) => x % 2 == 0);
// ForEach
numbers.ForEach((n) => $Log(n));
// Reduce
sum = numbers.ReduceToNum((acc, x) => acc + x, 0);
Ternary Operator¶
A compact alternative to if-else for simple assignments:
Examples:
// Simple assignment
status = age >= 18 ? "Adult" : "Minor";
// In calculations
discount = isPremium ? 0.2 : 0.1;
premium = basePremium * (age > 65 ? 1.25 : 1.0);
// With expressions
max = a > b ? a : b;
min = a < b ? a : b;
When to use:
- Simple conditions
- Single value assignment
- Inline calculations
When to avoid:
- Complex logic
- Multiple statements
- Nested ternaries (hard to read)
Block Statements¶
Blocks group multiple statements:
With if:
if (premium > threshold) {
discount = premium * 0.1;
premium = premium - discount;
$Log("Discount applied: " + discount);
}
With while:
Standalone (creates new scope):
{
tempValue = expensiveCalculation();
result = processValue(tempValue);
$Log("Processed: " + result);
}
// tempValue out of scope here
Common Patterns¶
Pattern 1: Range Checking¶
if (age >= 18 && age <= 65) {
premium = standardPremium;
} else if (age < 18) {
premium = youthPremium;
} else {
premium = seniorPremium;
}
Pattern 2: Null Checking¶
if (object != null) {
if (object.property != null) {
value = object.property.value;
}
}
// Or combined
if (object != null && object.property != null) {
value = object.property.value;
}
Pattern 3: Validation¶
hasErrors = false;
errorMessage = "";
if (age < 18) {
hasErrors = true;
errorMessage = "Must be 18 or older";
} else if (premium > maxPremium) {
hasErrors = true;
errorMessage = "Premium exceeds maximum";
}
if (!hasErrors) {
// Process
}
Pattern 4: Accumulation¶
Pattern 5: Early Return¶
function validate(data) {
if (data == null) {
return false;
}
if (data.age < 18) {
return false;
}
if (data.premium > maxPremium) {
return false;
}
return true;
}
Pattern 6: State Machine¶
state = "INIT";
while (state != "DONE") {
if (state == "INIT") {
initialize();
state = "PROCESSING";
} else if (state == "PROCESSING") {
if (process()) {
state = "COMPLETE";
} else {
state = "ERROR";
}
} else if (state == "COMPLETE") {
finalize();
state = "DONE";
} else if (state == "ERROR") {
handleError();
state = "DONE";
}
}
Control Flow with Functions¶
Conditional Execution¶
function processOrder(order) {
if (order.total < minOrderAmount) {
return null;
}
if (order.customer == null) {
return null;
}
// Process order
result = calculateTotal(order);
return result;
}
Loop with Function¶
function sumArray(arr) {
sum = 0;
index = 0;
while (index < arr.Length) {
sum += arr[index];
index++;
}
return sum;
}
Recursive Control Flow¶
function factorial(n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
result = factorial(5); // 120
Best Practices¶
1. Use Array Methods Instead of Loops¶
// Less ideal
sum = 0;
i = 0;
while (i < numbers.Length) {
sum += numbers[i];
i++;
}
// Better
sum = numbers.ReduceToNum((acc, x) => acc + x, 0);
2. Keep Conditions Simple¶
// Complex
if ((age >= 18 && age <= 65 && hasLicense) || (age > 65 && hasSpecialPermit && !hasSuspension)) {
// ...
}
// Better: break into parts
isStandardEligible = age >= 18 && age <= 65 && hasLicense;
isSeniorEligible = age > 65 && hasSpecialPermit && !hasSuspension;
if (isStandardEligible || isSeniorEligible) {
// ...
}
3. Avoid Deep Nesting¶
// Deeply nested
if (a) {
if (b) {
if (c) {
if (d) {
// ...
}
}
}
}
// Better: early returns
if (!a) return;
if (!b) return;
if (!c) return;
if (!d) return;
// ...
4. Use Ternary for Simple Cases¶
// Verbose
if (age >= 18) {
status = "Adult";
} else {
status = "Minor";
}
// Concise
status = age >= 18 ? "Adult" : "Minor";
5. Always Use Braces¶
6. Check Boolean Conditions Explicitly¶
// Correct (EverSharp requires explicit boolean)
if (count > 0) {
}
if (name != null && name != "") {
}
if (isActive == true) {
} // Or just: if (isActive) { }
// Would be errors in EverSharp
// if (count) { }
// if (name) { }
Common Mistakes¶
Mistake 1: Using Non-Boolean Conditions¶
Mistake 2: Expecting Break/Continue¶
// ERROR: break doesn't exist
// while (true) {
// if (found) break;
// }
// CORRECT: use flag
found = false;
while (!found) {
if (condition) {
found = true;
}
}
Mistake 3: Using For Loop¶
// ERROR: for doesn't exist
// for (i = 0; i < 10; i++) {
// $Log(i);
// }
// CORRECT: use while
i = 0;
while (i < 10) {
$Log(i);
i++;
}
Mistake 4: Forgetting Loop Increment¶
// ERROR: Infinite loop
// counter = 0;
// while (counter < 10) {
// $Log(counter);
// // Forgot: counter++;
// }
// CORRECT
counter = 0;
while (counter < 10) {
$Log(counter);
counter++; // Don't forget!
}
Mistake 5: Assignment in Condition¶
// ERROR: Assignment returns value, not boolean
// if (x = 10) { }
// CORRECT: Use comparison
if (x == 10) {
}
// Or if you meant assignment then check:
x = 10;
if (x > 5) {
}
Advanced Examples¶
Example 1: Premium Calculation¶
function calculatePremium(age, coverage, history) {
basePremium = coverage * 0.01;
// Age adjustment
if (age < 25) {
basePremium *= 1.5;
} else if (age > 65) {
basePremium *= 1.25;
}
// Coverage tier adjustment
if (coverage > 500000) {
basePremium *= 1.1;
} else if (coverage < 100000) {
basePremium *= 0.9;
}
// History adjustment
if (history == "excellent") {
basePremium *= 0.8;
} else if (history == "poor") {
basePremium *= 1.3;
}
return $Round(basePremium, 2);
}
Example 2: Data Validation¶
function validatePolicy(policy) {
errors = [];
if (policy == null) {
errors.Push("Policy is null");
return errors;
}
if (policy.number == null || policy.number == "") {
errors.Push("Policy number required");
}
if (policy.premium <= 0) {
errors.Push("Premium must be positive");
}
if (policy.customer == null) {
errors.Push("Customer required");
} else {
if (policy.customer.age < 18) {
errors.Push("Customer must be 18 or older");
}
}
return errors;
}
errors = validatePolicy(myPolicy);
if (errors.Length > 0) {
$Log("Validation errors:");
errors.ForEach((err) => $Log(" - " + err));
}
Example 3: Batch Processing¶
function processBatch(items) {
successCount = 0;
failureCount = 0;
index = 0;
while (index < items.Length) {
item = items[index];
if (item != null && item.isValid) {
if (processItem(item)) {
successCount++;
} else {
failureCount++;
}
}
index++;
}
return {
success: successCount,
failure: failureCount,
total: items.Length,
};
}
Next Steps¶
- Learn functions: Functions
- Explore lambda expressions: Lambda Expressions
- See examples: Examples