Racket Recursive Practices
This is actually a lab for my CSCC24 course (Principles of Programming Languages).
Racket is very different from popular programming languages, such as Python, C++.
Its concept is based on something called "functional programming", which I had never touched before.
Honestly, I think Racket is an interesting and elegant language, but it is a little hard to get used to.
This is my solution for the lab. I'm putting it here in case I forget some expressions one day. xD
#lang racket
(require test-engine/racket-tests)
(provide my-length my-reverse is-pal? num-els sum-els repeat-twice my-filter my-map)
;; (my-length xs) -> integer?
;; xs: list?
;; returns the length of xs
(define (my-length xs)
(if (null? xs) 0 (+ (my-length (rest xs)) 1))
)
;; (my-reverse xs) -> list?
;; xs: list?
;; returns the reverse of xs
(define (my-reverse xs)
(if (null? xs) '() (append (my-reverse (rest xs)) (list (first xs))))
)
;; (is-pal? xs) -> boolean?
;; xs: list?
;; returns whether xs is a palindrome
(define (is-pal? xs)
(cond [(<= (length xs) 1) #t]
[(equal? (take xs 1) (take-right xs 1)) (is-pal? (drop (drop-right xs 1) 1))]
[else #f]
)
)
;; (num-els xs) -> integer?
;; xs: list?
;; returns the number of (non-list) elements of xs, on any nesting level
(define (num-els xs)
(cond [(null? xs) 0]
[else
(let ([res (num-els (rest xs))])
(if (list? (first xs))
(+ res (num-els (first xs)))
(+ res 1)
)
)
]
)
)
;; (sum-els xs) -> number?
;; xs: list?
;; returns the sum of (non-list) elements of xs, on any nesting level.
;; returns 0 if xs is empty.
(define (sum-els xs)
(cond [(null? xs) 0]
[else
(let ([res (sum-els (rest xs))])
(if (list? (first xs))
(+ res (sum-els (first xs)))
(+ res (first xs))
)
)
]
)
)
;; (repeat-twice xs) -> list?
;; xs: list?
;; returns a list which repeats each element of lst twice
(define (repeat-twice xs)
(if (null? xs)
'()
(append (append (list (first xs)) (list (first xs))) (repeat-twice (rest xs)))
)
)
;; (my-filter f xs) -> list?
;; f: boolean-valued function applicable to every element of xs
;; xs: list?
;; returns a list of those elements from xs that pass the function
;; f (i.e., f(x) is true for element x in xs), in their original order
(define (my-filter f xs)
(if (null? xs)
empty
(let ([res (my-filter f (rest xs))])
(if (f (first xs)) (append (list (first xs)) res) res)
)
)
)
;; (my-map f xs) -> list?
;; f: function applicable to every element of xs
;; xs: list?
;; return the result of applying f to every element of xs
(define (my-map f xs)
(if (null? xs)
empty
(append (list (f (first xs))) (my-map f (rest xs)))
)
)
(module+ main
(check-expect (my-length empty) 0)
(check-expect (my-length '(1 2 3)) 3)
(test)
)
1 Comment
Other functional programming languages are also interesting (Erlang, Haskell, OCaml, etc). I just know functional programming recently when I read about the design of Rust. In my understanding, the functional programming languages describe manipulations that you intend to do on a data structure as a mapping from original data to destination. It is useful in data science and math. I myself have used to imperative programming :>