10 ms·
> by getting the whole parser onto a single screen, I find that I can get the whole problem into my brain’s working memory and avoid burning cycles scrolling up
by codesections 6y ago
> by getting the whole parser onto a single screen, I find that I can get the whole problem into my brain’s working memory and avoid burning cycles scrolling up and down to pin down butterflies bugs.
This is an excellent point, and one that not enough programmers pay attention to (well, outside of the APL family of languages, anyway!)
- hoytech 6y agoForth programmers often talk about keeping down the number of screens a lot too, for example page 23 of Thinking Forth: "A component can usually be written in one or two screens of Forth." (Aside from the attraction in small and simple code, each screen in forth is traditionally allocated a designated spot on the hard-drive so it's partially also for space and HDD usage efficiency too)
- neutronicus 6y agoAs a C++ programmer, I've grown so sick of } } // not } // a single } // fucking else // implicit else // return nullptr return result; } A deeply-indented scope should mean "shit is complicated, think deeply about it," not "there were five times I tried something and elected to punt and return null if it failed." The LLVM style guide has the right idea; if you're gonna punt, early-return. As a side-note, I really wish the C++ community would take a page out of Lisp's book and stop giving closing braces their own lines. But that'll never happen.
- augustk 6y agoIf a function returns early, its post-conditions cannot be checked.
- lizmat 6y agoThis is not true in Raku: whichever way you leave a subroutine, the returned value will be checked against the return constraint. And throw if that fails. More generally, you can specify KEEP and UNDO phasers in a block, that will fire whether the block is left successfully or not. So a typical usage would be `UNDO $dbh.rollback`.
- fnord77 6y agocould you give an example of this? (all I can think of is something where you could handle it with a finally-type clause) maybe a fn shouldn't have post conditions?
- quietbritishjim 6y agoDo you mean checked by a human reader? If so, a linear sequence of if statements that return early is far easier to check than than deeply nested statements where the error handling for failures is effectively back-to-front at the end. Or are you saying that there are some lines of code at the end checking the post conditions? I'm not exactly sure what that would look like, it sounds a bit insane, especially if you do it for every function. Could you give an example?
- augustk 6y agoI mean programmatically with an assertion statement or similar. You don't want to add the same assertion before each return statement.
- darwingr 6y agoI’d love an example if you have one. I’ve used assertions lots as guards or pre-condition checks on entering the function but never right before returning.
- augustk 6y agoA complicated sorting algorithm could assert that the result is sorted before returning.
- raiph 6y agoHopefully you saw Liz's comment. Raku has a zero cost way to add arbitrary post processing that kicks in no matter where or how a block of code exits. This provides a general mechanism accessible by arbitrary user defined control flow related constructs. Raku also ships with a dozen or so built in constructs such as PRE and POST blocks that are the foundational elements for DbC, plus UNDO and KEEP blocks for transactional semantics, and so on.
- panpanna 6y ago> giving closing braces their own lines Oh for the love of God, please don't! That would make things even more unreadable. Also, the closing braces are often accompanied by error handling and cleaning up code. You might like the golang approach better, which is really the Linux kernel approach when I think about it....
- snazz 6y agoI think that C-like languages wouldn’t be able to handle putting closing braces on the same line because of the lack of Paredit-style editor support. In Lisp, it works well.
- codesections 6y agoWhat doesn't work well for C-like languages? I've been writing a lot of Rust lately with Smartparens (a paredit like package in Emacs) and haven't had any issues with its support for Rust.
- snazz 6y agoWe're talking about putting the closing brace on the same line of an expression, like this: int double(int x){ return x * 2;} instead of like this: int double(int x) { return x * 2; } In Lisp, you would write that like this: (defun double (x) (* 2 x)) and not this: (defun double (x) (* 2 x) ) You can read either with syntax highlighting and the appropriate indentation, but it's much harder to get away with putting the closing brace on the same line in C-like languages because of how few people use something like Smartparens or Paredit and how having multiple kinds of brackets (parens, square brackets, curly braces, and angle brackets) introduces ambiguity.
- codesections 6y agoYeah, I understood what we were talking about – sorry for not being more clear in my reply earlier. When you said that putting the closing bracket on the same line wouldn't work because of the "lack of Paredit-style editor support" for C-like languages, I thought you meant that the Paredit-style plugins wouldn't work well with/support C-like languages. That struck me as odd, because I use Smartparens when writing Rust, and it works just as well as it does when I write a lisp/scheme. In particular, it handles parens, square brackets, curly braces, and angle brackets just fine (and it even distinguishes between a single quote that's used to start a character literal (which should be paired) and a single quote that indicates a lifetime label (which should not))[0]. I could easily use it to write Rust with closing braces on the same line; the only reason I don't is because it's not the common style in that community. Based on your last comment, I now understand that you're not saying Paredit-style plugins don't _work_ with C-like languages. You're saying that most programmers who write in those languages don't use those plugins. Is that right? If so, I agree that they aren't widely used and that it'd be hard for anyone to use the formatting style above without adopting a plugin. [0]: The only thing Smartparens fails to handle is that it does not recognize that a pipe character is a pair when delimiting the arguments for a closure. I'm sure I could fix either Smartparens or rust-mode to fix that issue but so far I haven't been annoyed enough to bother. [Edited to add a missing close-paren, fittingly enough.]
- 0x445442 6y agoI call it telescope or pennant code, it's definitely a smell.
- aldanor 6y agoIn Python, it's even worse, since there's no braces and not returning anything implicitly returns None.
- rmtech 6y agoPython at least has if ... elif ... else to deal with it.
- empthought 6y agoMypy fixes the second problem, at least.
- deckiedan 6y agoI always take this as Python's way of strongly discouraging deeply nested and overly long functions... ( I realise this might be Stockholm syndrome...)
- proverbialbunny 6y agoIn many situations you can fix this by adding a not to the if statement. eg, Before: if (a.works()) { // some code if (b.works()) { // more code } } After: if (!a.works()) { // error handling code, if necessary return; } // some code if (!b.works()) { // error handling code, if necessary return; } // more code
- quietbritishjim 6y agoThis is called "early return" and the parent already mentioned it: > if you're gonna punt, early-return
- afiori 6y agohere there is some significant restructuring of the flow control, early returns could have just meant return statements in the middle of the function.
- quietbritishjim 6y agoI'm really quite sure they were referring to the type of code in your comment. Early return on error (as in, what you posted) vs single return with deeply nested if statements is an absolutely classic coding debate.
- afiori 6y agojust as a quick clarification, I am not the OP
- quietbritishjim 6y agoOops, I did indeed miss that. I suppose that shows that it was helpful to spell it out.
- giancarlostoro 6y ago
- esaym 6y ago>if you're gonna punt, early-return. I don't know what it is but I once interviewed for an embedded C position. During the interview, I wrote out some code samples. The only issue the interviewer found was that I had "returned early". He said there could basically only be one return in a function and it had to be at the end. I told him I'd never heard of that. He only said it was a "standard" that had to be followed because of the crypo involved in the code base. Sadly, even though I didn't get the job, that stupid statement of only one return call in a function has stuck with me and lead to many mental arguments.
- riquito 6y agoStriving for a single return (without going out of your way to achieve it) is good practice. There are two main advantages: - it's obvious when the function ends, no hidden early exits in the middle of nowhere - if you need to do something before returning, there is only one place to do it (e.g. trim the output, e.g. log performances), and it make it easier to move this kind of last mile logic to a different function (if it's of any interest) About your interview, don't sweat it, is not for that you didn't pass (you could do a great job and yet lose to a more fit candidate)
- kqr 6y agoThe "standard" this might have been a reference to is MISRA C. It can be a useful rule to avoid leaking resources/finalising shit.
- melvinroest 6y ago> by getting the whole parser onto a single screen, I find that I can get the whole problem into my brain’s working memory and avoid burning cycles scrolling up and down to pin down butterflies bugs. I haven't seen many developers do this: get a computer screen that can stand in the portrait position. My setup currently is: laptop monitor + 27" screen in portrait. I never have the trouble of scrolling back up and down again when it comes to reading code.
- xapata 6y agoI use two large external monitors, one in portrait. It's changed my coding style.