|
;; 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. |