Raising a customized error/exception - exception

I'm playing around with Pharo, and would like to raise a customized error/exception/something, but I've got no idea how.
I've browsed the relevant (I think) chapters of "Pharo by Example" and "Deep into Pharo"; but couldn't make heads or tails about it - it seems way above the level that I need...
I've got a setter for a variable, and would like to raise an error/exception if the input isn't an Integer:
MyClass >> someVariable: anInteger
anInteger isInteger
ifFalse: [ self SomehowProtestLoadly - the part I don't know how to do ].
someVariable := anInteger
Just aborting or exiting would be sufficient... but if possible, I'd like to do it with a bit more "flare" - and in a more explainatory way...

The easiest way is to just signal a generic error:
someVariable: anInteger
anInteger isInteger
ifFalse: [self error: 'must be an Integer'].
someVariable := anInteger
Now, if you want to signal a specific error, do the following:
Create a subclass of Error, say, NonIntegerArgument
Write your code like this
someVariable: anInteger
anInteger isInteger
ifFalse: [NonIntegerArgument signal: 'must be an Integer'].
someVariable := anInteger
For handling this exception do the following
[myObject someVariable: self value]
on: NonIntegerArgument
do: [:ex | self handleException: ex]
Note that your exception could provide more information, say the actual argument that was sent. To do this add an instance variable to your NonIntegerArgument class, namely, argument. Add a getter and a setter for it. Then
NonIntegerArgument class >> #signal: aString argument: anObject
^self new
argument: anObject;
signal: aString
and use it this way
someVariable: anInteger
anInteger isInteger
ifFalse: [
NonIntegerArgument
signal: 'must be an Integer'
argument: anInteger].
someVariable := anInteger
Now, the ex variable will be able to respond with the argument of the offending message.

Related

Why doesn't Perl 6's try handle a non-zero exit in shell()?

This try catches the exception:
try die X::AdHoc;
say "Got to the end";
The output shows that the program continues:
Got to the end
If I attempt it with shell and a command that doesn't exit with 0, the try doesn't catch it:
try shell('/usr/bin/false');
say "Got to the end";
The output doesn't look like an exception:
The spawned command '/usr/bin/false' exited unsuccessfully (exit code: 1)
in block <unit> at ... line ...
What's going on that this makes it through the try?
The answer is really provided by Jonathan Worthington:
https://irclog.perlgeek.de/perl6-dev/2017-04-04#i_14372945
In short, shell() returns a Proc object. The moment that object is sunk, it will throw the exception that it has internally if running the program failed.
$ 6 'dd shell("/usr/bin/false")'
Proc.new(in => IO::Pipe, out => IO::Pipe, err => IO::Pipe, exitcode => 1, signal => 0, command => ["/usr/bin/false"])
So, what you need to do is catch the Proc object in a variable, to prevent it from being sunk:
$ 6 'my $result = shell("/usr/bin/false"); say "Got to the end"'
Got to the end
And then you can use $result.exitcode to see whether it was successful or not.

pprint in browser repl causes TypeError

Does anybody understand the following behavior inside a ClojureScript browser repl? (provided by the boot tool chain)
my.core> (require 'cljs.pprint)
nil
my.core> (cljs.pprint/pprint "one")
#object[TypeError TypeError: cljs.pprint is undefined]
No stacktrace available.
my.core> (cljs.pprint/pprint "one" "two" "three")
WARNING: Wrong number of args (3) passed to cljs.pprint/pprint at line 1 <cljs repl>
#object[TypeError TypeError: cljs.pprint is undefined]
No stacktrace available.
It looks, that there is no reference to cljs.pprint/pprint, however the repl knows about the arity of this function.
this might help as well:
my.core> (cljs.repl/dir cljs.pprint)
t_cljs$pprint28171
t_cljs$pprint28177
with-pprint-dispatch
with-pretty-writer
write
write-out
nil
cider-repl-toggle-pretty-printing did the trick.

Exception handling with Dire

I'm trying to handle exceptions with Dire library. Like this:
(defn test-fn []
(client/head "https://google.com/404")
)
(with-handler! #'test-fn
java.lang.Exception
(fn [e] "error!"))
But always got an error:
ExceptionInfo clj-http: status 404 clj-http.client/wrap-exceptions/fn--3052 (client.clj:196)
I've tried to change java.lang.Exception to clojure.lang.ExceptionInfo with same effect. Did I miss something?
clj-http uses Slingshot apparently, cf. clj-http documentation on exceptions. The throw+ operation of Slingshot can throw any kind of object, not just exceptions (Throwables). The clj-http documentation has an example:
; Response map is thrown as exception obj.
; We filter out by status codes
(try+
(client/get "http://some-site.com/broken")
(catch [:status 403] {:keys [request-time headers body]}
(log/warn "403" request-time headers))
(catch [:status 404] {:keys [request-time headers body]}
(log/warn "NOT Found 404" request-time headers body))
(catch Object _
(log/error (:throwable &throw-context) "unexpected error")
(throw+)))
Furthermore, the Dire documentation has an example of how to integrate with Slingshot: basically you should be able to drop [:status 404] instead of the java.lang.Exception.

F# Lazy and Exceptions

Given this example:
let value = try (lazy raise(Exception())).Value with | _ -> false
Why is the exception not captured in the try block. Keep in mind that I raise the exception like this to prove the example. The point is that if I have a lazy code that throws and exception, it seems to be unable to capture in the try block. Do I have to be specific in my match of the exception or do I have to capture the exception inside the lazy expression itself?
The following prints both the exception and the value which is false.
let value =
try
(lazy raise(System.Exception())).Value
with
| exn -> printfn "%A" exn
false
printfn "%A" value
I'm not able to rep your results. What are you seeing?
let value =
try
(lazy raise(Exception())).Value
true
with
| ex ->
printfn "got exception";
false
Gives me
got exception
val value : bool = false
Edit:
Adding debugging image

How do I get an unhandled exception to be reported in SML/NJ?

I have the following SML program in a file named testexc.sml:
structure TestExc : sig
val main : (string * string list -> int)
end =
struct
exception OhNoes;
fun main(prog_name, args) = (
raise OhNoes
)
end
I build it with smlnj-110.74 like this:
ml-build sources.cm TestExc.main testimg
Where sources.cm contains:
Group is
csx.sml
I invoke the program like so (on Mac OS 10.8):
sml #SMLload testimg.x86-darwin
I expect to see something when I invoke the program, but the only thing I get is a return code of 1:
$ sml #SMLload testimg.x86-darwin
$ echo $?
1
What gives? Why would SML fail silently on this unhandled exception? Is this behavior normal? Is there some generic handler I can put on main that will print the error that occurred? I realize I can match exception OhNoes, but what about larger programs with exceptions I might not know about?
The answer is to handle the exception, call it e, and print the data using a couple functions available in the system:
$ sml
Standard ML of New Jersey v110.74 [built: Tue Jan 31 16:23:10 2012]
- exnName;
val it = fn : exn -> string
- exnMessage;
val it = fn : exn -> string
-
Now, we have our modified program, were we have the generic handler tacked on to main():
structure TestExc : sig
val main : (string * string list -> int)
end =
struct
exception OhNoes;
open List;
fun exnToString(e) =
List.foldr (op ^) "" ["[",
exnName e,
" ",
exnMessage e,
"]"]
fun main(prog_name, args) = (
raise OhNoes
)
handle e => (
print("Grasshopper disassemble: " ^ exnToString(e));
42)
end
I used lists for generating the message, so to make this program build, you'll need a reference to the basis library in sources.cm:
Group is
$/basis.cm
sources.cm
And here's what it looks like when we run it:
$ sml #SMLload testimg.x86-darwin
Grasshopper disassemble: [OhNoes OhNoes (more info unavailable: ExnInfoHook not initialized)]
$ echo $?
42
I don't know what ExnInfoHook is, but I see OhNoes, at least. It's too bad the SML compiler didn't add a basic handler for us, so as to print something when there was an unhandled exception in the compiled program. I suspect ml-build would be responsible for that task.