Recently when I self-learnt MIT 6.5151 course, I first read CS 61AS Unit 0 as the preparation. Then I have read SICP 1 to 2.1 (with related lecture notes) as ps0 requires (also read 2.2.1 as CS 61A notes requires) and then Software Design for Flexibility (SDF) Prologue, chapter 1 and partly Appendix on Scheme.
Currently I am reading SDF chapter 2 and doing exercise 2.11 (f).
f. Another big extension is to build make-converter so that it
can derive compound conversions, as required, from previously
registered conversions. This will require a graph search.
I want to make unit-conversion-key-graph
equal to (((quote tonne) ((quote kg) (quote g))) ((quote celsius) ((quote kelvin) (quote fahrenheit))))
in the following code.
But using set!
in fold
will throw errors since res
may be used like the state variable in fold
(This is similar to for i in range(10): i=i+1; print(i)
in python but the latter doesn’t throw errors and i=i+1
does nothing at all.). This is one restriction. It will throw error “;The object #!unspecific, passed as the first argument to car, is not the correct type.” sometime after set!
.
The following unit-conversion-list
is to be consistent with the code base where each pair is paired with some conversion procedure.
(define (displayln x)
(newline)
(display x))
(define unit-conversion-list '((('celsius . 'kelvin) . 1) (('tonne . 'kg) . 2)
(('tonne . 'g) . 3) (('celsius . 'fahrenheit) . 4)))
(displayln unit-conversion-list)
;; /a/7871106/21294350
(define (list-with lst idx val)
(if (null? lst)
lst
(cons
(if (zero? idx)
val
(car lst))
(list-with (cdr lst) (- idx 1) val))))
;; https://cookbook.scheme.org/find-index-of-element-in-list/
(define (list-index fn lst)
(displayln lst)
(let iter ((lst lst) (index 0))
(if (null? lst)
-1
(let ((item (car lst)))
(if (fn item)
index
(iter (cdr lst) (+ index 1)))))))
(define unit-conversion-key-graph
(fold
(lambda (unit-conversion res)
(let ((key-pair (car unit-conversion)))
(let* ((from (car key-pair))
(to (cdr key-pair))
(from-idx
(list-index
(lambda (adjacent-node-pair) (equal? from (car adjacent-node-pair)))
res)))
(if (>= from-idx 0)
(begin
(displayln from-idx)
(set! res (list-with res from-idx (list from (list (cadr (list-ref res from-idx)) to))))
(displayln res)
(displayln "one iter ends"))
(cons (list from to) res)))))
'()
unit-conversion-list))
Then is there one elegant way similar to the above fold
(both books recommends functional programming) but without the above restriction to make unit-conversion-key-graph
right?