9 ms·
Call me crazy, but I don't like any of this. Make more named functions. Keep your logic flat and explicit. I believe go wants you to code this way as well. Imag
by integrii 2y ago
Call me crazy, but I don't like any of this. Make more named functions. Keep your logic flat and explicit. I believe go wants you to code this way as well. Imagine the horrors this kind of function chaining creates. Actually, you don't have to. It's JavaScript.
- lifthrasiir 2y agoEven JS doesn't really use functional styles that much. In fact, the whole reason for functional styles is the decomposability: any language with easy function chaining like `x |> f |> g |> h` will also have an easy extraction of any part of the chain (say, `x |> fg |> h where fg = f . g`). It is not a good idea to use chaining when the language supports no such feature, as it would be much harder to work with such chains then.
- arethuza 2y ago.Net seems to handle it pretty well with LINQ? https://medium.com/@sanjanasw99/an-in-depth-guide-to-linq-in-net-understanding-implementing-and-utilizing-22eddc92b13a https://medium.com/@sanjanasw99/an-in-depth-guide-to-linq-in...
- lifthrasiir 2y agoLINQ is a very dense syntactic sugar for some selected `IEnumerable` methods. It will surely look like chaining in typical uses and thus is useful, but different from an arbitrary chaining.
- bilinguliar 2y agoWhen Go eventually lets all this horrible syntax sugar into the standard library, we will meet again in the Zig community.
- tapirl 2y agoIt is a sad fact that Go is becoming more and more like JavaScript (and deviating from C).
- ptman 2y agoThere's always C if you prefer your language to work like C. Go is supposed to be an improvement over C for most programming tasks.
- tapirl 2y ago> Go is supposed to be an improvement over C for most programming tasks. This is not true. s/Go/Zig is true. That is why I'm switching to Zig now.
- cedws 2y agoYou're right, this functional style 'clever' programming is exactly what Go discourages (or did discourage... historically...) This is the exactly the kind of code I don't want to see. I want to see clear, easy to read, obvious functions that do exactly what they say on the tin.
- coin 2y agoFor lots of people, unnecessary for loops makes the code less readable. When using filter and map, all the looping is abstracted out so the reader can concentrate on what's being filtered and transferred. The loops and their temporary variables just clutters up the code.
- snypox 2y agoFor me, the JS/LINQ style is much more readable than a bunch of for loops.
- vineyardmike 2y agoSince you asked, I’ll call you crazy. This sort of “chaining” syntax is pretty standard in many languages (Java, JS, Elixir, etc). Especially for streams/iterators/lists. You can have pretty well named and flat logic too. I think it’s just poorly written demo code. To me, this “functional” style of chaining is great. It highlights intent when reading the chain (you read “filter” as a step instead of a for loop with a conditional inside). It’s also really easy to recompose or reorder, and the code-review diffs are super easy to reason about when that happens. I don’t think it really generates anything conventionally called “horrors” either - you can still use named functions and everything you love, this just makes it easier to use. It may encourage more well-written code too. Imagine a simple example - get all files in some directory, filter out non-json files, perform some name-manipulation (map) function, and then return a new list. The “old” way would require a series of for loops that make and fill slices passed to each. You then wrap that whole thing in a new method called “GetRenamedJsonFiles(path string) []File”. With the iterator chaining, you can still wrap it in a named method, but now you can replace the repeated for loops and intermediary slices with: “return GetFiles(path).Filter(isJsonFunc).Map(updateFileNameFunc).Collect()”. It’s probably easier to read, easier to change up later if requirements change, and easier to validate intent when reviewing, etc. It even encourages smaller, dedicated, easy to update or share methods - it encourages named methods for the intermediary steps (getFiles, isJson, updateName).
- lifthrasiir 2y agoYou can still refactor the original function: func GetRenamedJsonFiles(path string) []File { files := GetFiles(path) jsonFiles := KeepJson(files) // or `Filter(files, IsJson)` renamedFiles := RenameFiles(jsonFiles) // or `Map(jsonFiles, RenameFile)` return renamedFiles } In fact, a long chain of function calls is often hard to read and has to be splitted into several parts anyway. I can even claim that this "old" style forces you to name the outcome of each step. Also it is unclear whether `GetFiles` returns a lazy iterator or a plain slice from its name (I guess it's lazy, but only because you have said `Collect()` there). It is not even like that "map" and "filter" don't have their places in this style. In fact function chaining is just a concise way to rephrase that! You can write in a functional style without having any function chaining, because the style is all about immutability and resulting composability. Mutability tends to not mix together---any such combination results in something more complex. As long as that can be eliminated, anything would work.