;; The first three lines of this file were inserted by DrRacket. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-beginner-reader.ss" "lang")((modname natnum-defn-taster) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f () #f))) (require 2htdp/image) ; A natnum is: ; - 0 OR ; - (add1 [natnum]) ;;;;;; Template for any function handling a natnum: ; func-for-natnum : natnum -> ?? ; #;(define (func-for-natnum n) (cond [(zero? n) ...] [(positive? n) (... (func-for-natnum (sub1 n)))])) ; bullseye : nat -> image ; return a picture of `n` concentric circles with decreasing sizes. (define (bullseye n) (cond [(zero? n) empty-image] [(positive? n) (underlay (circle (* n 10) 'outline 'blue) (bullseye (sub1 n)))])) #|(check-expect (bullseye 0) empty-image) (check-expect (bullseye 1) (circle 10 'outline 'blue)) (check-expect (bullseye 2) (overlay (circle 20 'outline 'blue) (circle 10 'outline 'blue))) |# (bullseye 6) ; write `list-ref` ; write `append` ? Hmm, dangerous. #| (A student question) > For writing `list-ref`, do we need to use a while-loop-function > in order to retrieve the index value for the list that `my-list-ref` takes in? > From what I understand, if index is 0, we return the first item in the list, > but it’s the part about a number greater than 0 that has me confused. The answer to this lies in the data-defn / template for natural-number. I'll walk through it; for tl;dr, skip to the template at the end, and the example above. datatype def: A natural-number is: 0, OR (+ 1 [natural-number]) So we'll have a template which is a `cond` with two branches: ; func-for-natnum : natnum -> ?? (define (func-for-natnum n) (cond [(zero? n) ...] [(positive? n) ...])) But then the recipe suggests "if you have a variant which is a struct, pull out its fields". It LOOKS like that doesn't apply here, but actually it does: If (positive? n), then our definition tells us that n is built on some other natnum plus one. (That's like a struct containing a natnum inside it.) How do we "pull out that field" -- extract the natnum that `n` was created out of? Well, `n` is (add1 [natnum]) so that inner natnum is just `(- n 1)`! Btw, there is also `(sub1 n)`, for symmetry with `add1`. ...And if we pull out the "field" that was hidden inside `n`, it has type `natnum` (from the data-def'n). So what function might we call on it? The recipe suggests: Make the natural-recursive call! Thus we get: ; func-for-natnum : natnum -> ?? (define (func-for-natnum n) (cond [(zero? n) ...] [(positive? n) (... (func-for-natnum (sub1 n)))])) So just like we didn't need a while-loop to process a list, we don't need a while-loop to process all the numbers. [We will talk soon, about the connection between loop-constructs, and recursion, and how “tail recursion” is just a loop in disguise.] ...And, this all follows from the same ol' steps of the design recipe. Respect the structure of your data, and the code is often easy! |#