Let debugger.log support any number of arguments
Would be very nice to have. My recommendation would be to have it log all arguments and only return the last.
For example:
const result = Math.PI * debugger.log('radius square', r ** 2)
I think valid arguments can be made for both the first and last values being the return value, so I'm hesitant to allow this. Additionally, I would expect implementations to print the source code passed to debugger.log (If you read the spec you can see the implementation is given access to the |Expression| which is passed).
For example in rust:
fn main() {
let r = 6.28f64;
let result = std::f64::consts::PI * dbg!(r.powf(2.0f64));
}
// stdout:
// [src/main.rs:3] r.powf(2.0f64) = 39.4384
What's the argument for returning the first parameter? I think the most common use case would be to use earlier parameters to label what the later parameters are - normally that's not done in reverse order.
I'm also a little hesitant of having it try to smartly "auto-label" the output with the source code - I might be logging out a larger expression, or I might be logging out multiple similar expressions, or I just don't want the clutter of the source code mixed with the output.
...though I can also see this being a convenient thing to have in some scenarios. Maybe if I were to actually use it, I would learn to like it.
What's the argument for returning the first parameter?
For this code
return arr.map(debugger.log).map(x => x + 1)
That seems like a weak argument; everyone already will have had to figure out that they need to convert it into a one-arg arrow function, or, use a function that ignores the 2nd and 3rd arg - this seems no different than parseInt to me.
Put another way, if that's an argument, then we basically couldn't ever have any built-in functions with more than one arg.
I'm not inclined to allow debugger.log in that form anyway, these aren't functions.
If it cannot be used as functions, they're less useful because I cannot write this arr.map(debugger.log)
arr.map(debugger.log)
arr.map(x => debugger.log(x))
arr.map(x => (console.log(x), x))
Everyone debugs differently - I personally wouldn't find arr.map(debugger.log) all that useful, as I normally just want to print out the whole array at once, not each individual item - especially when working in a browser environment that provides tools to collapse/expand the array, but also in node, as I find their default array formatting to work just fine.
debugger.log(arr)
However, I realize that everyone has different styles of debugging that they find comfortable to them, and it's good to try and recognize everyone's preferences.
@Jack-Works I continue to not understand your dislike of arrow functions, and I'm happy to lean on them for this and other proposals.
@Jack-Works I continue to not understand your dislike of arrow functions, and I'm happy to lean on them for this and other proposals.
I just think add more wraps is annoying when I want to quick peak on the intermediate value when I write a long composed expression.
Ah, so if I understand you right @Jack-Works, you want it for this purpose?
const doTransfomration = data => data
.filter(x => x != null)
.map(x => x ** 2)
.map(debugger.log)
.filter(x => x > 100)
e.g. you're wanting to stick a debugger.log in the middle of an array's fluent API, to see what an intermediate value is? I can certainly sympathize with that. The current alternative would be something like this:
const doTransfomration = data => debugger.log(data
.filter(x => x != null)
.map(x => x ** 2)
)
.filter(x => x > 100)
// or ...
const doTransfomration = data => data
.filter(x => x != null)
.map(x => x ** 2)
.map(x => debugger.log(x))
.filter(x => x > 100)
(The .map(debugger.log) solution only helps with the array's fluent API - ideally, we would find a solution that works for any fluent API)
Another alternative, as discussed a bit in this thread on the tc39 forums, is this clever trick that uses the pipe operator, and which works in any fluent API - I'm using hack-pipes in this example. (That particular thread talks a good amount of debugging large expressions).
const doTransfomration = data => data
.filter(x => x != null)
.map(x => x ** 2)
|> debugger.log(?)
.filter(x => x > 100)
The debugger.log(?) and the .filter(...) get combined into one line: debugger.log(?).filter(...), which actually works just fine. And since this is for debugging, clever hacks like this aren't that bad to do.
In your example you can just do this:
const doTransfomration = data => data
.filter(x => x != null)
.map(x => debugger.log(x ** 2))
.filter(x => x > 100)