I'm parsing with common lisp library meta-sexp.
When I call a rule like this (entity? (create-parser-context str)), I'm not getting any error if the str is invalid. How to get the errors displayed?
A non-match is not an error unless a rule (entity?) or the code calling it programs a non-match as failure.
See the readme. There is an example rule integer-debug?, in the center of the document, that uses a callback to report the character and position of input that failed to parse an integer.
Since rules return NIL on no-parse, to signal a fatal error: (or (entity? (create-parser-context input)) (error "Input is bad!)) could be used to bail out with an error message from an irrecoverable input error.
Related
There are currently four different error logging levels: "#debug, #info, #warn, and #error" all of which have a different use case and implications of their use. In general, when is it appropriate to use the different logging macros?
From the docs:
#debug "Verbose debugging information. Invisible by default"
#info "An informational message"
#warn "Something was odd. You should pay attention"
#error "A non fatal error occurred"
Read more in the Julia docs here. In particular, it's important to note that #error does NOT throw an error, it merely logs an error and continues execution. If you want to throw an error, use the error function instead.
val SOME i = Int.fromString e
I have a line like this on my code and smlnj shows me this warning
vm.sml:84.7-84.32 Warning: binding not exhaustive
SOME i = ...
Is this bad practice? Should I use a function to handle the option or am I missing something?
If you're just working on a small script you'll run once, it's not necessarily bad practice: If Int.fromString e fails (and returns NONE instead of SOME _), then the value binding will fail and an exception will be raised to the appropriate handler (or the program will exit, if ther is no handler). To disable this warning, you can run the top-level statement (for SML-NJ 110.96): Control.MC.bindNonExhaustiveWarn := false;.
As an alternative approach, you could throw a custom exception:
val i =
case Int.fromString e
of SOME i => i
| NONE => raise Fail ("Expected string value to be parseable as an int; got: " ^ e)
The exception message should be written in a way that's appropriate to the provenance of the e value. (If e comes from command-line input, the program should tell the user that a number was expected there; if e comes from a file, the program should tell the user which file is formatted incorrectly and where the formatting error was found.)
As yet another alternative: If your program is meant to be long-running and builds up a lot of state, it wouldn't be very user-friendly if the program crashed as soon as the user entered an ill-formed string on the command line. (The user would be quite sad in this case, as all the state they built up in the program would have been lost.) In this case, you could repeatedly read from stdin until the user types in input that can be parsed as an int. This is incidentally more-or-less what the SML/NJ REPL does: instead of something like val SOME parsedProgram = SMLofNJ.parse (getUserInput ()), it would want to do something like:
fun getNextParsedProgram () =
case SMLofNJ.parse (getUserInput ())
of NONE => (print "ERROR: failed to parse\n"; getNextParsedProgram ())
| SOME parsedProgram => parsedProgram
In summary,
For a short-lived script or a script you don't intend on running often, turning off the warning is a fine option.
For a program where it's unexpected that e would be an unparseable string, you could raise a custom exception that explains what went wrong and how the user can fix it.
For longer-lived programs where better error handling is desired, you should respect the NONE case by pattern-matching on the result of fromString, which forces you to come up with some sort of error-handling behavior.
What exactly happens in
tryCatch(warning("W"),warning = function(c) cat(c$message))
As far as I understand this the call warning("W") creates a condition object c of type warning and then someone (who?) looks for a handler (where? and recognizes the handler how?) and calls the handler on c.
The task of tryCatch is only to "establish" the handlers. What does this mean? In short the question is: how exactly does the condition object get to its handler?
In my experience, tryCatch is used to catch and either ignore or specifically handle errors and warnings. While you can do warnings with this function, I see it more often used with withCallingHandlers (and invokeRestart("muffleWarning")).
The Advanced R book is a good reference for many topics; for this, I'd recommend two chapters:
Exceptions and debugging, where Hadley highlights one key difference:
withCallingHandlers() is a variant of tryCatch() that establishes local handlers, whereas tryCatch() registers exiting handlers. Local handlers are called in the same context as where the condition is signalled, without interrupting the execution of the function. When a exiting handler from tryCatch() is called, the execution of the function is interrupted and the handler is called. withCallingHandlers() is rarely needed, but is useful to be aware of.
Bold emphasis is mine, to highlight that tryCatch interrupts, withCallingHandlers does not. This means that when a warning is raised, nothing else is executed:
tryCatch({warning("foo");message("bar");}, warning=function(w) conditionMessage(w))
# [1] "foo"
tryCatch({warning("foo");message("bar");})
# Warning in tryCatchList(expr, classes, parentenv, handlers) : foo
# bar
Further details/examples are in the Beyond exception handling chapter.
tryCatch executes the expression in a context where anything "raised" is optionally caught and potentially altered, ignored, logged, etc. A common method I see is to accept any error and return a known entity (now without an error), such as
ret <- tryCatch(
something_that_fails(),
error = function(e) FALSE)
Unlike other operating systems that allow precise filters on what to handle (e.g., python and its try: ... except ValueError: syntax, ref: https://docs.python.org/3/tutorial/errors.html#handling-exceptions), R is a bit coarser in that it catches all errors you can get to figure out what kind of error it is.
If you look at the source of tryCatch and trace around its use of its self-defined functions, you'll see that ultimately it calls an R function .addCondHands that includes the list of handlers, matching on the names of the handlers (typically error and warning, though perhaps others might be used?). (The source for that function can be found here, though I don't find it very helpful in this context).
I don't know exactly how to answer "how exactly ... get to its handler", other than an exception is thrown, it is caught, and the handler is executed with the error object as an argument.
I have an expression that spits out multiple errors:
stop("first")
stop("second")
stop("third")
print("success")
Is there a way to make this expression run all the way to the end (and, if possible, store all of the errors)?
The problem with tryCatch is that it stops execution on the first handled condition (so this will print "There was an error" exactly once).
tryCatch({
stop("first")
stop("second")
stop("third")
print("success")
}, error = function(e) print("There was an error"))
I read that withCallingHandlers will capture conditions and continue execution, so I tried something like this...
withCallingHandlers(
{...},
error = function(e) print("There was an error")
)
...but, although this does print the message, it also fails after the first error, which, as far as I can tell, is because the default restart just runs the current line again.
I think what I need to do is write a custom restart that simply skips the current expression and jumps to the next one, but I'm at a bit of a loss about how to go about that.
(Background: Basically, I'm trying to replicate what happens inside testthat::test_that, which is that even though each failing expectation throws an error, all expectations are run before quitting).
I am starting to use the futile.logger package. There is a nice FATAL error logging that I would like to use in conjuction with stop.
But say I do :
stop(flog.fatal('crash for some reason'))
I get
[FATAL] [2015-07-06 22:46:54] [base.stop] crash for some reason
Error:
[FATAL] [2015-07-06 22:46:54] [base.stop] crash for some reason
How can I just stop (abort the program), after logging what the flog.fatal logged
So [FATAL] [2015-07-06 22:46:54] [base.stop] crash for some reason and that's it
Your question as stated seems trivial? Just do
flog.fatal('crash for some reason'); stop()
?
(I personally find futile.logger more useful for writing text messages to a file, not to the console, but also print the messages to the console with R's conditions message(), warning(), stop() etc.
The value returned by flog.fatal is a character vector (length 1) which stop prints.
res <- flog.fatal('crash for some reason')
print(res)
As alternative you can use ftry function from the futile.logger package.
> futile.logger::ftry(log("a"))
ERROR [2017-08-22 10:50:51] non-numeric argument to mathematical function
Error in log("a") : non-numeric argument to mathematical function