4 ms·
What do you mean by refactoring? Automated tools to do that? Why would manual refactoring be better than let's say in more dynamic languages?
by mateuszf 11y ago
What do you mean by refactoring? Automated tools to do that?
Why would manual refactoring be better than let's say in more dynamic languages?
- pjmlp 11y ago> Why would manual refactoring be better than let's say in more dynamic languages? The compiler won't let you generate an executable if you missed a code location. Whereas in dynamic languages you never know if you have covered all the code locations.
- mateuszf 11y agoOk, but it's the same feature as in other static typing languages, like C/C++/Java?
- tome 11y agoYes, but pjmlp is massively understating the case. Haskell's type system and fine-grained level of compositionality is remarkably helpful when it comes to refactoring.
- pjmlp 11y agoYeap, I was just presenting the broader picture, specially since in the enterprise space, unit tests have even lower priority than documentation.
- dllthomas 11y agoAlthough you can get some serious mileage out of C's type system (such as it is). Refactoring in Python is... broken. I can't imagine why anyone would use Python when they need their code to stay nimble.
- rprospero 11y agoPerhaps a bit of a different viewpoint, but one of the reasons that I keep coming back to Haskell is that it lets me refactor things things that I can't in other languages. Take the following C code: char* response(messy* message) { body* b = message->body; if(b==NULL) { return NULL;} char** lines = b->text; if(t==NULL) { return NULL; } if(b->line_count < 11) { return NULL; } return t[10]; } Writing all of those if statements grows tedious. A lazier programmer could just drop them, but then the program would crash whenever the program received malformed data. With Hackell, though, I can refactor out the if statements and get the following equivalent code: response :: Messy -> Maybe String response message = do b <- body message lines <- text body lines `atMay` 10 I want to be clear on a couple of points. First, the Haskell code performs all of the same "null" and bounds checks that the C code made, so this is an apples-to-apples comparison. Furthermore, this isn't using exceptions, like a similar piece of C++ code might try. There's no stack unwinding and nothing can escape to contaminate the rest of your program. Finally, this isn't just a weird special case built into the language. With a minimal amount of effort, I could have each failure return a unique error Code. errorCode :: Maybe a -> b -> Either b a errorCode (Just value) _ = Right value errorCode Nothing code = Left code response :: Messy -> Either Int String response message = do b <- body message `errorCode` 1 lines <- text body `errorCode` 2 (lines `atMay` 10) `errorCode` 3 I don't know a way of doing that in any of the C style languages. In those languages, you're forced to add in another if statement every time your code touches message->body to ensure that you're not going to segfault. With Haskell, I can refactor away those if statements and I don't have that code being duplicated all throughout my project. EDIT: improved readability of errorCode
- mightybyte 11y agoJust a small side note, you don't even need to write your errorCode function. That and a number of other useful functions are provided in the errors package (http://hackage.haskell.org/package/errors http://hackage.haskell.org/package/errors). Also, I like to use string error messages because they're easier to grep for. Here's what your response function would look like with those changes. response :: Messy -> Either String String response message = do b <- note "error in body" $ body message lines <- note "error in text" $ text b note "error in atMay" $ lines `atMay` 10