# Function contracts for multiple return values

**URL:** https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284
**Category:** Questions & Answers
**Tags:** question
**Created:** [November 27, 2021, 12:27am UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284 "2021-11-27T00:27:18Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![badkins](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/badkins/32/99_2.png) [@badkins](https://racket.discourse.group/u/badkins)
#### Post date: [November 27, 2021, 12:27am UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/1 "2021-11-27T00:27:19Z")

</div>

I would like to specify the following (which doesn't work) for the return values of a function:

```
(or/c (values t1 t2)
      (values t3 t4))

```

In other words, I'd like to verify that _either_ the function returns two values of types t1 & t2, respectively, _or_ the function returns two values of types t3 & t4, respectively, but not, for example, two values of types t1 & t4.

`or/c` is expecting a single value. Any thoughts about how to accomplish this?

---

<div class="post-metadata">

### Author: ![badkins](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/badkins/32/99_2.png) [@badkins](https://racket.discourse.group/u/badkins)
#### Post date: [November 27, 2021, 12:55am UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/2 "2021-11-27T00:55:49Z")

</div>

From Sorawee on Slack #general, using the dependent range feature of `->i`.

```
#lang racket

(define f/c
  (->i ([_ number?]) (values [x (or/c 1 2)]
                             [y (x) (if (= x 1) 11 12)])))

(define/contract (f x) f/c
  (values 2 12))

(define/contract (g x) f/c
  (values 1 11))

(define/contract (h x) f/c
  (values 1 12))

(f 1) ; OK
(g 1) ; OK
(h 1) ; contract violation

```

---

<div class="post-metadata">

### Author: ![badkins](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/badkins/32/99_2.png) [@badkins](https://racket.discourse.group/u/badkins)
#### Post date: [November 27, 2021, 4:15pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/3 "2021-11-27T16:15:59Z")

</div>

It appears Sorawee's solution works perfectly. The contract is for a class method; hence, the entry for `this`. I'm very impressed with Racket's contract system!

```scheme
[ get-user-data
  (->i ([_ any/c] ; this
        [conn connection?]
        [reference-key string?]
        [type string?])
       (values [hsh (or/c hash? #f)]
               [ errors (hsh) (if (hash? hsh)
                                  '()
                                  (listof string?)) ])) ]

```

P.S. It looks like someone may have marked the previous reply solved prematurely, maybe an admin/moderator? May I humbly suggest we wait a period of time to allow the OP to mark a solution before doing so on their behalf? I was busy yesterday evening, so I was only able to test the solution today.

---

<div class="post-metadata">

### Author: ![jbclements](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/jbclements/32/11_2.png) [@jbclements](https://racket.discourse.group/u/jbclements)
#### Post date: [November 28, 2021, 6:03pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/4 "2021-11-28T18:03:13Z")

</div>

Apologies, that was me. I will be more circumspect in the future!

John

---

<div class="post-metadata">

### Author: ![joeld](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/joeld/32/38_2.png) [@joeld](https://racket.discourse.group/u/joeld)
#### Post date: [April 26, 2023, 2:45pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/5 "2023-04-26T14:45:22Z")

</div>

Looks like this question came up again, in slightly different form, on racket-mode's github: ["result arity mismatch" when using a contract with or/c and values · Issue #659 · greghendershott/racket-mode · GitHub](https://github.com/greghendershott/racket-mode/issues/659)

Is it documented anywhere that `values` can be used at all in contracts?

---

<div class="post-metadata">

### Author: ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)
#### Post date: [April 26, 2023, 6:42pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/6 "2023-04-26T18:42:04Z")

</div>

I took a quick look at the issue and yes, perhaps this was a bad choice on my part in the design of the syntax of the range of function contracts! The use of `values` there is purely syntactic; it is really a kind of "keyword" that's attached to `->` and friends. This was done in the days before keywords, I belive (or maybe before I realized I should have used them). If it had been something like:

```scheme
(-> integer? #:values boolean? boolean?)

```

instead of

```scheme
(-> integer? (values boolean? boolean?))

```

maybe it would have been a lot cleaner. Or maybe even `#:results` or something to indicate where arguments end and results begin.

But to answer your question, [here are the docs for `->`](https://docs.racket-lang.org/reference/function-contracts.html#%28form._%28%28lib._racket%2Fcontract%2Fbase..rkt%29._-~3e%29%29) and `values` appears in the blue box there.

---

<div class="post-metadata">

### Author: ![badkins](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/badkins/32/99_2.png) [@badkins](https://racket.discourse.group/u/badkins)
#### Post date: [April 26, 2023, 7:25pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/7 "2023-04-26T19:25:04Z")

</div>

Yikes - when I incorrectly opened that racket-mode github issue, I had completely forgotten about this discourse thread I started, and the fact that I have an example of what I wanted to do in another project - embarrassing!

---

<div class="post-metadata">

### Author: ![joeld](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/joeld/32/38_2.png) [@joeld](https://racket.discourse.group/u/joeld)
#### Post date: [April 26, 2023, 9:20pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/8 "2023-04-26T21:20:00Z")

</div>

I only saw it because I came here to ask my question about using `values` in contracts (occasioned by your recent issue) and it popped up on the "similar topics" list on the right while I was typing.

Further curiosity: when you want to return two values that are guaranteed to be either string and integer _or_ `#f` and `#f`, is there a particular reason you want `values` rather than, say, `cons/c`?

---

<div class="post-metadata">

### Author: ![badkins](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/badkins/32/99_2.png) [@badkins](https://racket.discourse.group/u/badkins)
#### Post date: [April 26, 2023, 11:18pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/9 "2023-04-26T23:18:43Z")

</div>

> [@joeld](#):
>
> Further curiosity: when you want to return two values that are guaranteed to be either string and integer _or_ `#f` and `#f`, is there a particular reason you want `values` rather than, say, `cons/c`?

Efficiency i.e. I don't want to allocate a cons cell.

---

<div class="post-metadata">

### Author: ![hendrikboom3](https://avatars.discourse-cdn.com/v4/letter/h/b5e925/32.png) [@hendrikboom3](https://racket.discourse.group/u/hendrikboom3)
#### Post date: [April 26, 2023, 11:38pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/10 "2023-04-26T23:38:10Z")

</div>

I wonder how 'values' does it?

-- hendrik

---

<div class="post-metadata">

### Author: ![badkins](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/badkins/32/99_2.png) [@badkins](https://racket.discourse.group/u/badkins)
#### Post date: [April 26, 2023, 11:51pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/11 "2023-04-26T23:51:02Z")

</div>

> [@hendrikboom3](#):
>
> I wonder how 'values' does it?

Here's a [paper by Ashley and Dybvig](https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=9641b95e96c6b80f19259c1bc334cbe8c1f24466)

---

<div class="post-metadata">

### Author: ![joeld](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/joeld/32/38_2.png) [@joeld](https://racket.discourse.group/u/joeld)
#### Post date: [April 27, 2023, 2:50am UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/12 "2023-04-27T02:50:54Z")

</div>

Ok, I see. I hadn’t thought of that! But that kind of optimization in this particular context is still a head-scratcher for me. Clearly you want to make some guarantees about the return value here, or you wouldn’t be using contracts. But the contracts themselves introduce a performance penalty that I would assume is far higher than that of the allocation of a single cons cell. If you’re already willing to incur that penalty, why not go a little further and do it in a way that actually makes the guarantee you want to make?

(No shade here; again I’m just curious. I’ve already learned something by asking one dumb question so I figure I’ll just keep going. I’ve never had to deal with the kind of problems where avoiding allocating cons cells made a difference.)

---

<div class="post-metadata">

### Author: ![sorawee](https://avatars.discourse-cdn.com/v4/letter/s/ea5d25/32.png) [@sorawee](https://racket.discourse.group/u/sorawee)
#### Post date: [April 27, 2023, 6:30am UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/13 "2023-04-27T06:30:53Z")

</div>

Yeah, the overhead of `->i` is pretty significant. The following program shows that the contracted `values` variant could be noticeably slower than the `cons` variant.

```scheme
#lang racket

(module test racket
  (define f1/c
    (->i ([_ any/c])
         (values [x (or/c string? #f)]
                 [y (x) (if (string? x) string? #f)])))

  (define f2/c
    (-> any/c (or/c (cons/c string? string?) (cons/c #f #f))))

  (provide (contract-out
            [foo1 f1/c]
            [foo2 f2/c]))

  (define (foo1 b)
    (if b
        (values "answer" "x")
        (values #f #f)))

  (define (foo2 b)
    (if b
        (cons "answer" "x")
        (cons #f #f))))

(require 'test)

(define N 1000000)

(time
 (for ([i N])
   (foo1 #t)
   (foo1 #f)))

(time
 (for ([i N])
   (foo2 #t)
   (foo2 #f)))

```

produces:

```scheme
cpu time: 882 real time: 887 gc time: 125
cpu time: 642 real time: 628 gc time: 114

```

But if these functions are also used within the module boundary a lot, avoiding the allocations could be very worthwhile

```scheme
#lang racket

(module test racket
  (define f1/c
    (->i ([_ any/c])
         (values [x (or/c string? #f)]
                 [y (x) (if (string? x) string? #f)])))

  (define f2/c
    (-> any/c (or/c (cons/c string? string?) (cons/c #f #f))))

  (provide (contract-out
            [foo1 f1/c]
            [foo2 f2/c]))

  (define (foo1 b)
    (cond
      [(= 0 b) (values "answer" "x")]
      [(= 1 b) (values #f #f)]
      [else
       (define-values (v1 v2) (foo1 (sub1 b)))
       (values v2 v1)]))

  (define (foo2 b)
    (cond
      [(= 0 b) (cons "answer" "x")]
      [(= 1 b) (cons #f #f)]
      [else
       (define p (foo2 (sub1 b)))
       (cons (cdr p) (car p))])))

(require 'test)

(define N 100000)
(define S 100)

(time
 (for ([i N])
   (foo1 S)
   (foo1 (add1 S))))

(time
 (for ([i N])
   (foo2 S)
   (foo2 (add1 S))))

```

produces:

```scheme
cpu time: 1279 real time: 1197 gc time: 406
cpu time: 2044 real time: 1991 gc time: 660

```

You can get an even more performant version by using multiple values within the module boundary, and switch to cons across module boundaries. But that seems cumbersome and not worthwhile doing, unless this part of the program is really performance-sensitive.

---

<div class="post-metadata">

### Author: ![badkins](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/badkins/32/99_2.png) [@badkins](https://racket.discourse.group/u/badkins)
#### Post date: [April 27, 2023, 1:26pm UTC](https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284/14 "2023-04-27T13:26:43Z")

</div>

> [@joeld](#):
>
> Ok, I see. I hadn’t thought of that! But that kind of optimization in this particular context is still a head-scratcher for me. Clearly you want to make some guarantees about the return value here, or you wouldn’t be using contracts. But the contracts themselves introduce a performance penalty that I would assume is far higher than that of the allocation of a single cons cell. If you’re already willing to incur that penalty, why not go a little further and do it in a way that actually makes the guarantee you want to make?

I design my functions independently of contracts. Contracts are optional, and in some cases, I'll turn them off, for performance, or other, reasons. They're more of a benefit to me during development and testing, than in production.

So, when I consider the performance of a function, I do so w/o regard to contracts i.e. "what's the right thing for this function to do if there was no contract".
