`ark` discussion notes
I had the pleasure of getting to chat a bit with @lionel- at posit::conf and just wanted to track a few notes that came out of the discussion.
tips for debugadapter
- Recommendation to use
later. From what I can tell, this will allow for easy management of a background thread that can affect the global environment. Quick POC:
looks like a totally viable solution to me. I don't really care about non-interruptable code as we just need to periodically listen for new state from the adapter at the top level. In fact, it might even offer a better alternative to running the debugger in a separate process.i <- 0 f <- function() { i <<- i + 1; later::later(f, 1) } f() # wait n seconds.. Sys.sleep will not work because bg thread can't use interrupts i # [1] <n> - Lionel mentioned a few edge cases where either the source isn't known (not yet sourced.. if there were other cases I forgot them)
- Lionel mentioned foreseen challenges with getting the source from lines sent to the console from a selection, suggesting that it might require a wrapping function for sending code with a "faked" srcref.
learnings from debugadapter for ark
- Mentioned that managing
trace()insertions ofbrowser()statements was painful.tracewill affect the function's body, meaning that multiple insertions need to account for the difference between source and traced version of the code (ie, a breakpoint at line 10 in the file open in a user's editor might actually want to insert a newbrowser()at line 11 because abrowser()statement has already been inserted at some point above). This is otherwise an attractive option, since the browser statement can be inserted at an arbitrary location (easily found withutils::findLineNum()) debug()simplifies this, as it will not insert code. However it introduces a new challenge - thatdebug()always enters the debug prompt upon entering a debugged function. Currently, I automatically step through the function until a breakpoint is hit. This still emits all the debug prompt output, so you get a bunch of messages as R steps through the lines of the function. Definitely still room for improvement.
for both.. potential bug?
- Mentioned bug with
debug(), in which theconditionargument seems to have no effect. Might be a base R bug, or at least a devel R bug.options(browser.hook = function(hook, condition, envir) { print(condition) }) f <- function() { print("123"); browser(condition = list(origin = "browser")) } debug(f, condition = list(origin = "globalenv")) f() # ... #> debug at #1: browser(condition = list(origin = "browser")) #> NULL # debug() condition output #> $origin # browser() condition output #> [1] "browser"
Another issue with debug() is that it's not really possible to use it for inserting breakpoints in anonymous / inaccessible functions, e.g. within lapply().
Ah, that's a good point. You're imagining a situation like:
1| lapply(
2| list(1, 2, 3),
3| function(i) {
o 4| print(i)
5| }
6| )
Yeah... that's going to be tedious to handle. I'd really like to avoid requiring extra code to be inserted into a snippet sent to the console, but this seems unavoidable in this case.
Have you explored how other languages handle breakpoints in non-function code? I wouldn't really expect this to even work if you're just using a simple "send to console" command. That said, I think it would definitely be a nice improvement.
hmm, in emacs-lisp at least you can break anywhere in a top-level expression.