No subject
From: ()
Date: Wed Aug 28 11:57:11 EDT 2013 |
|
$ cat abc.rkt
#lang racket
(provide
(contract-out
[add-number (-> number? number? number?)]))
(define (add-number x y) (+ x y))
$ cat edf.rkt
#lang racket
(require "abc.rkt")
(add-number "1" 2)
$ racket -l errortrace -t edf.rkt
add-number: contract violation
expected: number?
in: the 1st argument of
(-> number? number? number?)
contract from: /Users/robby/Desktop/abc.rkt
blaming: /Users/robby/Desktop/edf.rkt
at: /Users/robby/Desktop/abc.rkt:4.3
errortrace...:
/Users/robby/Desktop/edf.rkt:3:0: (lifted.0 (quote "1") (quote 2))
/Users/robby/Desktop/edf.rkt:3:0: (call-with-values (lambda () (lifted.0
(quote "1") (quote 2))) print-values)
context...:
/Users/robby/git/plt/racket/collects/racket/contract/private/blame.rkt:135=
:0:
raise-blame-error
/Users/robby/Desktop/edf.rkt: [running body]
As you can see, the source location of the call is there (those "lifted.0"s
are unfortunate, however).
There are no values of local variables, however. Last time I checked,
errortrace runs at about a factor of 3 slowdown to just record the precise
stack traces that it does record (and as the compiler gets better, the gap
gets bigger) so the right tradeoff isn't very clear there either. And,
given Racket's "language workbench" capabilities, this is something that
anyone can experiment with. errortrace is a library that is implemented by
traversing a fully expanded program and dropping in with-continuation-marks
in just the right places. Then these marks can be read back and
reconstructed into a stack trace. The debugger works the same way, except
that it's instrumentation actually does capture local variables. I don't
know the relative performance of the two, but we could certainly experiment
with using something more like the debugger's annotations.
Returning to the original message in the thread, I don't know how the OP
wrote their program in a way to get no stacktrace information at all;
possibly it was at the top-level, in which case there was no stacktrace to
report and I guess in 'real life' one wouldn't complain in this case anyway=
.
I have given a little bit of thought to enhancing the arrow contract
combinators (things like -> and ->* and ->i) so the detect the case when a
first-order portion of one of the argument contract fails and then report
all the other arguments, which would, in this case, report the number 2 in
the edf.rkt file, something missing from the error messages that'd be nice
to see. I'm not sure how to do without hurting performance in an
unacceptable way. But probably I just haven't tried hard enough.
Robby
[1] I find myself writing this little program fragment a lot when I can't
figure how code is getting to some bad spot:
(printf "----------\n")
(for ([x (in-list
(continuation-mark-set->context
(current-continuation-marks)))])
(printf " ~s\n" x))
(printf "----------\n")
It can be very helpful.
On Sun, Sep 8, 2013 at 4:06 PM, Daniel Prager <daniel.a.prager at gmail.com>wr=
ote:
> For the consideration of Robby et al:
>
> The clearest run-time errors I ever received were dumped out of
> SmallEiffel / SmartEiffel in response to contract violations.
>
> These were stack-traces that -- critically -- included parameter values
> and local state information for each stack frame. Blame for pre- and
> post-condition violations were easy to read off, down to the line / colum=
n.
>
> Example from http://www.minimalprogramming.org/proglang.pdf pp177-:
>
> *** Error at Run Time ***: Require Assertion Violated.
> *** Error at Run Time ***: consistent_balance
> 3 frames in current stack.
> =3D=3D=3D=3D=3D Bottom of run-time stack =3D=3D=3D=3D=3D
> System root.
> Current =3D TEST#0x8061a60
> line 4 column 2 file ./test.e
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> make TEST
> Current =3D TEST#0x8061a60
> account =3D Void
> line 8 column 4 file ./test.e
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> make ACCOUNT
> Current =3D ACCOUNT#0x8061a88
>
> [ minimal_balance =3D 0.000000
>
> balance =3D 0.000000
>
> ]
>
> a_minimal_balance =3D 100.000000
> initial_balance =3D 10.000000
> line 7 column 42 file ./account.e
> =3D=3D=3D=3D=3D Top of run-time stack =3D=3D=3D=3D=3D
> *** Error at Run Time ***: Require Assertion Violated.
> *** Error at Run Time ***: consistent_balance
>
>
> The author remarks, "That=E2=80=99s what I call a comprehensive error des=
cription.
> Not only do we get the name of the violated condition and the values of t=
he
> parameters passed to the constructor method, but also the state of the
> account object in question."
>
> This could be improved further. When I rolled my own contracts for C#
> (pre-MS code contracts) I captured and reprocessed the stack trace to
> included a "----->" to point at the line/column reference to the calling
> code (for a pre-condition violation) or the supplying code (for a
> post-condition violation). I also reversed the direction of the trace so
> that errors would appear at the top, thereby avoiding having to read down=
a
> long trace when the error was usually apparent from the the top.
>
> But those aspects are sugar, although pedagogically usefully and
> practically very convenient. Frustratingly, what I couldn't do, was dump
> out parameters (and state) automatically, necessitating manual annotation
> in the contract violation messages (which then became a risk/reward
> trade-off).
>
> Cheers
>
> Dan
>
>
> On Sun, Sep 8, 2013 at 11:40 PM, Robby Findler <
> robby at eecs.northwestern.edu> wrote:
>
>> You are not the only one to complain :). We've been having an internal
>> discussion about this, actually.
>>
>> In this particular, case, I think that you are using provide/contract,
>> right? If so, the blame really lies with the entire file edf.rkt. So the=
re
>> really isn't anything more specific to say.
>>
>> Robby
>>
>>
>>
>> On Sun, Sep 8, 2013 at 4:20 AM, antoine <antoine597 at gmail.com> wrote:
>>
>>> Hello,
>>>
>>> I have just start using contracts in racket, but i am a bit disapointed
>>> by the
>>> error message they give to me.
>>>
>>> example contract error:
>>>
>>> add-number: contract violation
>>> expected: number?
>>> given: "1"
>>> in: the 2nd argument of
>>> (-> number? number? number?)
>>> contract from: abc.rkt
>>> blaming: edf.rkt
>>> at: abc.rkt:5.3
>>>
>>> I would have expected to have the line and column number in the blaming
>>> line
>>> like what you could get from a stacktrace.
>>>
>>> Is it possible in contracts?
>>> Am i the only one to complain? :)
>>>
>>> Thanks you in advance.
>>> ____________________
>>> Racket Users list:
>>> http://lists.racket-lang.org/**users<http://lists.racket-lang.org/user=
s>
>>>
>>
>>
>> ____________________
>> Racket Users list:
>> http://lists.racket-lang.org/users
>>
>>
>
>
> --
> *Daniel Prager*
> Agile/Lean Coaching, Software Development and Leadership
> Twitter: @agilejitsu <https://twitter.com/agilejitsu>
> Blog: agile-jitsu.blogspot.com
>
--047d7b2e46f0a2dac304e5e61421
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Thank you for your thought, Dan. Here are some of min=
e in return.</div><div><br></div>I would say that there are several separat=
e things going on here and we'd benefit from separating them in our dis=
cussion. As I understand them, contract violations are separate from stack =
traces. A contract violation is the discovery that something gone wrong in =
a specific program state (which is what essentially all of the fields in th=
e OP's message show). A stack trace tries to reconstruct something abou=
t the context of that call in the underlying VM and is subject to the vagar=
ies of things happening in Racket's optimizer. You can get stacktraces =
at any point in a Racket program [1] and they are useful for other kinds of=
debugging than just from figuring out when an error occurred.<div>
<br></div><div>Anyway, here's my attempt to reconstruct from the error =
message, a program that behaves like the OP, but run with our better stack =
printing mechanism (errortrace, it's called) turned on.=C2=A0</div><div=
>
<br></div><div>From my terminal window:</div><div><br></div><div><div>$ cat=
abc.rkt</div><div>#lang racket</div><div>(provide</div><div>=C2=A0(contrac=
t-out=C2=A0</div><div>=C2=A0 [add-number (-> number? number? number?)]))=
</div><div>
(define (add-number x y) (+ x y))</div><div>$ cat edf.rkt<br></div><div>#la=
ng racket</div><div>(require "abc.rkt")</div><div>(add-number &qu=
ot;1" 2)</div><div>$ racket -l errortrace -t edf.rkt<br></div><div>
add-number: contract violation</div><div>=C2=A0 expected: number?</div><div=
>=C2=A0 in: the 1st argument of</div><div>=C2=A0 =C2=A0 =C2=A0 (-> numbe=
r? number? number?)</div><div>=C2=A0 contract from: /Users/robby/Desktop/ab=
c.rkt</div><div>=C2=A0 blaming: /Users/robby/Desktop/edf.rkt</div>
<div>=C2=A0 at: /Users/robby/Desktop/abc.rkt:4.3</div><div>=C2=A0 errortrac=
e...:</div><div>=C2=A0 =C2=A0/Users/robby/Desktop/edf.rkt:3:0: (lifted.0 (q=
uote "1") (quote 2))</div><div>=C2=A0 =C2=A0/Users/robby/Desktop/=
edf.rkt:3:0: (call-with-values (lambda () (lifted.0 (quote "1") (=
quote 2))) print-values)</div>
<div>=C2=A0 context...:</div><div>=C2=A0 =C2=A0/Users/robby/git/plt/racket/=
collects/racket/contract/private/blame.rkt:135:0: raise-blame-error</div><d=
iv>=C2=A0 =C2=A0/Users/robby/Desktop/edf.rkt: [running body]</div><div><br>=
</div></div><div>As you can see, the source location of the call is there (=
those "lifted.0"s are unfortunate, however).=C2=A0</div>
<div><br></div><div>There are no values of local variables, however. Last t=
ime I checked, errortrace runs at about a factor of 3 slowdown to just reco=
rd the precise stack traces that it does record (and as the compiler gets b=
etter, the gap gets bigger) so the right tradeoff isn't very clear ther=
e either. And, given Racket's "language workbench" capabiliti=
es, this is something that anyone can experiment with. errortrace is a libr=
ary that is implemented by traversing a fully expanded program and dropping=
in with-continuation-marks in just the right places. Then these marks can =
be read back and reconstructed into a stack trace. The debugger works the s=
ame way, except that it's instrumentation actually does capture local v=
ariables. I don't know the relative performance of the two, but we coul=
d certainly experiment with using something more like the debugger's an=
notations.</div>
<div><br></div><div>Returning to the original message in the thread, I don&=
#39;t know how the OP wrote their program in a way to get no stacktrace inf=
ormation at all; possibly it was at the top-level, in which case there was =
no stacktrace to report and I guess in 'real life' one wouldn't=
complain in this case anyway.</div>
<div><br></div><div>I have given a little bit of thought to enhancing the a=
rrow contract combinators (things like -> and ->* and ->i) so the =
detect the case when a first-order portion of one of the argument contract =
fails and then report all the other arguments, which would, in this case, r=
eport the number 2 in the edf.rkt file, something missing from the error me=
ssages that'd be nice to see. I'm not sure how to do without hurtin=
g performance in an unacceptable way. But probably I just haven't tried=
hard enough.</div>
<div><br></div><div>Robby</div><div><br></div><div>[1] =C2=A0I find myself =
writing this little program fragment a lot when I can't figure how code=
is getting to some bad spot:</div><div><br></div><div><div>(printf "-=
---------\n")</div>
<div>(for ([x (in-list</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (contin=
uation-mark-set->context</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0(current-continuation-marks)))])</div><div>=C2=A0 (printf " =C2=
=A0~s\n" x))</div><div>(printf "----------\n")</div>
</div><div><br></div><div>It can be very helpful.</div><div><br></div><div =
class=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On Sun, Sep 8, 201=
3 at 4:06 PM, Daniel Prager <span dir=3D"ltr"><<a href=3D"mailto:daniel.=
a.prager at gmail.com" target=3D"_blank">daniel.a.prager at gmail.com</a>></sp=
an> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr">For the consideration of Robby et al:<div=
><div>
<br></div><div>The clearest run-time errors I ever received were dumped out=
of SmallEiffel / SmartEiffel in response to contract violations.</div><div=
><br></div>
<div>These were stack-traces that -- critically -- included parameter value=
s and local state information for each stack frame. =C2=A0Blame for pre- an=
d post-condition violations were easy to read off, down to the line / colum=
n.</div>
<div><br></div><div>Example from=C2=A0<a href=3D"http://www.minimalprogramm=
ing.org/proglang.pdf" target=3D"_blank">http://www.minimalprogramming.org/p=
roglang.pdf</a> pp177-:</div><div><br></div><blockquote style=3D"margin:0px=
0px 0px 40px;border:none;padding:0px">
<div><div>*** Error at Run Time ***: Require Assertion Violated.</div></div=
><div><div>*** Error at Run Time ***: consistent_balance</div></div><div><d=
iv>3 frames in current stack.</div></div><div><div>=3D=3D=3D=3D=3D Bottom o=
f run-time stack =3D=3D=3D=3D=3D</div>
</div><div><div>System root.</div></div><div><div>Current =3D TEST#0x8061a6=
0</div></div><div><div>line 4 column 2 file ./test.e</div></div><div><div>=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D</div></div><div><div>make TEST</div=
>
</div><div><div>Current =3D TEST#0x8061a60</div></div><div><div>account =3D=
Void</div></div><div><div>line 8 column 4 file ./test.e</div></div><div><d=
iv>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D</div></div><div><div>make ACCOUN=
T</div>
</div><div><div>Current =3D ACCOUNT#0x8061a88</div></div></blockquote><bloc=
kquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><blockquot=
e style=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div><div>=C2=
=A0 [ minimal_balance =3D 0.000000</div>
</div></blockquote><blockquote style=3D"margin:0px 0px 0px 40px;border:none=
;padding:0px"><div><div>=C2=A0 =C2=A0 balance =3D 0.000000</div></div></blo=
ckquote><blockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0p=
x"><div><div>
=C2=A0 ]</div></div></blockquote></blockquote><blockquote style=3D"margin:0=
px 0px 0px 40px;border:none;padding:0px"><div><div>a_minimal_balance =3D 10=
0.000000</div></div><div><div>initial_balance =3D 10.000000</div></div><div=
><div>
line 7 column 42 file ./account.e</div>
</div><div><div>=3D=3D=3D=3D=3D Top of run-time stack =3D=3D=3D=3D=3D</div>=
</div><div><div>*** Error at Run Time ***: Require Assertion Violated.</div=
></div><div><div>*** Error at Run Time ***: consistent_balance</div></div><=
/blockquote><div>
<br></div><div>The author remarks, "That=E2=80=99s what I call a compr=
ehensive error description. Not only do we get the name of the violated con=
dition and the values of the parameters passed to the constructor method, b=
ut also the state of the account object in question."</div>
<div><br></div><div>This could be improved further. =C2=A0When I rolled my =
own contracts for C# (pre-MS code contracts) I captured and reprocessed the=
stack trace to included a "----->" to point at the line/colum=
n reference to the calling code (for a pre-condition violation) or the supp=
lying code (for a post-condition violation). =C2=A0I also reversed the dire=
ction of the trace so that errors would appear at the top, thereby avoiding=
having to read down a long trace when the error was usually apparent from =
the the top. =C2=A0</div>
<div><br></div><div>But those aspects are sugar, although pedagogically use=
fully and practically very convenient. =C2=A0Frustratingly, what I couldn&#=
39;t do, was dump out parameters (and state) automatically, necessitating m=
anual annotation in the contract violation messages (which then became a ri=
sk/reward trade-off).<br>
</div><div><br></div><div>Cheers</div><div><br></div><div>Dan</div><div><br=
></div></div><div class=3D"gmail_extra"><div><div class=3D"h5"><br><div cla=
ss=3D"gmail_quote">On Sun, Sep 8, 2013 at 11:40 PM, Robby Findler <span dir=
=3D"ltr"><<a href=3D"mailto:robby at eecs.northwestern.edu" target=3D"_blan=
k">robby at eecs.northwestern.edu</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr">You are not the only one to complain :). =
We've been having an internal discussion about this, actually.<div>
<br></div><div>In this particular, case, I think that you are using provide=
/contract, right? If so, the blame really lies with the entire file edf.rkt=
. So there really isn't anything more specific to say.</div><span><font=
color=3D"#888888">
<div><br></div><div>Robby</div><div><br></div></font></span></div><div><div=
><div class=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On Sun, Sep =
8, 2013 at 4:20 AM, antoine <span dir=3D"ltr"><<a href=3D"mailto:antoine=
597 at gmail.com" target=3D"_blank">antoine597 at gmail.com</a>></span> wrote:=
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex">Hello,<br>
<br>
I have just start using contracts in racket, but i am a bit disapointed by =
the<br>
error message they give to me.<br>
<br>
example contract error:<br>
<br>
=C2=A0add-number: contract violation<br>
=C2=A0expected: number?<br>
=C2=A0given: "1"<br>
=C2=A0in: the 2nd argument of<br>
=C2=A0 =C2=A0 =C2=A0 (-> number? number? number?)<br>
=C2=A0contract from: abc.rkt<br>
=C2=A0blaming: edf.rkt<br>
=C2=A0at: abc.rkt:5.3<br>
<br>
I would have expected to have the line and column number in the blaming lin=
e<br>
like what you could get from a stacktrace.<br>
<br>
Is it possible in contracts?<br>
Am i the only one to complain? :)<br>
<br>
Thanks you in advance.<br>
____________________<br>
=C2=A0Racket Users list:<br>
=C2=A0<a href=3D"http://lists.racket-lang.org/users" target=3D"_blank">http=
://lists.racket-lang.org/<u></u>users</a><br>
</blockquote></div><br></div>
</div></div><br>____________________<br>
=C2=A0 Racket Users list:<br>
=C2=A0 <a href=3D"http://lists.racket-lang.org/users" target=3D"_blank">htt=
p://lists.racket-lang.org/users</a><br>
<br></blockquote></div><br><br clear=3D"all"><div><br></div></div></div><sp=
an class=3D""><font color=3D"#888888">-- <br><div dir=3D"ltr"><div style=3D=
"font-family:arial;font-size:small"><b>Daniel Prager</b></div><div style=3D=
"font-family:arial;font-size:small">
Agile/Lean Coaching, Software Development and Leadership</div>
<div style=3D"font-family:arial;font-size:small"><font color=3D"#999999">Tw=
itter:</font>=C2=A0<a href=3D"https://twitter.com/agilejitsu" style=3D"colo=
r:rgb(17,85,204)" target=3D"_blank">@agilejitsu</a>=C2=A0</div><div style=
=3D"font-family:arial;font-size:small">
<font color=3D"#999999">Blog:</font>=C2=A0<a href=3D"http://agile-jitsu.blo=
gspot.com/" style=3D"color:rgb(17,85,204)" target=3D"_blank">agile-jitsu.bl=
ogspot.com</a></div></div>
</font></span></div></div>
</blockquote></div><br></div></div>
--047d7b2e46f0a2dac304e5e61421--