4 ms·
var admins = users.Where(user => user.isAdmin()).Select(user => user.Name) vs var admins []string for _, user := range users { if user.IsAdmin
by NateDad 12y ago
var admins = users.Where(user => user.isAdmin()).Select(user => user.Name)
vs
var admins []string
for _, user := range users {
if user.IsAdmin() {
admins = append(admins, user.Name)
}
}
So, at the end of the day, these two pieces of code do the exact same thing, and have mostly the exact same meaning. I read them almost identically...
Make a list of admins. iterate through the users, if the user is an admin, append its name to the list of admins.
The unrolled version is a lot easier to modify later. What if you decide that each of these admin users should have a star next to their name? For the go code, you just add one line:
var admins []string
for _, user := range users {
if user.IsAdmin() {
admins = append(admins, user.Name)
user.Name = user.Name + "*"
}
}
for the C# code, you either have to write a second LINQ query (and now you're iterating the list twice unnecessarily), or you have to unroll it into a normal loop.
So now you've added complexity to the language that is only really good for saving carriage returns, and it makes your code harder to maintain. Sure, it's pretty and interesting from a programming theory POV... but at the end of the day, I don't get paid to write pretty or interesting code. I do get paid to write maintainable code.
- inglor 12y agoI humbly disagree - in the C# code I can pass an IQueryable and reuse the same code to make an SQL query, or a RavenDB query, or an XML query and it works just the same - there is a unified way to access data in the language. As for your query: ``` var admins = users.Where(u => u.IsAdmin()).Select(u => u.Name); var stars = admins.Select(name => name + "*"); ``` Like you said, you don't get paid per line feed - it's ok to have multiple lines and you can keep the nice syntax. It's ok to not like complicated code - no one likes complicated code - which is why I don't like for loops - I don't _care_ how something is iterated I just want to map every object.
- NateDad 12y agoWell, so, that's actually not doing the right thing. You just changed the names in the list of strings that holds admin names, but not the names on the user objects themselves. Even if the first half were returning the users themselves to the admins list, you're still iterating over the list twice. This is yet another reason why the for loop is good - it makes it more clear what is actually going on. This is your code in for loops: var admins []string for _, u := range users { if u.IsAdmin() { admins = append(admins, u.Name) } } for i := range admins { admins[i] = admins[i] + "*" } The problem with the fancy syntax is that it makes it too easy to write suboptimal code that you'd never write if you were writing plain old for loops, like the above.
- frowaway001 12y ago> you're still iterating over the list twice There is nothing about higher-order operations that would require developers to implement xs.map(...).map(...).map(...) or xs.Select(...).Select(...).Select(...) or whatever as multiple traversals over the data structure. > The problem with the fancy syntax is that it makes it too easy to write suboptimal code that you'd never write if you were writing plain old for loops, like the above. Maybe Google should just invest in hiring better people? I know it's getting increasingly harder to find people who still haven't evolved from the 1960ies mindset, but still ...
- djur 12y agoI'm not familiar specifically with LINQ but in most languages that implement map/reduce/filter operations, the "*" requirement could be clearly expressed using a map. What happens when you need an alphabetical list of admins who have logged in during the last week? The for-loop approach becomes progressively more and more cluttered with implementation cruft, while a declarative approach just adds a filter and a sort. And, to be frank, even the example you present is clearer to me in LINQ than in Go, and I am much more familiar with Go.