5 ms·
This is why I enjoy Go, it shepherds you to write clear and uniform code that cannot be mistaken. This is 'boring,' true, but I will die on the hill that engine
by weakfish 5y ago
This is why I enjoy Go, it shepherds you to write clear and uniform code that cannot be mistaken. This is 'boring,' true, but I will die on the hill that engineering should be boring if that's what produces a robust outcome. Elegant functional trickery can be cool in a personal project, but I don't want to spend 2 hours deciphering someone else's elegance when trying to solve a business problem.
- xigoi 5y agoitems.filter(item => item.isSelected) is not “functional trickery”.
- kubb 5y agoFor weakfish it might be - maybe he's never thought about what this does and when he sees it, his eyes gloss over it as unreadable cleverness.
- Dylan16807 5y agoI feel comfortable saying such a person would be wrong.
- macgyverismo 5y agoLet’s play devils advocate; does it return a filtered list, does it change itself or both? As clear as it may look at first, I still would have to look in the docs to find out.
- Zababa 5y agoYou could make the same arguments when you're working with slices in Go. Take append(slice, element). Does it return a slice with the element appended to it, or does it modify the slice in-place?. For some things, you have to look at the docs, that's how it is. Usually languages have conventions around that. In JS, map, filter and reduce always return a fresh array and leave the initial array untouched.
- masklinn 5y ago> You could make the same arguments when you're working with slices in Go. Take append(slice, element). Does it return a slice with the element appended to it, or does it modify the slice in-place? A funny trick question as it pretty much does both. Also I'll take "functional trickery" over needing a page called Slice Tricks so you can find out how to delete an item any day of the week.
- wruza 5y agoYou don't have to, because irl it's: let show_items = items.filter(…) But yeah, things like this you have to know in advance anyway.
- chrismorgan 5y agoIn some languages, especially many ahead-of-time compiled languages, this will be a part of the signature so that it’s at least much more difficult to get wrong¹. In Rust, for example: • `fn filter(self, P²) -> A` consumes self and returns a new thing of type A; • `fn filter(&mut self, P)` mutates in-place; • `fn filter(&self, P) -> B<'_>` doesn’t mutate self, but produces a new thing of type B containing references to the contents of self. As a concrete example, Rust has `Vec::retain(&mut self, P)` to filter a list/array in place, and `Iterator::filter(self, P) -> Filter<Self, P>` to filter an iterator, consuming that iterator object and wrapping it in another. This is a sterling example of the point of the original article: Rust pushes you to thinking about ownership, and it’s really great and I miss it when working in other languages, where I have to stop and think whether I’m allowed to mutate this object or whether I should make a copy, and the cost of getting it wrong is bad performance in one direction and bugs that can be a nightmare to diagnose in the other direction. —⁂— ¹ You need linear types to make it just about impossible to get wrong by accident. Rust has a weaker substitute that you can annotate functions with, #[must_use], which says “warn the user if they neglect to use the return value, because they’re almost certainly doing the wrong thing”. ² I’ve omitted the filter predicate P from the signatures to reduce distraction; in each case it’d probably be something like `<P: FnMut(&Self::Item) -> bool>`: a function that is passed a reference to an item and returns true or false.
- kaba0 5y agoThen what is? A filtering then later mapping with a bit of flatMap and a final reduce? Because if it is not functional trickery, I don’t really know what is (and no, recursion is not the answer) and it is sure clearer than the 3 nested loop or whatever one might come up with.
- tester34 5y agoMonads :P
- gatestone 5y agoElegant is "pleasingly ingenious and simple". But it's often in the eye of the beholder, if a loop or a list comprehension is simpler.
- lmm 5y agoPeople don't properly account for the cost of reading volumes of code. They'd rather see 10,000 lines that will take them a week to read than 10 lines that will take them an hour to read.
- warkdarrior 5y agoIt's more about the context. Yes, this module could have 10,000 lines of boring code or 10 dense lines. But the overall system is 100,000 lines across 3 languages, 8 runtimes, and 2 databases, so the savings from that one module are minor in the big picture.
- oaiey 5y agoWhile that is a correct assessment that it is massively overlooked, most of us lost more time in 10 liners than in 10k projects.
- Zababa 5y agoIt's surprising to me that as a engineer you seem to be taking pride in not knowing things. I personally have a biais for functional programming in general. I think there is a lot to learn by studying the languages and pattern used. And I think the last 5-10 years have proved that I'm right, as more and more languages are adopting features that were used only by functional languages before. Records, ADTs, pattern matching. I think Go would have benefited from studying these languages. But I also appreciate Go as a language. I love the wide standard library, I love how asynchronous IO is handled, I love the tooling and the fast compilation, I love the cross-compilation. And more than that, I recognize them as good solutions to problems. I wish other languages would adopt that. I wish making a web server/API in OCaml was as easy as in Go. I wish Rust had some M:N threading model when doing stuff that's a bit less performance-sensitive. I wish Stack/Cabal/Nix were as easy as go build. When I had to make a small program to cut text files for a friend, I did it in Go, and it was a great experience. We're engineers, let's try to be a bit less tribalist and a bit more pragmatic, and we will all end up with better tools.
- dmux 5y ago>It's surprising to me that as a engineer you seem to be taking pride in not knowing things. I'm not the GP, but I think this is off the mark. There's a big difference in purposefully choosing boring technology and purposefully taking pride in not knowing things.
- Zababa 5y agoI think the message that I initially replied to hints more at the "taking pride in not knowing things", or at least can be interpreted that way easily. A different message, that, according to me, doesn't have this issue would be: "This is why I enjoy Go, it shepherds you to write clear and uniform code that cannot be mistaken. Go makes well-known tradeoffs that have already been discussed to death, and I find that I agree with these tradeoffs. In my experience, collaborating on Go code is easier as the absence of some means of abstractions prevents people from creating their "language inside the language", and thus allow for a team to share more easily their mental model about how the code works." You could even add a caveat in the form of "Go isn't perfect, no language is, and has made what could be considered objective flaws. But on the other hand, the handling of things like generics shows that the maintainers are not closed to idea. They tend to err on the side of taking more time to make things rights, even if that time isn't always needed, and that's a tradeoff I agree with.".