Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

How about Python? You can write IO in a relatively functional fashion in Python:

  print sum(float(line) for line in open('somefile.txt'))


Heh, that's actually slightly shorter than this Haskell version:

  print =<< sum . map read . lines <$> readFile "somefile.txt"
Someone can probably golf this shorter, though. =)


This defaults Num, Read, and Show to Integer—I try to avoid defaulting because it’s kind of a language wart. And speaking of golf: same length but one fewer import by killing the fmap.

    print . sum . map read . lines =<< readFile "somefile.txt"


Much clearer. I slightly prefer the following though:

    ((print . sum . map read . lines) <=< readFile) "somefile.txt"


Pointfree makes more sense for a definition, I think:

    sumFileLines = print . sum . map read . lines <=< readFile
Less so inline because of the excessive parentheses or ($).


There should be one-- and preferably only one --obvious way to do it.


Right, I actually agree and think your version is best!


Nice. I like this version!


Sure. print sum(map(float, open('somefile.txt')))


That's a bit of cheating, as it removes 'lines' or 'line' from code, decreasing readability. So to be fair you want to add it back: print sum(map(float, open('somefile.txt'))) # over lines or print sum(map(lambda line: float(line), open('somefile.txt')))

Either one is all right, but personally I prefer list comprehension notation.

As per Guido: ... and that a more concise notation for anonymous functions would make map() more attractive. Personally, I disagree—I find the list comprehension notation much easier to read than the functional notation, especially as the complexity of the expression to be mapped increases. ...


In Python it's well known that the default iterator on a file gives you the lines. Arguably a function would've been a clearer design, but this is idiomatic in the language we have.

As far as map vs. list comprehension, yes, I prefer the comprehension in the cases where map would need lambda. Here that's not the case. Per "as the complexity of the expression to be mapped increases", this expression 'float' is the simplest possible.


Agreed. Python is my language of choice... ;) Though I'm really starting to look for a statically-typed, compiled language...


Python was my favourite language, but after a year of scala I can't go back. Syntax is almost as lightweight as python, sometimes even lighter (_.something rather than lambda x: x.something is a godsend); tuples and case classes mean it's easy to define a new type for things where you'd use a dictionary or object() in python, and the type system is expressive enough that it doesn't get in the way, not to mention the joys of e.g. the typeclass pattern (which allows a level of dynamicity that would be simply impossible to do sanely in python). There's a mature deployment story (because at that stage it's just .jars) and the huge java library ecosystem is available up to a point.


This may be interesting for you: https://github.com/kachayev/fn.py

- this library allows to use Scala-style underscore arguments in Python code (and much more).


I'm curious, what for? Performance, type safety or compile errors?

If type safety, then in my opinion it is overrated. A side effect of using dynamically-typed language is that developers keep their naming conventions consistent and in check. Because that's the only sane way to avoid stupid typos in a language that doesn't have a compiler. It is not so in the compiled language world. What I often see in the code, where type safety is enforced, - is that developers get sloppy with names! And as a result, there is a significant increase in bugs caused by logic errors. sad


    Performance, type safety or compile errors?
Yes, yes and yes.

    A side effect of using dynamically-typed language is that developers
    keep their naming conventions consistent and in check.
I've not found this to be the case. I just discussed method naming in Javascript with a developer today while I was reviewing his code. He's a very good developer and this is an A+ codebase (no, it's not a pile of jQuery plugins...). But he hadn't really thought about how to name some methods and didn't realize the confusion that would be caused in 6-18 months. We left it as he had written it because it would have been a pain to hunt down the dependencies.

Were we working in a compiled world, we would have refactored and the compiler would have caught any missed dependencies in a second.

    What I often see in the code, where type safety is enforced, - 
    is that developers get sloppy with names!
I've definitely not seen that. I maintain the same rigor w.r.t. hygiene whether I'm working in statically or dynamically typed languages, but I really miss the compiler when I'm working in dynamic languages.

At the risk of sounding really rude, can I ask whether your anecdotes are informed by work with competent developers?


   We left it as he had written it because it would have been a pain to hunt down the dependencies. Were we working in a compiled world, we would have refactored and the compiler would have caught any missed dependencies in a second.
Ideally, unit tests should take compiler role and be able to catch typos and missing dependencies. There is really no excuse for not maintaining unit tests in the dynamic world. Unless it is a research grade code with limited lifetime.

As to your question, I have no idea really. I've stopped judging goodness of other developers and myself some years back.


But why basically write a compiler yourself when you can get the one that comes with the language for free?


Pardon me for not being clear enough (and for derailing the thread?).

What I was trying to say, is that you can catch missing dependencies and misspellings for free, while running lightweight unit tests. (unit tests are there for catching logic errors and allowing debugging of individual modules; catching misspellings is just a side effect).

On a side note, if somebody is complaining that "a typo in the python code caused client call at 2AM, this could have never happened in Haskell", what they are really saying is that they haven't bothered to run any test coverage whatsoever before deploying new code.


>What I was trying to say, is that you can catch missing dependencies and misspellings for free, while running lightweight unit tests. (unit tests are there for catching logic errors and allowing debugging of individual modules; catching misspellings is just a side effect).

Sure, but a lot of code doesn't need that. Say you're writing a conversion between two datatypes; in something like Haskell you can be confident that if it compiles then it's correct. There's no logic for there to be errors in, so having to write a unit test would be an additional overhead in a more weakly typed language.

>On a side note, if somebody is complaining that "a typo in the python code caused client call at 2AM, this could have never happened in Haskell", what they are really saying is that they haven't bothered to run any test coverage whatsoever before deploying new code.

Bollocks. You can have 100% line coverage and still hit a type error. And a language where you have to have 100% coverage is a lot less pleasant to work in than one where you don't.


There are some things you can enforce with a type system that you cannot practically implement with unit tests.

For example in [1] it is described how a type system can be used to help you keep track which kind of string contains what data (SQL, XML, user input...) to catch problems with injection attacks at compile time.

[1] http://blog.moertel.com/posts/2006-10-18-a-type-based-soluti...


A type system like this can create a lot of drag, when, say, you need to interface to an external library and suddenly discover that this library, annoyingly, only works with strings, not your data types. In this case you might have been better off, just by keeping name conventions straight.

Still. Yes. Your point is certainly valid.


I'll take a sloppily named Haskell codebase over a well-named Python codebase, especially when reliability is compared.

Type-safety of the Java kind might be overrated. Type-safety of the Haskell kind, though is hard to over-rate. It catches the vast majority of bugs, including ones people would refer to as "logic bugs".




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: