#racket
#racket
Вопрос:
Есть ли способ получить только один из результатов, возвращаемых из values
? Я пытался сделать (define x (first (values 1 2)))
, но это не сработало. Это единственный способ написать что-то вроде (define-values (x dont-care) (values 1 2))
и определить дополнительную переменную?
Ответ №1:
Это единственный способ написать что-то вроде
(define-values (x dont-care) (values 1 2))
и определить дополнительную переменную?
Все единственные способы получить одно из значений из многозначной вещи включают определение дополнительных переменных, как dont-care
здесь. Однако вы можете использовать область видимости, либо локальную, либо макроскопическую, чтобы смягчить это и скрыть их.
Вы можете использовать let-values
для ограничения области следующим образом:
(define x (let-values ([(x dont-care) (values 1 2)]) x))
Или вы можете использовать макрос, чтобы «скрыть» другие переменные:
(define-syntax-rule (define-first-of-two-values x expr/2vs)
(define-values (x dont-care) expr/2vs))
(define-first-of-two-values x (values 1 2))
После этого определение x
будет доступно, но dont-care
не будет, поскольку оно ограничено областью определения макроса.
Вы также можете использовать существующий макрос, такой как match-define-values
, с _
подстановочным знаком для значений, которые вас не интересуют.
(match-define-values (x _) (values 1 2))
match-define-values
Макрос фактически расширяется во что-то очень похожее на первый let-values
пример выше.
Комментарии:
1. Спасибо! Возможно, не связанный с этим вопрос: является ли multiple-values лучшим способом реализации функции, которая возвращает несколько значений? Или лучше использовать такие вещи, как пары? (с тем преимуществом, что возвращаемыми значениями можно манипулировать с помощью
car
иcdr
)2. Многозначности определенно менее гибки, чем такие данные, как пары, кортежи или списки. Было много случаев, когда я выбирал возвращать список фиксированной длины вместо нескольких значений, особенно если я хочу, чтобы что-то либо завершилось успехом с несколькими значениями, либо завершилось неудачей с одним значением
#f
. Подобные шаблоны плохо сочетаются сvalues
возвратами, но списки фиксированной длины более гибкие.3. @JRR Хотя схема с несколькими значениями, вероятно, быстрее, чем CL, ее гораздо менее удобно использовать. В CL вы всегда можете использовать каждую функцию, которая возвращает несколько значений, и она будет использовать только первое вне
multiple-value-bind
(так же, как Schemelet-values
).4. Спасибо обоим. Я пытался найти эквивалент «параллельного присваивания» python в racket и наткнулся на это. Не уверен, правильно ли это делать?
5. Сопоставление с шаблоном, из
racket/match
Ответ №2:
Я использовал этот макрос:
(define-syntax-rule (first-value expr)
(call-with-values (λ () expr)
(λ (result . ignored) result)))
> (first-value (values 10 20 30 40 50))
10
Это работает с любым количеством значений. Смотрите call-with-values
документацию.