5 ms·
Yeah I tried it a few times and there was usually pushback during code review. I agree though, saving a few characters is not worth the readability you lose vs
by pawelduda 3y ago
Yeah I tried it a few times and there was usually pushback during code review. I agree though, saving a few characters is not worth the readability you lose vs even something like `users.map { |u| (...) }`
- kubectl_h 3y agoWe outlawed it immediately via Rubocop but I use it all the time in IRB. We also don't allow single letter variable names. I'm an old school rubyist and find this to be an annoying constraint that can't be auto-corrected so it adds a little friction to writing code but arguing for more terse code is always a losing proposition so I just deal with it.
- pawelduda 3y agoYes, in repl it's convenient. I don't mind single letter block var names if the block spans one line :)
- toxik 3y ago`ii` it is then
- billyruffian 3y agosigh, I once encountered a PFY junior who named all variables some variation on `nx`, so `n1`, `n2`, `n99` because they 'were all just numbers'.
- toxik 3y agoUsing `i`, `j`, and `k` as index variables is not bad practice.
- billyruffian 3y agoWell, my attempt at a humorous aside didn't land. To be strictly serious we are talking about block parameters in ruby which contain the values yielded to it which, in an enumeration, is likely to be a value object from a collection and only occasionally an index (where you've explicitly chained `#with_index` for e.g.). If you are nesting deep enough in ruby to call for `k` then, yes, it would be bad practice.
- jimmaswell 3y agoI would quit if I had to write multi-character index variables.
- jonahx 3y agoAesthetically, yes, I agree (subjectively) that "_1" is uglier than "|u|". However, saying that the latter is "more readable" lacks foundation imo... both are conventions, both are simple to understand, and you can adapt to either quickly. I'd argue this is a case of "familiarity"/"readability" confusion. A more practical argument is that "|u|" is more widely known by inexperienced ruby devs, and hence has an advantage on larger teams, especially those with turnover. With that said, I agree with author's position.
- grumple 3y agoIn practice, you wouldn't use |u| either. You'd use |user|. I would only allow single character variables if they are scoped entirely within one line of code. But even then, best practice is to use good variable names, so I'd still prefer `users.map{ |user| do_something(user) }` or whatever. I use the to_proc pattern for existing methods on the object like `users.map(&:email)`. The only case where I've used a shorthand pattern like _1 is with regex matching where the matched groups are not named, so $1, $2, $3 refer to the first, second, third matched groups, etc. Having worked a lot with csvs (mentioned in an example), referencing the header (or creating one) has always been really valuable, using numbers is asking for trouble when the spec inevitably changes or when a dev wants to know if a script will work with some new file.
- jonahx 3y agoImo using "good variable names" in cases where that variable is effectively functioning as nothing more than a syntactically necessary placeholder for a point-free phrase is a clear (if well-intentioned) mistake. It makes the code noisy and verbose for no benefit. To take the exact example you gave, `users.map{ |u| do_something(u) }` is unambiguously better than `users.map{ |user| do_something(user) }`. What we really want is `users.map{ do_something }`. It is only happenstance that ruby allows this form for methods only via `users.map(&:some_method)`, and we are stuck with forced variable names when calling other functions. Still, we can reduce the boilerplate as much as possible, and this is the basic argument of the article. Also fine: `users.map{ |x| do_something(x) }` (the "x" as a conventional placeholder for the meaningless but syntactically necessary placeholder) and `users.map{ do_something(_1) }` (the _1 accomplishing the same thing). In either case, the "meaningful variable" is already there in the name "users" -- repeating it is mere stutter and detracts from, rather than enhancing, clarity. The exception (as you noted) would be a longer multiline block where repeating `user` can aid short term memory, especially if the block contains other local variables.
- dragonwriter 3y ago_1 takes two characters per use, single-character explicitly named variables take one character per use plus 3 per variable (4 for the first), counting spaces, so you save two characters (three for the first) if the variable is used once, minus one per additional use of a variable. With only one variable, and sometimes with very simple expressions with more than one, you probably get a readability benefit by avoiding stuttering: { _1 + _2 } reads a little better than: { |x, y| x + y } But with any even slightly complex expression in the block, that goes from a benefit to a cost.