I’m the sole employee of Lojic Technologies, and for the past few years, I’ve been developing back-end heavy Racket web applications for a client.
I’d like to do the following for the return values of a function, but it doesn’t work in this form. Anyone have an idea how to accomplish this? (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.
I broke my own rule of preferring to ask questions on Discourse - I’ll post there now, so if possible, answer there…
…done <https://racket.discourse.group/t/function-contracts-for-multiple-return-values/284|Discourse link>
I’m not on Discourse, so I will answer here:
One possibility is lifting or/c
over ->
(or/c (-> ... (values t1 t2)) (-> ... (values t3 t4)))
Hmm… I’m not sure if being in a class complicates things, but I tried the following: (or/c
(->m connection? string? string? (values hash? '()))
(->m connection? string? string? (values #f (listof string?))))
and received an error: get-user-data: broke its own contract\n two of the clauses in the or/c might both match: (->m connection? string? string? (values hash? (quote ()))) and (->m connection? string? string? (values #f (listof string?)))
Oh interesting. I do get this error too, so that probably is not the right idea
Definitely a good try though - thanks :)
My API is questionable anyway, so the proper thing may be to revise the function signature, but I’m still curious about whether it’s possible.
> If there are multiple higher-order contracts, or/c uses contract-first-order-passes? to distinguish between them. More precisely, when an or/c is checked, it first checks all of the flat contracts. If none of them pass, it calls contract-first-order-passes? with each of the higher-order contracts. If only one returns true, or/c uses that contract. If none of them return true, it signals a contract violation. If more than one returns true, it also signals a contract violation. For example, this contract
Apparently, there’s a “dependent range” feature.
I can see how distinguishing only on return value adds complexity.
#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
I’m kinda unhappy with this
Apparently, the return arity must be the same.
Equal return arity seems reasonable - I’ll fool around with it - thanks!
FYI - I posted your solution on Discourse w/ attribution. You’re always so helpful, can I tempt you to joining Discourse? :)
I don’t have time to incorporate it into my class right now, but if I can get it to work tomorrow, I’ll mark it as “solved” on Discourse.
Sure, I will join at some point. @spdegabrielle mentioned that there are a lot of seeding posts / experiments at the beginning, and that is why I hesitated to join. But once the forum is past the experimenting phase, I hope things will be more stable and organic, and I would love to join then.