On Fri, Mar 31, 2017 at 4:00 PM, David Storrs <david.sto...@gmail.com> wrote:
> Imagine I have the following trivial module (ignore that things are defined
> out of sequence for clarity):
>
> #lang racket
>
> (define (foo arg)
>     (_baz arg)  ; do some checking, raise an exception if there's a problem
>     ...do stuff...
> )
>
> (define (bar arg)
>     (_baz arg)  ; do some checking, raise an exception if there's a problem
>     ...do stuff....)
>
> (define (_baz arg)  ; internal helper function
>     (when (equal? arg "bad value")
>         (raise-arguments-error '_baz "got a bad value" "val" val))) ;; <===
> report is from _baz, not foo or bar
>
> (provide foo bar)
>
>
> In Perl I can use caller() [1] to access the stack so that I can have _baz
> report errors as though the error were coming from 'foo' or 'bar' as
> appropriate -- which is what the user expects to see, since their code
> called 'foo' or 'bar', not '_baz'.  (Even better, I could report as though
> the error were coming from the *caller* of foo / bar, which is the user's
> actual code and the real source of the problem.) How can I do the same in
> Racket?  I see the errortrace library, but that says "don't install this
> into a module and expect it to work."
>
> I could pass the name down, of course, but that's clumsy.  I could also
> create a parameter and set it every time I call the helper function that
> needs it, but that's even more clumsy / action-at-a-distance-y and easy to
> forget.  What's the right way?
>
>
> [1] https://perldoc.perl.org/functions/caller.html
>


Depending on your exact situation, you may be able to get the contract
system to do the work for you. A non-trivial example from actual code:

In the Gregor library, there are a number of constructors that accept
year, month, and day arguments. All of them need to ensure that the
combination refers to an actual day. Instead of having each use code
like:

     (if (date-exists? year month day)
       (something-useful)
       (raise-bad-date ...))

those functions all have contracts like:

```
[date (->i ([year exact-integer?])
           ([month (integer-in 1 12)]
            [day (year month) (day-of-month/c year month)])
           [d date?])]
```

The most interesting argument contract there is `day-of-month/c`,
which checks the `day` argument, but depends on both `year` and
`month`, as well.

`day-of-month/c` is defined like this:

```
(define (day-of-month/c y m)
  (integer-in 1 (days-in-month y m)))
```
Where `days-in-month` does what you would expect.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to