John Clements
unread,May 7, 2021, 11:53:21 AM5/7/21Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Racket Users
Background: I teach a PL course, using Shriram’s PLAI. Many of the assignments require students to maintain an environment mapping symbols to values. Shriram illustrates a nice easy way to do this, as a list of two-element structures. You can also use an immutable hash. Fine. So I’m grading a student submission, and I come across this:
(: extend-environment* (-> Environment (Listof (List Symbol Value)) Environment))
(define (extend-environment* env kv)
(let loop ([kv : (Listof (List Symbol Value)) kv]
[env env])
(cond
[(empty? kv) env]
[else
(let* ([kv-pair (first kv)]
[new-env (KVEnvironment (first kv-pair) (second kv-pair) env)])
(loop (rest kv) new-env))])))
;; Returns a new environment with old-env as parent
(: extend-environment (->* (Environment Symbol Value) #:rest-star (Symbol Value) Environment))
(define (extend-environment env key value . kv)
(define kv* : (Listof (List Symbol Value))
(let loop : (Listof (List Symbol Value))
([kv : (Rec x (U Null (List* Symbol Value x))) (list* key value kv)])
(if (empty? kv)
'()
(let* ([take-two (list (first kv) (second kv))]
[drop-two (rest (rest kv))])
(list* take-two (loop drop-two))))))
(extend-environment* env kv*))
This solution uses
1) a named let,
2) the list* function,
3) a ->* type with a #:rest-star argument, and
4) A custom rec type for alternating symbols and values.
To cap it all off, the student DOESN’T EVEN USE the extra hardware. This is the only use of extend-environment in the code:
(extend-environment e name arg)
So, uh, any idea where this code came from?
:)
John