Starklings04-Cairo: If

Extropy.IO
5 min readAug 5, 2024

We’re back with another article of Starklings Cairo. In this installment, we’ll explore if, the most basic (but still surprisingly versatile!) type of control flow. If you haven't seen our other articles, you can start with these: Variables in Cairo and Primitive Types in Cairo as well as Felt Operations. Understanding how to use if expressions is fundamental for controlling the flow of your programs and making decisions based on conditions.

Further information

  • If expressions — The Cairo book goes into more detail on how to use if and else as well as else if. We always recommend you go through the book as you are doing these exercises to help reinforce the concepts.

Alright let’s get started with these exercises!

if1.cairo

// if1.cairo
// Execute `starklings hint if1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn bigger(a: usize, b: usize) -> usize { // Complete this function to return the bigger number!
// Do not use:
// - another function call
// - additional variables
}
// Don't mind this for now :)
#[cfg(test)]
mod tests {
use super::bigger;
#[test]
fn ten_is_bigger_than_eight() {
assert(10 == bigger(10, 8), '10 bigger than 8');
}
#[test]
fn fortytwo_is_bigger_than_thirtytwo() {
assert(42 == bigger(32, 42), '42 bigger than 32');
}
}

First, we are tasked with completing the function to return the bigger number between a and b. We should not use another function call or additional variables. This seems simple enough, but as always let's take a look at the errors to keep on getting familiar with the output.

if1.cairo Errors

Compiling test(exercise_crate_unittest) exercise_crate v0.1.0 (/Users/desmo/repos/starklings/starklings-cairo1/runner-crate/Scarb.toml)
error: Unexpected return type. Expected: "core::integer::u32", found: "()".
--> /Users/desmo/repos/starklings/starklings-cairo1/runner-crate/src/lib.cairo:6:40
fn bigger(a: usize, b: usize) -> usize { // Complete this function to return the bigger number! ^******************************************************

The error indicates that the function does not return the expected type, which means we haven’t implemented the return logic yet.

if1.cairo Solution

To solve this, we’ll use a simple if expression to compare a and b:

fn bigger(a: usize, b: usize) -> usize {
b
} else {
a
}
}

Explanation

In this very simple exercise, we can see how to use the if expression to check which variable is bigger, a or b. The function bigger takes two parameters, a and b, both of type usize.

  1. Comparison: The if statement checks the condition if a < b to compare the two variables.
  • If the condition is true (meaning a is less than b), the function executes the code block inside the if statement and returns b.
  • If the condition is false (meaning a is not less than b), the function executes the code block inside the else statement and returns a.

2. Control Flow:

  • When a is less than b, the function returns b, as b is the larger number.
  • When a is greater than or equal to b, the function returns a, as a is the larger number or equal to b.

This simple logic ensures that the function always returns the bigger of the two numbers without using any additional variables or function calls. This approach is efficient and straightforward, demonstrating the basic use of if and else in control flow. The function effectively selects the larger of the two numbers without any unnecessary complexity.

Great, let’s move on to the next one…

if2.cairo

// if2.cairo
// Step 1: Make me compile!
// Step 2: Get the bar_for_fuzz and default_to_baz tests passing!
// Execute `starklings hint if2` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn foo_if_fizz(fizzish: felt252) -> felt252 {
// Complete this function using if, else if and/or else blocks.
// If fizzish is,
// 'fizz', return 'foo'
// 'fuzz', return 'bar'
// anything else, return 'baz'
if fizzish == 'fizz' {
'foo'
} else {
1_u32
}
}
// No test changes needed!
#[cfg(test)]
mod tests {
use super::foo_if_fizz;
#[test]
fn foo_for_fizz() {
assert(foo_if_fizz('fizz') == 'foo', 'fizz returns foo')
}
#[test]
fn bar_for_fuzz() {
assert(foo_if_fizz('fuzz') == 'bar', 'fuzz returns bar');
}
#[test]
fn default_to_baz() {
assert(foo_if_fizz('literally anything') == 'baz', 'anything else returns baz');
}
}

This is a classic coding problem that gets us working with if expressions to return different values based on the input. Such problems are fundamental for understanding how conditional statements work in programming.

Using if, else if, and else statements, you can make your program react differently depending on the input it receives. This is crucial for creating dynamic and flexible applications. In this particular exercise, we are asked to implement a function that returns different outputs based on the value of the input parameter. This teaches us how to chain multiple conditions together and handle various scenarios in a structured manner.

if2.cairo Errors

Compiling test(exercise_crate_unittest) exercise_crate v0.1.0 (/Users/desmo/repos/starklings/starklings-cairo1/runner-crate/Scarb.toml)
error: Unexpected return type. Expected: "core::felt252", found: "?0".
--> /Users/desmo/repos/starklings/starklings-cairo1/runner-crate/src/lib.cairo:9:45
fn foo_if_fizz(fizzish: felt252) -> felt252 {
^
⚠️ Testing of exercises/if/if2.cairo failed! Please try again. Here's the output:

The error indicates that the return type of the function is incorrect. This means our function isn’t returning the expected felt252 values.

if2.cairo Solution

So, let’s go ahead and solve this:

fn foo_if_fizz(fizzish: felt252) -> felt252 {
if fizzish == 'fizz' {
'foo'
} else if fizzish == 'fuzz' {
'bar'
} else {
'baz'
}
}

Explanation

  1. If Expression:
  • We use an if expression to check if fizzish is equal to 'fizz'. If it is, we return 'foo'.

2. Else If Expression:

  • We use an else if expression to check if fizzish is equal to 'fuzz'. If it is, we return 'bar'.

3. Else Expression:

  • If fizzish is neither 'fizz' nor 'fuzz', we return 'baz'.

This pattern is very common in control flow, where multiple conditions need to be checked sequentially.

Conclusion

In this post, we went into the basics of using if expressions in Cairo. We started with a simple exercise to determine the bigger of two numbers using an if expression. Then, we moved on to a slightly more complex problem where we used if, else if, and else blocks to return different values based on the input.

Understanding how to use if expressions is crucial for controlling the flow of your programs and making decisions based on conditions. By mastering these basics, you can build more complex and dynamic applications in Cairo.

Stay tuned for more exercises with the Cairo programming language in our upcoming articles.

--

--

Extropy.IO

Oxford-based blockchain and zero knowledge consultancy and auditing firm