# How to attach contract on generic function?

**URL:** <https://racket.discourse.group/t/how-to-attach-contract-on-generic-function/3297>\
**Category:** Questions & Answers\
**Tags:** question, contract, generics\
**Created:** [November 6, 2024, 10:58am UTC](https://racket.discourse.group/t/how-to-attach-contract-on-generic-function/3297 "2024-11-06T10:58:21Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andy](https://avatars.discourse-cdn.com/v4/letter/a/aeb1de/32.png) [@Andy](https://racket.discourse.group/u/Andy)\
**Post date:** [November 6, 2024, 10:58am UTC](https://racket.discourse.group/t/how-to-attach-contract-on-generic-function/3297/1 "2024-11-06T10:58:21Z")

</div>

Hello! I'm trying to use contract with generic functions. However, the code doesn't work as expected:

```scheme
#lang racket
(require racket/generic)
(define-generics g
  (g-func g))
(struct s ()
  #:methods gen:g
  [(define/contract (g-func x)
     (-> s? s?)
     x)])

```

Running the code in DrRacket would result in

```plaintext
s?: undefined;
 cannot reference an identifier before its definition

```

But it's fine to use `s?` inside the body of `g-func`, outside the contract definition. e.g. `(define (g-func x) (when (s? x) x))`. Why does it happen? Am I using contract the wrong way?

---

<div class="post-metadata">

**Author:** ![bakgatviooldoos](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/bakgatviooldoos/32/1381_2.png) [@bakgatviooldoos](https://racket.discourse.group/u/bakgatviooldoos)\
**Post date:** [November 6, 2024, 1:44pm UTC](https://racket.discourse.group/t/how-to-attach-contract-on-generic-function/3297/2 "2024-11-06T13:44:37Z")

</div>

Hi, @Andy.

I have not used generics enough to know right from wrong, but hopefully if I post a kind-of wrong answer, someone will correct that.

Technically, this works, but I assume there is probably something going on here that should be addressed differently. It is because the binding for `s?` does not exist yet in the context which the contract is being created. But, by wrapping the procedure, we obviate that (at the cost of some indirection).

```scheme
(require racket/generic)

(define-generics g (g-func g))
(struct s ()
  #:methods gen:g
  [(define/contract (g-func x)
     (-> (λ (x) (s? x))
         (λ (x) (s? x)))
     x)])

(g-func (s))
;=> #<s>

```

* * *

Edit:  
To be more precise, you can think of the contract as something that is separate from the body of the procedure. So, the body will not be "evaluated" at the same time as the terms for the contract, and so will not be subject to this contextual mismatch. We achieve the same mechanic by wrapping the `s?` in a `lambda`.

---

<div class="post-metadata">

**Author:** ![Andy](https://avatars.discourse-cdn.com/v4/letter/a/aeb1de/32.png) [@Andy](https://racket.discourse.group/u/Andy)\
**Post date:** [November 6, 2024, 2:43pm UTC](https://racket.discourse.group/t/how-to-attach-contract-on-generic-function/3297/3 "2024-11-06T14:43:50Z")

</div>

Thanks for your solution!  
It's surprising that wrapping it up in a lambda works. Now I understand that the error

```scheme
cannot reference an identifier before its definition

```

occurs when someone tries to access an identifier which is defined but not bound, e.g. `(define a a)`. When writing a contract, the expression is immediately evaluated, so the error occurs. But in the body of `g-func`, it's okay to use `s?` because it won't be evaluated until being called.

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [November 6, 2024, 4:07pm UTC](https://racket.discourse.group/t/how-to-attach-contract-on-generic-function/3297/4 "2024-11-06T16:07:57Z")

</div>

Although I have almost no hands-on real-world experience with `racket/generic`, I suspect the intended or typical case is to use `define` for the `#:methods` -- not `define/contract`.

I imagine often people don't use a contact at all (it might be too expensive)?

Or they attach a contract on export with `(provide (contract-out ...))` (if that even makes sense for generics)?

Or I suppose you could `define/contract` a plain old helper function, and the method is a wrapper calling that?

Anyway this is one of my half-arsed answers, the main value of which will be to provoke someone to correct me, and voila, you get _that_ answer. 😄
