Why Learning Haskell/Python Makes You a Worse Programmer
lukeplant.me.uk
lukeplant.me.uk
string.Join("\n", mylist.ConvertAll<string>( delegate(Foo foo) { return foo.Description(); }).FindAll( delegate(string x) { return x != ""; }).ToArray());
can be rewritten as:
string.Join("\n", (from f in myList where f.Description() != "" select f.Description()).ToArray());
which is super-easy to read and understand. Maybe not as concise or pretty as Python or Haskell, but definitely a step in the right direction.
Others' comments that the author should consider F# are well founded, as it integrates seamlessly with other .NET-based code (such as C#) and is a pretty great language. However, it's worth noting that the post was written in 2006, well before F# was widely known about or distributed.
join "\n", grep { $_ } map { $_->description } @myList;
Or join "\n", grep /./, map { $_->description } @myList;
Ruby: myList.collect { |f| f.description }.select { |d| d != "" }.join("\n")
Python: descriptions = (f.description() for f in mylist)
Or if we'd like to constrain ourselves to one method `FooClass.description()` descriptions = map(FooClass.description, mylist) # `map` returns an iterator in py3k
"\n".join(filter(None, descriptions)) # `None` means `lambda x: x` here
Or if you don't like `filter()` "\n".join(d for d in descriptions if d)
Or if `description()` is a side-effect-free method then It should be a property: "\n".join(f.description for f in mylist if f.description)
At the end of the day new features doesn't matter due to most .NET-shops use old C# versions and It will not change any time soon. while (*to++ = *from++);
to be a readable C code (not that I'll recommend it)).It is wrong to judge a language by tiniest code examples.
myList collect(description) select(!="") join("\n")
http://www.iolanguage.com/scm/git/checkout/Io/docs/IoGuide.h... myList.collect { |f| f.description }.select { |d| d != "" }.join("\n")
becomes myList.map(&:description).reject(&:empty?).join("\n")
which is even more direct: take my list, map each element to its description, reject anything empty, and join with newlines. # `None` means `lambda x: x` here
I find it more helpful to think of it as meaning `bool` in that context. I think the None special case is only there because filter() predates bool() in Python. "\n".join(filter(bool, descriptions))
Or `len` "\n".join(filter(len, descriptions)) String.Join("\n", Array.of_seq (seq {for foo in mylist do if foo.Description <> "" then yield foo.Description}))
(String.Join should have an overload for string IEnumerables / seqs and not just accept string arrays.)Then don't use those idioms. Work with your language, not against it. Learning Haskell taught the author to be more conscientious with state. Good. But nobody wants to debug imperative/OO code written by somebody newly infatuated with Haskell* -- it's like when people study a foreign language in high school and start dropping little fragments of Spanish/French/Japanese/etc. into casual conversation all the time, oblivious to whether the people around them understand it.
One of the comments (by "tom") nails it:
One of the more potent reasons for learning other modus operandi in programming to keep you from building tolerance to the same assumptions.
Learning several unrelated languages will almost certainly make you a better programmer, but code that assumes everybody else you're working with has the same background as you will be difficult to maintain. The language you're working in is the foundation for your shared culture, so do your best to write idiomatically in that.
* I have been guilty of this.
I think this is a natural phase of learning - when you first grasp a new concept, you use it everywhere; later, you use it where appropriate. Maybe the first phase is exploratory practice, to grasp its limitations. I'm sure there is a pithy expression for these two phases.
Anyone know it?
The first phase is like "To the man with a hammer, everything looks like a nail". It's also similar to Fred Brooks' "Second System Effect" http://en.wikipedia.org/wiki/The_Mythical_Man-Month#The_Seco... , where you try to learn from all the mistakes you made in the First System.
Children learning language will apparently learn and use plurals correctly - until they discover the abstraction that you can add "s" to make a plural. They then apply it everywhere, including the irregular plurals: mans, foots, tooths, mouses etc. (that last one may be legit these days, mouse having acquired a technical referent). Or even like that developmental stage of babies, where they try chewing everything they find.
I think this explains the whole article and why there is no serious discussion here.
listOfTestObjects.ForEach(x => sOutputDescriptions += "\n" + x.Description());
http://weblogs.asp.net/scottgu/archive/2007/04/08/new-orcas-...
http://www.postmodernprogramming.org/stories/fixed_point_mad...
Then his conclusion: "I have no doubt that in general I am a better programmer for learning these languages..."
Um, hello?
While learning languages X and Y will make you a better programmer in the long term, due to the added perspective they give you, keep in mind that this experience doesn't necessarily apply immediately and directly to every language you work in - don't try to force alien idioms from your new language of fascination into your day-to-day work language, because it's probably a much greater stretch than you realize. It will instead make your code incredibly awkward for everybody else to maintain, actually making you a worse programmer. (This is my understanding, but speaking as someone who has been guilty of doing this in the past, it's really something to be mindful about.)
I constantly find myself wanting to use idioms from these languages, or noticing how much less code I'd be able to write if I was using one of these languages.
That said, I am sad that the BGGA closures proposal won't make the cut for Java 7. I hope that some IDEs and APIs support it anyway.
The thing I like about Fortress is that it's a grown and growable language, with almost all constructs first class and exposed. Just like Lisp. But it's coming from the complete opposite direction in terms of syntax. Lisp barely has any syntax. Fortress gives you the most powerful production parser in a programming language, plus extremely adaptable syntax (where spaces can be operators!) plus a wicked way to render code, plus the ability to make your programs platform portable, adaptable, and parallelizable. It can be looked at as a programming language, true. But it can also be fruitfully imagined as a powerful framework for building one's own programming language. This is what I like to do with it. :-)
There are social factors in language choice, it isn't just about the quality of the language itself.
result = join(new ArrayList<String>(){{ addAll(list); while(remove("")); }},"\n");
And as a bonus - for the extra few characters you typed, this will fail at compile time instead of runtime when the list turns out to contain FooBars instead of strings.
That's the moral of the story? That's not a moral, that's whining.
4-ply parameterized types (e.g. string array list option) do not attractive siblings in Java-land.