typed/racket + racket interoperability - racket

How can I use typed Racket for some functions in my codebase, but use (untyped) Racket for others? When I define a function in Racket but import it into a typed Racket context, it seems to be changing the behavior of the function (functions described below).
As it is now, the files do typecheck, but don't pass my tests in p11typedtest.rkt -- however, my files do successfully pass my tests if I either (A) switch p11typed.rkt to regular Racket or (B) copy the pack function into p11typed.rkt and provide its type annotation.
;; p09.rkt
#lang racket
(provide pack)
;; packs consecutive duplicates within a list into sublists
(define (pack lst)
(for/foldr ([acc '()]) ([x lst])
(match acc
[(cons (cons y ys) zs) #:when (equal? x y)
(list* (list* x y ys) zs)]
[_ (list* (list x) acc)]
)))
;; p11typed.rkt
#lang typed/racket
(provide encode-runlen-mod)
;; (require (only-in (file "p09.rkt") pack))
(require/typed (only-in (file "p09.rkt") pack)
[pack (All (A) (-> (Listof A) (Listof (Listof A))))]
)
(define-type (Runof a) (List Index a))
(define-type (RunListof a) (Listof (U a (Runof a))))
;; encodes a list as a list of runs
(: encode-runlen-mod (All (A) (-> (Listof A) (RunListof A))))
(define (encode-runlen-mod lst)
;; uncomment to print the result of pack
;; (displayln (pack lst))
(for/list ([dups (pack lst)])
(match (length dups)
[1 (car dups)]
[n (list n (car dups))]
)))
; (: pack (All (A) (-> (Listof A) (Listof (Listof A)))))
; (define (pack lst)
; (for/foldr ([acc '()]) ([x lst])
; (match acc
; [(cons (cons y ys) zs) #:when (equal? x y)
; (list* (list* x y ys) zs)]
; [_ (list* (list x) acc)]
; )))
;; p11typedtest.rkt
#lang racket
(require (only-in (file "p11typed.rkt") encode-runlen-mod))
(define (test-output namespace expr v)
(let* ([val (eval expr namespace)]
[fail (not (equal? val v))])
(begin
(display (if fail "FAIL" "ok "))
(display " '(=? ")
(print expr)
(display " ")
(print v)
(display ")'")
(if fail
(begin
(display ", got ")
(print val)
(displayln " instead")
)
(displayln "")
)
(void))
))
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(test-output ns '(encode-runlen-mod '(1 2 3 4)) '(1 2 3 4))
(test-output ns '(encode-runlen-mod '(1 1 1)) '((3 1)))
(test-output ns '(encode-runlen-mod '(1 2 2 3 4)) '(1 (2 2) 3 4))
(test-output ns '(encode-runlen-mod '(1 2 3 4 4 4)) '(1 2 3 (3 4)))
(test-output ns '(encode-runlen-mod '(1 2 3 (3 4))) '(1 2 3 (3 4)))
(test-output ns '(encode-runlen-mod '(A A A A B C C A A D E E))
'((4 A) B (2 C) (2 A) D (2 E)))
)

Related

Why we can't use (values) like this?

(define (avg . l)
(/ (apply + l) (length l)))
(define (delist ls)
(apply values ls))
(avg (delist '(1 2 3))) ;;error
(avg 1 2 3) ;; return 2
without call-with-values, can I bind the value returned by values to each parameter in other ways?
can I bind the value returned by values to each parameter in other ways?
Here are most of the ways I know of to bind variables to returned values in Racket:
#lang racket/base
(define (list->values lst) (apply values lst))
(define-values (a b c) (list->values '(1 2 3)))
(displayln (+ a b c))
(let-values ([(d e f) (list->values '(4 5 6))])
(displayln (+ d e f)))
(require racket/match)
(match/values (list->values '(7 8 9))
([x y z] (displayln (+ x y z))))
(require srfi/8)
(receive (i j k) (list->values '(10 11 12)) (displayln (+ i j k)))
(displayln (call-with-values (lambda () (list->values '(13 14 15))) +))

a bunch of lists of numbers

I would like to write the Racket function find-subsets. The function produces the list of subsets of a list of numbers w/o helper functions and that only uses lambda, cond, cons, rest, first, and other primitive functions.
For instance, the following check-expects should be satisfied:
(check-expect (find-subsets '(2 2 3 3)) '(() (2) (3) (2 2) (2 3) (3 3) (2 2 3) (2 3 3)
(2 2 3 3)))
(check-expect (find-subsets '(1 2 3)) '(() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3)))
Basically, this function produces the power set of a set of numbers, but I'm not sure how it can produce all of the elements, without recursion.
#lang racket
(define-syntax-rule (my-let ([var val]) body)
((λ (var) body) val))
(define-syntax-rule (Y e)
((λ (f) ((λ (x) (f (λ (y) ((x x) y))))
(λ (x) (f (λ (y) ((x x) y))))))
e))
(define-syntax-rule (define/rec f e)
(define f (Y (λ (f) e))))
(define/rec my-append
(λ (l1)
(λ (l2)
(cond [(empty? l1) l2]
[else (cons (first l1) ((my-append (rest l1)) l2))]))))
(define/rec my-map
(λ (f)
(λ (l)
(cond [(empty? l) empty]
[else (cons (f (first l)) ((my-map f) (rest l)))]))))
(define/rec my-power-set
(λ (set)
(cond [(empty? set) (cons empty empty)]
[else (my-let ([rst (my-power-set (rest set))])
((my-append ((my-map (λ (x) (cons (first set) x))) rst))
rst))])))
Summary:
I took the standard definition of powerset from here and curried it. Then I replaced let, append, and map with my-let, my-append, and my-map. I defined the Y combinator as the Y macro and a helper define/rec that makes a function recursive. Then I defined my-append and my-map using the define/rec macro (note that they're curried too). We can substitute everything to get the desired code.

How do these LISP expressions evaluate to the answer provided?

Now, just by looking at the question and the variables L and X, I can see, more or less, at the very minimum how these answers come to fruition.
But this time I would like to know the inner workings, step by step, as to how these answers come about. My professor is absolutely terrible and can't explain anything for his life.
L = (D B B A A A A C)
X = ((2B) (4A) (1C))
Q1) (cons (list (+ (caar X) 1) (cadar X)) (cdr X))
Answer: ((3B) (4A) (1C))
Q2) (cons (list 1 (car L)) X)
Answer: ((1D) (2B) (4A) (1C))
Are you sure you didn't miss spaces in the definition of X?
Looks like, it should be defined like this:
X = ((2 B) (4 A) (1 C))
The computation is like this:
;;; Setup.
(defvar L '(D B B A A A A C))
(defvar X '((2 B) (4 A) (1 C)))
;;; Q1:
(cons (list (+ (caar X) 1) (cadar X)) (cdr X))
;;; ^^^^^^^^
;;; (caar X) = 2
(cons (list (+ 2 1) (cadar X)) (cdr X))
;;; ^^^^^^^
;;; (+ 2 1) = 3
(cons (list 3 (cadar X)) (cdr X))
;;; ^^^^^^^^^
;;; (cadar X) = B
(cons (list 3 'B) (cdr X))
;;; ^^^^^^^^^^^
;;; (list 3 'B) = (3 B)
(cons '(3 B) (cdr X))
;;; ^^^^^^^
;;; (cdr X) = ((4 A) (1 C))
(cons '(3 B) '((4 A) (1 C)))
;;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;;; (cons '(3 B) '((4 A) (1 C))) = ((3 B) (4 A) (1 C))
'((3 B) (4 A) (1 C))
;;; Q2:
(cons (list 1 (car L)) X)
;;; ^^^^^^^
;;; (car L) = D
(cons (list 1 'D) X)
;;; ^^^^^^^^^^^
;;; (list 1 'D) = (1 D)
(cons '(1 D) X)
;;; ^^^^^^^^^^^^^^^
;;; (cons '(1 D) X) = ((1 D) (2 B) (4 A) (1 C))
'((1 D) (2 B) (4 A) (1 C))

Mapping within macro without extra parentheses?

Say I have a macro like this:
(define-syntax (choose stx)
(define data (syntax->datum stx))
(define args (cadr data))
(define body (cddr data))
(define output
`(apply (case (car ,args)
,(map (lambda (choice)
`((,(car choice)) ,(cadr choice)))
body)
(else (displayln "error")))
(cdr ,args)))
(println output)
#'(void))
If I use this on something like this (there could be more options):
(choose args
("run" runsomething)
("del" delsomethingelse))
It transforms it to
(apply
(case (car args)
((("run") runsomething)
(("del") delsomethingelse))
(else (displayln "error")))
(cdr args))
Which is not valid code, because the map gave it extra parentheses. Instead I want it to give me this:
(apply
(case (car args)
(("run") runsomething)
(("del") delsomethingelse)
(else (displayln "error")))
(cdr args))
How could I do something like this?
Use unquote-splicing (aka ,#) to get rid of the list surrounding map.
Example:
(define xs '(a b c))
`(1 2 ,xs 3 4) ; => '(1 2 (a b c) 3 4)
`(1 2 ,#xs 3 4) ; => '(1 2 a b c 3 4)
However I notice that you use syntax->datum on the input stx
of the syntax transformer. That removes lexical information, which
could end up causing problems. It recommend using either syntax-case
or syntax-parse, which use pattern matching to pick out the elements
of the input syntax and templates to generate the output.
(define-syntax (choose stx)
(syntax-case stx ()
[(_choose args
(datum fun-expr)
...)
#'(apply (case (car args)
[(datum) fun-expr]
...)
(cdr args))]))
(define (run-it . xs) (list 'ran-it xs))
(define (del-it . xs) (list 'delt-it xs))
(choose (list "run" 1 2 3)
("run" run-it)
("del" del-it))
Output: '(ran-it (1 2 3))

Map! procedure in Racket

The map! procedure should modify the existing list to have the values of the operator applied to the original values.
For example:
(define a '(1 2 3 4 5))
(define double (lambda (x) (* x 2)))
(map! double a)
returns
done
Then when a is evaluated, a should return
(2 4 6 8 10)
map! procedure must do that work.
(define (map! operator given-list)
(if (null? given-list) 'done
(<the procedure that does the modification>)))
My guess1:
(map (lambda (x) (set! x (operator x))) given-list)
(map! double a)
returns:
'(#<void> #<void> #<void> #<void> #<void>)
My guess2:
(cons (operator (car given-list)) (map! double (cdr given-list)))
(map! double a)
returns:
'(2 4 6 8 10 . done)
My guess3:
(set! given-list (map operator given-list))
(map! double a)
returns:
'(2 4 6 8 10)
My guess4:
(let ((element (car given-list)))
(set! element (operator given-list) (map! operator (cdr given-list)))
(map! double a)
returns:
'done
but, when "a" is evaluated, it still says:
'(1 2 3 4 5)
What do I have to do for this?????
You cannot use set! for this. You need to use set-car! on the cons cell you're changing. Here's how you might write it:
(define (map! f lst)
(let loop ((rest lst))
(unless (null? rest)
(set-car! rest (f (car rest)))
(loop (cdr rest)))))
If you have SRFI 1, it's even easier (if we ignore for a moment that SRFI 1 already defines map! ;-)):
(define (map! f lst)
(pair-for-each (lambda (pair)
(set-car! pair (f (car pair))))
lst))