Homework Assignment 6
Recursion and Language Processing
CS 3540
Programming Languages and Paradigms
Spring Semester 2023
Due: Tuesday, March 4 at 10:00 AM
Introduction
This assignment asks you to write even more recursive functions in
Racket. The goals of this assignment are to gain more experience
with common recursion patterns and to begin applying them to
programming language topics. For this assignment:
- Template Source File
Download the zipped directory
that contains templates for your solutions and your file of
Rackunit tests. Please use the given names as the
names of the files you submit, and don't modify the
provide or require clauses in any of the files.
With provide, you must define all five functions.
If you don't have time to solve a problem, define a function that
takes the correct number of arguments and returns a legal default
value, such as 0 or '().
The zip file also includes two files that contain helper functions
we saw in class. Keep them in the folder with your solutions and
tests. You will not submit these files.
As always, please use the assigned names for the two files you do
submit, homework06.rkt and
homework06-tests.rkt.
- Do Not Use...
- ... any of Racket's primitive higher-order functions
in any of your solutions, including map,
apply, and filter.
- ... any function that converts a list argument to another
datatype. Process the list.
- ... a let expression or an internal
define in any of your solutions.
- Organizing Code
- As before, put your solutions in homework06.rkt.
Put any helper functions you write for a problem after the
main function of your solution.
- As before, put your tests in homework06-tests.rkt
and, for each problem, write at least three Rackunit
expressions to test your solution. Depending on the type
of value that the function produces, use
check-equal? or
check-true/false. Test only the public
functions; helper functions are not visible outside your
solution module.
Problems
- Write a structurally recursive function
(list-index s los) that takes two arguments,
a symbol and a list of symbols. list-index
returns the 0-based first occurrence of s in
los. If s does not occur in the list, it
returns -1. For example:
> (list-index 'd '(a b c d e f d))
3
- Write a structurally recursive function named
(tree-sum bin-tree) that takes as an argument
a binary tree bin-tree of this form:
<binary-tree> ::= <number>
| (<number> <binary-tree> <binary-tree>)
tree-sum returns the sum of all the values in the
tree. For example:
> (tree-sum '(1 (2 3 4) 5))
15
> (tree-sum '(8 (13 11 (5 24 6)) (15 (12 10 14) 20)))
138
Note: You do not need an accumulator variable
for this problem! Simple structural recursion is your friend.
- Write a structurally recursive function named
(tree? exp)
that takes one argument, which can be any Racket expression.
(tree? exp) returns true if exp is a
bin-tree as defined for Problem 2, and false otherwise.
For example:
> (tree? '1)
#t
> (tree? '(8 (13 11 (5 24 6)) (15 (12 10 14) 20)))
#t
> (tree? 'x) ; not a number
#f
> (tree? '(1 (2 3 4) (2 3 4 5))) ; too many items in a tree
#f
> (tree? '(8 (13 x (5 24 6)) (15 (12 10 14) 20))) ; contains non-number
#f
This is your second type predicate. Follow the datatype for
this problem! Simple structural recursion is your friend.
- Write a structurally recursive function
(unused-var? v exp) that takes as input a symbol
and an expression in the the little language from class:
<exp> ::= <varref>
| (lambda (<var>) <exp>)
| (<exp> <exp>)
unused-var? returns true if v is
declared as a variable anywhere in exp and never
used. Recall that only lambda expressions can
declare a variable. For example:
; x is declared and not used
> (unused-var? 'x '(lambda (x) y))
#t
; x is declared *and* used
> (unused-var? 'x '(lambda (y) (lambda (x) x)))
#f
; ... but y is declared and not used
> (unused-var? 'y '(lambda (y) (lambda (x) x)))
#t
; here, x is declared and used in the app's argument
> (unused-var? 'x '(a (lambda (z) (lambda (y) (lambda (x) x)))))
#f
Three quick notes:
- unused-var? will need to know if a variable
does not occur free in an expression, so it should
call occurs-free?. Have your source file
require the occurs-procs.rkt file from
class.
- You must use the syntax procedures for the
little language when you define your function. Have your
source file require the syntax-procs.rkt
file from class.
- Don't forget that applications and lambda
expressions may contain lambda expressions.
But then, if you follow the BNF description, you already know
that!
Deliverables
By the due time and date,
submit
the following files:
- homework06.rkt, the source file containing your
function definitions
- homework06-tests.rkt, the source file containing
your test cases
Be sure that your submission follows the
submission requirements.
Eugene Wallingford .....
wallingf@cs.uni.edu .....
February 28, 2023