Racket101

7 minute read

Published:

In this post, we will be looking at basic Racket programming. At the end of the post, we will be doing some Racket programming exercises on the Jyputer environment. If you missed the previous post, where we looked at setting up the environment for the RackeTutes tutorial series, you can check it out from here.

Racket, a descendant of the Scheme programming language, is a versatile and dynamic programming language renowned for its unique approach to language design and extensibility. Building upon the foundations of Lisp and Scheme, Racket has evolved into a feature-rich language that emphasizes language-oriented programming and supports the creation of new languages. With Racket, programmers can not only write code but also delve into the world of language exploration, experimentation, and customization. Racket provides a comprehensive set of libraries and tools that facilitate language development, including a powerful macro system for metaprogramming. Racket’s commitment to language design, extensibility, and educational principles makes it an excellent choice for delving into new programming concepts, implementing domain-specific languages, and teaching fundamental programming principles. Racket comes with three components,

  1. racket - compiler/ interpriter/ runtime
  2. DrRacket - IDE
  3. raco - package manager

In our tutorials, we will be using Racket inside the Jupyter Notebook environment. Setting up the environment with ease is discussed in my previous post.

This complete post is available as a Jupyter Notebook here.

Usually, we need to start the rkt script with specifying the language variant.

#lang racket

Ops! We get the following error,

eval:1:0: read-syntax: `#lang` not enabled possible reason: not allowed again inside a module that already starts `#lang`, or not enabled for interactive evaluation context...: /usr/share/racket/pkgs/sandbox-lib/racket/sandbox.rkt:114:0: default-sandbox-reader /usr/share/racket/pkgs/sandbox-lib/racket/sandbox.rkt:572:0: input->code /usr/share/racket/pkgs/sandbox-lib/racket/sandbox.rkt:929:14

This happens due to the kernel running behind the Jupyter. Therefore to use Racket on Jupyter Notebook, language variant specification should be like this.

#lang iracket/lang #:require rosette

Interactiveness

All the features that you can enjoy while using dr.Racket can be enjoyed on Jupyter Notebook. Let’s see some examples of function definitions, and racket drawings.

Function Outputs

The final variable that appears on a Racket function is considered as it’s return value. This value gets printed directly to the output when you run a cell.

Let’s see some examples,

Racket has implementations of built-in functions for different operations. Sample usage of built-in function extract given in the Racket documentation is as below.

(define (extract str)
  (substring str 4 7))
(extract "the gal out of the city")

"gal"

Import Racket Functions

Let’s assume that we need to import a function from an existing racket program. It is simple as changing the language definition. In the same location of this Notebook, I have created print.rkt which contains the following Racket program to print a string to the terminal.

#lang rosette/safe

;; print.rkt
(provide print)

(define (print x)
  (display x) )

In order to import the above function to the Jupyter Notebook, we just need to use the general (require " ") syntax. Let’s see it in action.

(require "print.rkt")
(print "Hello world!")

Hello world!

Graphics

Racket has its own Drawing Toolkit. Output from the functions are directly displayed in Jupyter Notebook. First we need to import the modules as follows,

 (require 2htdp/image)

Then we can start drawing

(circle 30 "outline" "red")

(add-line
    (rectangle 100 100 "solid" "darkolivegreen")
    25 25 75 75
    (make-pen "goldenrod" 30 "solid" "round" "round"))

 (require lang/posn)

(underlay
   (rectangle 80 80 "solid" "mediumseagreen")
   (polygon
    (list (make-posn 0 0)
          (make-posn 50 0)
          (make-posn 0 50)
          (make-posn 50 50))
    "outline"
    (make-pen "darkslategray" 10 "solid" "round" "round")))


 (require 2htdp/planetcute)

 ; stack : non-empty-list-of-images -> image
; stacks 'imgs' on each other, separated by 40 pixels
(define (stack imgs)
  (cond
    [(empty? (rest imgs)) (first imgs)]
    [else (overlay/xy (first imgs)
                      0 40
                      (stack (rest imgs)))]))
(beside/align
   "bottom"
   (stack (list wall-block-tall stone-block))
   (stack (list character-cat-girl
                stone-block stone-block
                stone-block stone-block))
   water-block
   (stack (list grass-block dirt-block))
   (stack (list grass-block dirt-block dirt-block)))

Conclusion

I think we have covered enough materials about the Racket and Jupyter Notebook. From here onwards, we will be looking at a bunch of example Racket programs that you can try on the Jupyter Notebook environment. In the next post, we will look at Rosette, which is a solver-aided programming language extension that is based on Racket.

Racket Play Ground!

Constructing the popular Pascal triangle with Racket

First we need to write a function to compute the factorial of a number

; Compute the factorial of a number
(define (factorial n)
    (define mult 1)
    (for ([i (in-range 1 n)]) 
        (set! mult (* i mult)))
        mult)

Then, we can construct the Pascal triangle

; Construct the Pascal triangle
(define (pascal n)
    (for ([i (in-range 0 n)])
        (for ([q (in-range 0 (+ (- n i) 1))])
            (display " ") )
        (for ([j (in-range 0 (+ i 1))])
            (display (/ (factorial i) (* (factorial j) (factorial (- i j))))) 
            (display " "))
            
    (displayln "" )))

Of course we need to test it, by calling it

(pascal 5)

      1
     1 1
    1 1 1
   1 2 2 1
  1 3 6 3 1

Answers to some problems from here

The local supermarket needs a program that can compute the value of a bag of coins. Define the program sum-coins. It consumes four numbers: the number of pennies, nickels, dimes, and quarters in the bag; it produces the amount of money in the bag.

(define (coin_sum p n d q) (display "$")(+ (* p 0.01)  (* n 0.05) (* d 0.1) (* q 0.25)))
(coin_sum 10 20 30 40)

14.1

An old-style movie theater has a simple profit function. Each customer pays $5 per ticket. Every performance costs the theater $20, plus $.50 per attendee. Develop the function total-profit. It consumes the number of attendees (of a show) and produces how much income the attendees produce.

(define (th_profit n) (display "profit of $") (- (* n 5) 20 (* 0.5 n)))
(th_profit 10)

profit of $25.0

Develop the function tax, which consumes the gross pay and produces the amount of tax owed. For a gross pay of $240 or less, the tax is 0%; for over $240 and $480 or less, the tax rate is 15%; and for any pay over $480, the tax rate is 28%.

(define (tax p) (display "owed tax $") 
    (if (< p 240) 0 
        (if (< p 480) (* p 0.15) (* p 0.28) )))
(tax 100)
(tax 300)
(tax 500)

owed tax $140.0

Write the program discount, which takes the name of an organization that someone belongs to and produces the discount (a percentage) that the person should receive on a purchase. Members of AAA get %10, members of ACM or IEEE get %15, and members of UPE get %20. All other organizations get no discount.

(define (discount m) (display "Discount is ")
    (if (string=? m "AAA") (displayln "%10")
        (if (or (string=? m "ACM") (string=? m "IEEE")) (displayln "%15") 
            (if (string=? m "UPE") (displayln "%20") 0))))

(discount "AAA")
(discount "ACM")
(discount "IEEE")
(discount "UPE")

Discount is %10
Discount is %15
Discount is %15
Discount is %20