check-exn
won’t tell you the error location when the exn-predicate
return #f
? See this example: (struct exn:fail:task ())
(struct exn:fail:task-2 ())
(define (task-always-fail)
(raise (exn:fail:task)))
(check-exn exn:fail:task-2? (λ () (task-always-fail)))
As you see, the (task-always-fail)
raise a wrong exception. Yes, this test failed, but it does not tell you where is wrong, no location information…(e.g. line number) It just says test-suite-2 > my-test-suite > Unnamed test
ERROR
A value other than an exception was raised: #<exn:fail:task>
Is this is a rackunit
’s bug?
When you create your own exn:fail:...
, you should inherit the struct from exn:fail
FWIW (struct exn:fail:task exn:fail ())
@sorawee @soegaard2 Thank you, it works!
Sorry, I am a newbie for Racket. About exception, I have a question: I am writing a library. If some interface of this library needs to throw an exception to user (represent possibility to failure, like Maybe), which exn
should I inherit?
For example, (struct exn:fail:task exn:fail ())
vs (struct exn:fail:task exn ())
Actually, if you wanna show this exception to user (who is not a programmer), then you should inherit exn:fail:user
@sorawee I means user of library. He is a programmer.:sweat_smile:
then exn:fail
In particular, there are two kinds of exn
: exn:fail
and exn:break
exn:break
is what you get when you ctrl+c
What do you mean by ctrl+c
? This keyword
is copy, I am a windows user.
Had to Google: ctrl+break on Windows. It sends a break signal to the running process.
I understand, thanks @sorawee and @soegaard2!
Ctrl+c ought to work in DOS though…
So yeah, when you use with-handler
(try
..catch
in other languages), you usually don’t want to intercept exn:break
. So people will usually catch exn:fail
If you inherit from exn
, then those with-handler
will not work.
So inherit from exn:fail
is the right way
Now I inherit from exn:fail
, but I want to wrap a value in it: (struct exn:fail:task exn:fail (error-code))
(exn:fail:task 100) ; <---- why this failed?
; exn:fail:task: arity mismatch;
; the expected number of arguments does not match the given number
; expected: 3
; given: 1
exn:fail
has exn
as its super type.
And exn
is defined as: (struct exn (message continuation-marks)
So your exn:fail:task
needs three arguments: message, continuation-marks and error-code
Something like: (exn:fail:task "an error occurred" (current-continuation-marks) 42)
Thanks @soegaard2 I just found if in the raise
, there is no need to fill these additional arguments.
—Edited:— This is wrong. It does not be filled these additional arguments automatically. You must be fill it manually. See comments below.
?
Can I pattern match a exception? (define (task-always-fail)
(raise (exn:fail:task 100)))
(check-exn (match? (exn:fail:task _ _ 100)) (λ () (task-always-fail)))
But failed.
PS: I found the match?
from https://github.com/racket/racket/issues/1690 It’s good, so I copy paste it. (btw, I dont know why match?
are not in the base library)
I think (task-always-fail)
throws an “wrong number of arguments” exception.
So it doesn’t match the exn:fail:task
I did some experiments: (check-exn (lambda (e)
(printf "the e is ~v\n" e)
#t)
(λ () (task-always-fail)))
The printf
’s result is > (exn:fail:contract:arity “exn:fail:task: arity mismatch;\n the expected number of arguments does not match the given number\n expected: 3\n given: 1\n arguments…:\n 100” #<continuation-mark-set>)
You do need continuation marks and message
Yes, it works perfectly now, thanks again!
(define (task-always-fail)
(raise (exn:fail:task "an error occurred" (current-continuation-marks) 100)))
(check-exn (match? (exn:fail:task _ _ 100)) (λ () (task-always-fail))) ; passed
(check-exn (match? (exn:fail:task _ _ 99)) (λ () (task-always-fail))) ; failure (and error location appeared)
btw, I think match?
is very useful, it should be added to base library :grinning:
Is there way to make a list in quote?
Backgound: I am writing a parser for s-expr by Racket. (ps: not practical programming, just for fun:grin:) Everything is OK, except that I don’t how to process quote. For example, suppose I want to parse '(1 2 3)
(parse try-s-expr (string->list "'(1 2 3)"))
I have been able to parse this '(1 2 3)
to (s-quote (1 2 3))
, where s-quote
is my AST node. My question is how to make this inner list (1 2 3)
to '(1 2 3
? I have read https://docs.racket-lang.org/guide/quote.html, but the quote
is a special form, so it is not suitable here.
I’m sorry, I just said “s-quote is my AST node” was actually a lie, because I want to use lisp homoiconicity, i.e. using Racket’s underlying structure as my AST node (actually, there is no custom AST node at all). But I hope you can understand what I mean…:worried: Thanks.
The reader turns ’(1 2 3) into (quote (1 2 3))
It’s the printer that prints (quote (1 2 3)) as ’(1 2 3).
So it looks like you are parsing it correctly.
@soegaard2 > The reader turns ’(1 2 3) into (quote (1 2 3)) In other words, I just need to create a list which has a symbol called quote
at head? Then OK?
Yes.
@soegaard2 Thank you:smiley:
I am trying to understand dot. > (cons 1 2)
'(1 . 2)
> (cons 0 (cons 1 2))
'(0 1 . 2)
It seems that dot just is a infix operator for cons
.
But what happen when dot appears multiple times in parentheses? E.g. > '(1 2 . 3 . 4)
'(3 1 2 4)
Thanks @sorawee. But I have to go to sleep:sleeping:. I will come back tomorrow (take a closer look at the documentation, because I just want to parse standard lisp syntax rather than extended syntax)