chansey97
2020-7-4 08:36:02

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?


sorawee
2020-7-4 08:37:25

When you create your own exn:fail:..., you should inherit the struct from exn:fail


soegaard2
2020-7-4 08:38:14

FWIW (struct exn:fail:task exn:fail ())


chansey97
2020-7-4 08:39:34

@sorawee @soegaard2 Thank you, it works!


chansey97
2020-7-4 08:55:16

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


sorawee
2020-7-4 09:00:25

Actually, if you wanna show this exception to user (who is not a programmer), then you should inherit exn:fail:user


chansey97
2020-7-4 09:01:01

@sorawee I means user of library. He is a programmer.:sweat_smile:


sorawee
2020-7-4 09:05:32

then exn:fail


sorawee
2020-7-4 09:06:48

In particular, there are two kinds of exn: exn:fail and exn:break


sorawee
2020-7-4 09:06:57

exn:break is what you get when you ctrl+c


chansey97
2020-7-4 09:08:16

What do you mean by ctrl+c? This keyword is copy, I am a windows user.


soegaard2
2020-7-4 09:10:58

Had to Google: ctrl+break on Windows. It sends a break signal to the running process.


chansey97
2020-7-4 09:11:43

I understand, thanks @sorawee and @soegaard2!


soegaard2
2020-7-4 09:12:18

Ctrl+c ought to work in DOS though…


sorawee
2020-7-4 09:13:42

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


sorawee
2020-7-4 09:14:02

If you inherit from exn, then those with-handler will not work.


sorawee
2020-7-4 09:14:46

So inherit from exn:fail is the right way


chansey97
2020-7-4 09:15:45

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


soegaard2
2020-7-4 09:17:27

exn:fail has exn as its super type.


soegaard2
2020-7-4 09:17:41

And exn is defined as: (struct exn (message continuation-marks)


soegaard2
2020-7-4 09:18:17

So your exn:fail:task needs three arguments: message, continuation-marks and error-code


soegaard2
2020-7-4 09:19:05

Something like: (exn:fail:task "an error occurred" (current-continuation-marks) 42)


chansey97
2020-7-4 09:22:00

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.


soegaard2
2020-7-4 09:30:35

?


chansey97
2020-7-4 09:30:46

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


chansey97
2020-7-4 09:30:52

But failed.


chansey97
2020-7-4 09:32:13

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)


soegaard2
2020-7-4 09:32:39

I think (task-always-fail) throws an “wrong number of arguments” exception.


soegaard2
2020-7-4 09:32:55

So it doesn’t match the exn:fail:task


chansey97
2020-7-4 09:34:33

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


sorawee
2020-7-4 09:34:54

You do need continuation marks and message


chansey97
2020-7-4 09:36:51

Yes, it works perfectly now, thanks again!


chansey97
2020-7-4 09:38:35

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


chansey97
2020-7-4 09:39:39

btw, I think match? is very useful, it should be added to base library :grinning:


chansey97
2020-7-4 19:30:43

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-&gt;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.


soegaard2
2020-7-4 19:31:42

The reader turns ’(1 2 3) into (quote (1 2 3))


soegaard2
2020-7-4 19:32:17

It’s the printer that prints (quote (1 2 3)) as ’(1 2 3).


soegaard2
2020-7-4 19:32:34

So it looks like you are parsing it correctly.


chansey97
2020-7-4 19:35:21

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


soegaard2
2020-7-4 19:35:34

Yes.


chansey97
2020-7-4 19:35:53

@soegaard2 Thank you:smiley:


chansey97
2020-7-4 20:50:29

I am trying to understand dot. &gt; (cons 1 2) '(1 . 2) &gt; (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. &gt; '(1 2 . 3 . 4) '(3 1 2 4)



chansey97
2020-7-4 21:09:37

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)