Arc Forumnew | comments | leaders | submitlogin
Arc's err vs Racket's error re: quote characters
2 points by zck 3818 days ago | 7 comments
I'm having trouble throwing errors with quotes in the strings.

    (err "oh no! We should have \"abc\" but we have \"abcd\".")
The output here is not the expected

    Error: "oh no! We should have "abc" but we have "abcd"."
But instead, that message with quotes escaped:

    Error: "oh no! We should have \"abc\" but we have \"abcd\"."
Ugh. I'm not really sure why that happens; err is defined in ac.scm as:

    (define err error)
And it works just fine in Racket:

    > (error "oh no! We should have \"abc\" but we have \"abcd\".")
    oh no! We should have "abc" but we have "abcd".
      context...:
       /usr/share/racket/collects/racket/private/misc.rkt:87:7
So I'm not sure what's going on.


3 points by fallintothis 3818 days ago | link

This is actually due to the code that handles errors in the REPL. Notice that it uses write to display the exception message instead of display:

    (define (tl2)
      (display "arc> ")
      (on-err (lambda (c) 
                (set! last-condition* c)
                (display "Error: ")
                (write (exn-message c))
                (newline)
                (tl2))
        ...))
Never known why, myself...

-----

3 points by zck 3818 days ago | link

Ugh, that's awful. I want to print out error messages that, in part, can be copied and pasted into the REPL. Right now, since double quotes are escaped, I'm printing single quotes, which obviously don't work. (https://bitbucket.org/zck/unit-test.arc/issue/40/make-error-...)

I guess this is a reason to switch to Anarki. But even that doesn't help too much given that I want unit-test.arc to work with arc3.1.

-----

2 points by fallintothis 3818 days ago | link

To play devil's advocate (and/or nihilist), why do you need that? Error messages in Arc are already universally this way, so it's expected behavior that the messages look crappy. :P

On a more constructive note, is there some part of your code (or could there be, with some rewriting) where you could specifically catch the exception whose message you want to display nicely? Seems like you could probably work out some way to wrap something like:

    arc> (on-err (fn (c)
                    (pr "Error: ")
                    (prn (details c)))
                 (fn () (err "a \"b\" c")))
    Error: a "b" c
Even with a macro:

    (mac w/nice-errors exprs
      `(on-err [do (pr "Error: ") (prn (details _))]
               (fn () ,@exprs)))
It's a bit of hack, but if you need to subvert the language's defaults in an implementation-conforming way, them's the breaks.

Side note: paging through your source code, I notice you have a few functions to support to-readable-string. I believe it could be greatly simplified, because write's job is already to print out values in ways that read can parse back in. Thus, save for the single-quote stuff, I think you could boil it all down to tostring:write. Play around with it and see if it's what you want:

    arc> (tostring:write (list 'a "b" (obj c 'd)))
    "(a \"b\" #hash((c . d)))"

-----

2 points by zck 3818 days ago | link

> To play devil's advocate (and/or nihilist), why do you need that? Error messages in Arc are already universally this way, so it's expected behavior that the messages look crappy. :P

Because I'm not satisfied with crappy behavior. It makes readability worse, and debugging harder.

I'll take a look to see if I can catch it better; reading over my code, some of it does seem to be convoluted, if working. I've never quite been happy with how the failure messages are calculated; if that changes, I can easily change how we handle printing the errors.

Other than the double-quote issue, I don't recall other big reasons to use to-readable-string. I'd certainly be a fan of removing code, if I can make it work. It would bring my macro:function ratio below 1:1 again, which would be awesome. :)

-----

2 points by akkartik 3818 days ago | link

The reason to use 'write rather than 'display is precisely so that things can be pasted into the repl. All you should have to do is 'read and 'eval the entire error string.

But there's definitely something busted about this. In anarki:

  arc> (= x "abc")
  arc> (err x)
  Error: "abc"           ; ok, looks good
  arc> (= x 'abc)
  arc> (err x)
  Error: "error: abc"    ; whaa..
There's also a long-standing issue that's bothered me before:

  arc> (= x "abc")
  arc> (err x " shouldn't be a string")
  Error: "abc \" shouldn't be a string\""
You're right, that's pretty ghastly. It should print:

  Error: "abc" shouldn't be a string
or:

  Error: "\"abc\" shouldn't be a string"
I'm still mulling what the culprit is here, but I don't think it's write vs display.

-----

4 points by rocketnia 3818 days ago | link

The culprit is that 'err is defined to be Racket's 'error. It looks like every single use case of 'error is discouraged for one reason or another in the Racket reference:

http://docs.racket-lang.org/reference/exns.html#%28def._%28%...

- (error sym) creates a message string by concatenating "error: " with the string form of sym. Use this form sparingly.

- (error msg v ...) creates a message string by concatenating msg with string versions of the vs (as produced by the current error value conversion handler; see error-value->string-handler). A space is inserted before each v. Use this form sparingly, because it does not conform well to Racket’s error message conventions; consider raise-arguments-error, instead.

- (error src frmat v ...) creates a message string equivalent to the string created by

  (format (string-append "~s: " frmat) src v ...)
When possible, use functions such as raise-argument-error, instead, which construct messages that follow Racket’s error message conventions.

-----

2 points by rocketnia 3816 days ago | link

Er, I knew it was weird for me to say "'err is defined to be Racket's 'error," but I just realized, that factoid was in the original post of this thread. :-p

-----