Мой вопрос заключается в переписывании вложенных условий if на один cond
с ветвью, имеющей локальную привязку. Я очень новичок в Racket, просто делаю первые шаги, поэтому, если мой вопрос глуп, пожалуйста, будьте снисходительны.cond с локальным связыванием
Вкратце задача состоит в том, чтобы написать функцию, которая принимает вектор и ищет в нем значение. Вектор содержит смешанные элементы - пары и непар. Значение интереса должно быть в автомобиле пары.
Рабочим раствор использует рекурсивную вспомогательную функцию с вложенным МФСОМ
[vlen (vector-length vec)]
[find-in-vector
(lambda (pos)
(if (= pos vlen) ;; if the end of the vector has been reached
#f ;; then return false
(let ([el (vector-ref vec pos)]) ;; Otherwise, extract current element from the vector,
(if (and (pair? el) (equal? v (car el))) ;; if the element is a pair and its car is what we want
el ;; then return the element
(find-in-vector (+ 1 pos))))))] ;; otherwise keep searching the vector
Я хотел бы переписать его так, что он использует cond
, что выглядит более компактным. Нижеприведенный код является возможной реализацией. Проблема заключается в том, что (vector-ref vec pos)
вычисляется несколько раз, и это то, что я хотел бы переписать так, что она вычисляется только один раз, как и в предыдущей реализации с вложенным МФСОМ
[vlen (vector-length vec)]
[find-in-vector
(lambda (pos)
(cond [(= pos vlen) #f]
[(and (pair? (vector-ref vec pos)) ;; one
(equal? v (car (vector-ref vec pos)))) ;; two
(vector-ref vec pos)] ;; three is too many
[#t (find-in-vector (+ 1 pos))]))])
И это то, что я достиг в больше всего: один вызов (vector-ref vec pos)
в тест-выраж и другой вызов в результате-выраж
(cond
[(= pos vlen) #f]
[(letrec ([el (vector-ref vec pos)]) ;; extract current element from the vector
(and (pair? el) (equal? v (car el)))) ;; and use it in conditionals
(vector-ref vec pos)] ;; again, extract and return. FIXIT
[#t (find-in-vector (+ 1 pos))]))]) ;; otherwise, keep searching
Как можно дальше сделать el
разделены между тест-ехрг и результатом экспрессии? И я бы хотел, чтобы el
оставался локальным для этой конкретной кондиционной ветви. Данный код работает неправильно. AFAIU, целое выражение letrec
: рассматривается как текст-выражение из cond?
(cond
[(= pos vlen) #f]
[(letrec ([el (vector-ref vec pos)])
(and (pair? el) (equal? v (car el)))
el)]
[#t (find-in-vector (+ 1 pos))])
Самый простой способ ввести локальную привязку - это 'lambda'. Вот тэп кода из ответа Криса: '(cond ... (((lambda (el) (и (pair? El) (equal? V (car el)) el)) (vector-ref vec pos))) (иначе ...)). Неловко, но работает. –
(хотя, я тестировал его в MIT Scheme, а не в Racket). –