Skip to main content

Practice Problems: Variable Scope (Pyret & Python)

Solutions are found at the bottom of the page!

Problem 1: Basic Scope Understanding

Problem Statement: Understand the difference between global and local variables by predicting the output of code snippets.

Part A: Pyret Scope For each Pyret code snippet, predict what will be printed or if there will be an error.

# Snippet 1
global-value = 10

fun test-function(x :: Number) -> Number:
local-value = 5
x + local-value + global-value
end

result = test-function(3)
# What is the value of `result`?

# Snippet 2
name = "Alice"

fun greet() -> String:
name + " says hello!"
end

greeting = greet()
# What is the value of `greeting`?

# Snippet 3
var counter = 0

fun increment() -> Number block:
counter := counter + 1
counter
end

first-call = increment()
second-call = increment()
# What are the values of `first-call` and `second-call`?

Part B: Python Scope For each Python code snippet, predict what will be printed or if there will be an error.

# Snippet 1
global_value = 10

def test_function(x):
local_value = 5
return x + local_value + global_value

result = test_function(3)
# What is the value of `result`?

# Snippet 2
name = "Alice"

def greet():
return name + " says hello!"

greeting = greet()
# What is the value of `greeting`?

# Snippet 3
counter = 0

def increment():
counter = counter + 1 # Will this work?
return counter

# What happens when we call `increment()`?

Problem 2: Pyret vs Python Comparison

Problem Statement: Compare how the same functionality is implemented in Pyret and Python.

Task: Bank Account Simulation Implement the same bank account functionality in both languages:

Pyret Version:

# PYRET
var account-balance = 1000.0
var transaction-count = 0

fun deposit(amount :: Number) -> Number:
# Add amount to balance, increment transaction count
# Return new balance
end

fun withdraw(amount :: Number) -> Number:
# Subtract amount if sufficient funds
# Increment transaction count
# Return new balance or raise error
end

fun get-balance() -> Number:
# Return current balance without modifying it
end

fun get-transaction-count() -> Number:
# Return number of transactions
end

fun reset-account() -> String:
# Reset balance to 1000 and transaction count to 0
# Return confirmation message
end

Python Version:

# PYTHON
account_balance = 1000.0
transaction_count = 0

def deposit(amount):
# Add amount to balance, increment transaction count
# Return new balance
pass

def withdraw(amount):
# Subtract amount if sufficient funds
# Increment transaction count
# Return new balance or raise error
pass

def get_balance():
# Return current balance without modifying it
pass

def get_transaction_count():
# Return number of transactions
pass

def reset_account():
# Reset balance to 1000 and transaction count to 0
# Return confirmation message
pass

Solutions

Problem 1:

Part A: Pyret Scope

# result in 18 (3 + 5 + 10)
# greeting is "Alice says hello!"
# first-call is 1, second-call is 2

Part B: Python Scope

# result is 18 (3 + 5 + 10)
# greeting is "Alice says hello!"

def increment():
counter = counter + 1 # UnboundLocalError
return counter

# The above raises UnboundLocalError because Python sees the assignment and treats counter as local, but tries to read it before assignment

Problem 2:

Pyret Version:

var account-balance = 1000.0
var transaction-count = 0

fun deposit(amount :: Number) -> Number:
doc: "deposits amount into account"
if amount > 0 block:
account-balance := account-balance + amount
transaction-count := transaction-count + 1
account-balance
else:
raise("Deposit amount must be positive")
end
where:
account-balance := 1000.0
transaction-count := 0

deposit(100) is 1100.0
deposit(50) is 1150.0
transaction-count is 2
end

fun withdraw(amount :: Number) -> Number:
doc: "withdraws amount from account if sufficient funds"
if amount > 0:
if account-balance >= amount block:
account-balance := account-balance - amount
transaction-count := transaction-count + 1
account-balance
else:
raise("Insufficient funds")
end
else:
raise("Withdrawal amount must be positive")
end
where:
account-balance := 1000.0
transaction-count := 0

withdraw(100) is 900.0
withdraw(50) is 850.0
transaction-count is 2
end

fun get-balance() -> Number:
doc: "returns current balance without modifying it"
account-balance
where:
account-balance := 500.0
get-balance() is 500.0
end

fun get-transaction-count() -> Number:
doc: "returns number of transactions"
transaction-count
end

fun reset-account() -> String block:
doc: "resets balance to 1000 and transaction count to 0"
account-balance := 1000.0
transaction-count := 0
"Account reset successfully"
where:
reset-account() is "Account reset successfully"
get-balance() is 1000.0
get-transaction-count() is 0
end

Python Version:

account_balance = 1000.0
transaction_count = 0

def deposit(amount):
"""deposits amount into account"""
global account_balance, transaction_count
if amount > 0:
account_balance += amount
transaction_count += 1
return account_balance
else:
raise ValueError("Deposit amount must be positive")

def withdraw(amount):
"""withdraws amount from account if sufficient funds"""
global account_balance, transaction_count
if amount > 0:
if account_balance >= amount:
account_balance -= amount
transaction_count += 1
return account_balance
else:
raise ValueError("Insufficient funds")
else:
raise ValueError("Withdrawal amount must be positive")

def get_balance():
"""returns current balance without modifying it"""
return account_balance

def get_transaction_count():
"""returns number of transactions"""
return transaction_count

def reset_account():
"""resets balance to 1000 and transaction count to 0"""
global account_balance, transaction_count
account_balance = 1000.0
transaction_count = 0
return "Account reset successfully"