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"