Stephen's mention of web server code reminded of me one of the very few
situations when I've struggled with Racket error messages, so I'll both
share an example and explain why I haven't complained about it before.

Here's a buggy program:

> #lang web-server
> (require web-server/servlet-env
>          web-server/formlets
>          racket/date)
> (define (start request)
>   (response/xexpr
>    `(html (head (title "Output"))
>           (body (p "You entered this date: "
>                    (b ,(get-date)))))))
> (define (get-date)
>   (define the-formlet
>     (make-date-formlet))
>   (formlet-process
>    the-formlet
>    (send/suspend
>     (λ (k-url)
>       (response/xexpr
>        `(html (head (title "Get Input"))
>               (body (h1 "Enter Some Date")
>                     (form ([method "POST"]
>                            [action ,k-url])
>                           ,@(formlet-display
>                              the-formlet)))))))))
> (define (make-date-formlet)
>   (formlet
>    (#%# ,{=> (text-input #:value (date->string
>                                   (current-date))
>                          #:attributes `([required ""]))
>              date-str}
>         (input ([type "submit"])))
>    date-str))
> (serve/servlet start #:stateless? #t)


Trying to run this program produces an error message that is in many ways
quite good: the message says:

stuff-url: Cannot stuff (kont #<procedure:...abort-resume.rkt:154:25>)
into a URL because it contains non-serializable pieces. Convert
#<procedure:...formlets/lib.rkt:17:2> to a serializable struct

In a tiny example like this, that's enough for me to pinpoint the bug:
formlets are represented internally as procedures, so the output of
(make-date-formlet) cannot be serialized when it's called in (get-date).

However, in larger #lang web-server programs, and especially in earlier
stages of my becoming familiar with #lang web-server, the stack trace is
unhelpful and a bit intimidating: it begins with

select-handler/no-breaks at:
  line 163, column 2, in file /Applications/Racket
v6.7/collects/racket/private/more-scheme.rkt

and runs through a list of "<unknown procedure>"s until concluding with

<unknown procedure> at:
  line 131, column 8, in file /Applications/Racket
v6.7/share/pkgs/web-server-lib/web-server/private/dispatch-server-with-connect-unit.rkt

At no point do any of the modules named or anything like that refer to my
code.

So why have I not complained about this?

First, most generally, because the bug is clearly my fault. Even when I was
at a stage of learning when I would have struggled to debug this, the
documentation makes it very clear that "the values in the lexical scope of
your continuations must be serializable for the continuations itself to be
serializable." Likewise, the formlet documentation explains that formlets
are implemented as procedures, and there are even old posts on this mailing
list specifically discussing the fact that formlets are not serializable.
So it would seem a bit decadent, I suppose, to complain about an error
message that is (especially by the standards of other languages) not
terrible at all, and which is sufficient to make it clear that, even if I'm
not immediately sure what the problem is, it's something I need to find and
fix in my code, not something the author of the library did wrong. (In
fact, it is something that the author of the library specifically warned me
not to do, though that makes it even more perplexing when I can't
immediately figure out how I managed to do it anyway.)

Second, in the specific case of #lang web-server, I considered the
extensive transformations that run on the source-text of my code to get
serializable continuations, and which seem to have something to do with the
fact that stack traces and errors in #lang web-server are generally harder
to understand than in #lang racket (certainly they do not have Dr. Racket
highlight the offending passages of my program in red, with beautiful
arrows to show me the context in which they occurred — but that is quite a
high standard indeed). As Stephen said, the internals seemed intimidating
and I felt a bit out of my depth, but also, specifically, it seemed like
improving this situation might be more of a hard technical problem than
just using contract-out at the right place.

I'll end with a thank you for all of the thought you all have given to
useful error messages, and for contracts specifically. It certainly is one
of the reasons I have been doing so much of my programming in Racket
lately. I took an HtDP-based course after many years of programming in
traditional/imperative languages, and one of the many transformative things
I learned from it was the importance of thinking specifically about the
legal inputs and outputs of each function. I have come more and more to use
contracts internally in the code I write, because whatever hypothetical
performance cost I may incur is almost always worth it to take advantage of
this incredible infrastructure for pinpointing the problem when (not if) I
produce runtime errors.

Happy New Year,
Philip

On Sun, Jan 1, 2017 at 4:46 PM, Robby Findler <ro...@eecs.northwestern.edu>
wrote:

> I mostly agree with Matthias, but wanted to add two things:
>
> 1) I've certainly experienced, many times, (both as the producer and
> consumer (and sometimes simultaneously)) contracts that were added
> because of runtime errors. But I do agree it is not as common as we
> had hoped it would be. And Stephen's comments suggest that there is a
> cultural issue here. So in that spirit, I want to say: please report
> (as bugs!) code that raises errors down in its bowels instead of at
> some more natural boundary in the code.
>
> 2) there is a technical difference between where the error is
> discovered and where the contract goes and the error messages
> generally have both of these components in them. It may be that the
> error message text isn't clear and these two separate things are
> getting conflated. (Overall, it is okay if the error is actually
> discovered in the bowels and this information shows up in the stack
> trace attached to the error message; the thing Matthias and I are
> thinking about is whether or not there is a contract that lives at
> some more reasonable boundary between the library you're using and the
> code you wrote that uses it.)
>
> Regardless, do post these errors. Feel free to ask if they seem to be
> missing checks or if something else is going on and lets try to build
> a better culture about getting good error messages!
>
> Happy New Year. :)
>
> Robby
>
>
>
> On Sun, Jan 1, 2017 at 12:51 PM, Matthias Felleisen
> <matth...@ccs.neu.edu> wrote:
> >
> >> On Jan 1, 2017, at 1:17 PM, Stephen De Gabrielle <
> spdegabrie...@gmail.com> wrote:
> >>
> >> Hi All,
> >>
> >> I occasionally write code with errors* that cause the DrRacket error
> message to link to an internal Racket file, rather than my own incorrect
> code.
> >>
> >> The last time I did this it was doing web server code, but I've also
> managed it with GUI code.(and playing with DrRacket Plugins)
> >>
> >> I've not filed a report (or attempted a patch) on this before, mostly
> out of embarrassment, but also because because I feel out of my depth in
> the racket internals and the error was in my own code.
> >>
> >> Should I report these when I find them? Should I attempt to work out
> the cause and attempt a patch?
> >
> >
> > A long time ago, Robby and I conjectured that if people reported those
> kinds of errors, the creators of libraries would eventually protect their
> APIs with contracts and the software would become more robust. This
> ‘gradual hardening’ with contracts did not happen over time. Sure, some
> people added contracts to libraries, others wrote them in Typed Racket. But
> all in all, we added contracts because we wanted to not because of ‘client
> pressure.’
> >
> > Your email is validation that something was wrong with our conjecture,
> but I can’t figure out what exactly is wrong. The word ‘fear’ and
> ‘embarrassment’ are suggestive. Perhaps developers are intimidated by the
> creators APIs and Libraries, because these people must be so much better
> and can’t possibly make mistakes.
> >
> > Well we all make mistakes and if others report them, we get better at
> overcoming these mistakes (starting with the elimination of bugs).
> >
> > Happy New Year — Matthias
> >
> > --
> > 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.
>
> --
> 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.
>

-- 
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