A playful introduction to Racket (<60 min activity), with example usage of quickcheck (property based testing)

3 min read Original article ↗
;; This is a playful introduction to Racket, using the in-built app ;; Dr. Racket, intended for a <60 min session. ;; Racket is a polygot-friendly, language designer friendly, beginner friendly ;; multi-paradigm general purpose programming language. ;; Install Racket and then open this little tutorial using Dr. Racket, by ;; saving it as a "racket_quick_intro.rkt" text file. ;; Download link for Racket: https://download.racket-lang.org ;; 1. Introduction ;; Dr. Racket is a multi-language IDE for Racket. ;; You can use Racket to make your own language or sub-language and then set ;; that as the language with a similar #lang invocation as below: #lang racket ;; Racket and Dr. Racket excel as a language laboratory. ;; As a basic tour of this environment, let's try to write a simple prime ;; number checker. ;; Also, let's decide to test our code using an external package called ;; "quickcheck". To install this package, `raco pkg install quickcheck`, or ;; go to File > Package Manager... and install. (require (prefix-in qc: quickcheck)) ;; 2. Basic Code ;; General notes about discovering documentation: ;; - try hovering over names; they show where their bound occurences happen, ;; or from where an occurence was bound ;; - for each unfamiliar name, try right clicking and searching it in the ;; help desk. (define (prime? x) (let* ([maxCandidate (exact-round (sqrt x))] [rangeCandidates (range 2 (+ maxCandidate 1))] [divisor? (lambda (y) (= 0 (modulo x y)))] [divisors (filter divisor? rangeCandidates)]) (if (= x 1) #f (empty? divisors)))) ;; 3. Basic Tests ;; Let's explore how we'll test our code. ;; `quickcheck` is one of a category of "property based testing" libraries; ;; others are Haskell's quickcheck (of which this is a port), Python's ;; hypothesis, and probably many others. ;; We define a property to be checked. Maybe think of it as a predicate ;; of sorts. (define prime?-returns-boolean (qc:property ([someNumber qc:arbitrary-natural]) (boolean? (prime? someNumber)))) ;; Here, we ask quickcheck to generate random values (we defined the values to ;; be provided as qc:arbitrary-natural) and test whether our property is really ;; true. ;; To run the check, run the quoted code in the REPL. (quote (qc:quickcheck prime?-returns-boolean)) ;; You'll note that when you hit run, the above line is printed in the REPL, so ;; you can copy and run it from there. ;; Let's test another couple of basic things. (define prime?-is-correct-for-first-10-primes (qc:property ([someNumber (qc:choose-one-of (list 2 3 5 7 11 13 17 19 23 29))]) (equal? (prime? someNumber) #t))) (define prime?-is-correct-for-10-non-primes (qc:property ([someNumber (qc:choose-one-of (list 1 4 6 8 10 12 14 15 16 18 20))]) (equal? (prime? someNumber) #f))) ;; To run the checks, run the quoted code in the REPL. (quote (qc:quickcheck prime?-is-correct-for-first-10-primes)) (quote (qc:quickcheck prime?-is-correct-for-10-non-primes)) ;; Recap ;; We got introduced to Racket and Dr. Racket, learned how to write some code ;; and test it, and learned how to explore documentation and install external ;; packages. ;; Next Steps? ;; Some fun options to choose your own adventure: ;; - module languages -- create you own language! ;; (https://docs.racket-lang.org/guide/languages.html) ;; - racklog -- Racket's take on logic programming ;; (https://docs.racket-lang.org/racklog/) ;; - typed/racket -- Racket's typed sister language ;; (https://docs.racket-lang.org/ts-guide/) ;; Self plug: kilotau.com.