views:

1356

answers:

14

Hey, I know this is an subjective question, but please don't vote to close it before I get the acceptable answer.

I'm a .NET programmer (somewhat experienced), and really want to learn a functional language. My preferred choices are F# and Python, and I'm really doubting about which one to choose. Please clear my doubts. I'm totally new with them both, so please tell me their benefits over each other, or why I should choose F#/Python.

Maybe I'm misleading, but Wikipedia says that:

F# (pronounced F Sharp) is a multi-paradigm programming language, targeting the .NET Framework, that encompasses functional programming as well as imperative object-oriented programming disciplines.

and:

Python supports multiple programming paradigms, primarily but not limited to object oriented, imperative and, to a lesser extent, functional programming styles.

Thanks in advance.

+15  A: 

Here are some facts about the languages (I know more about F# so am likely to have bias) which may inform your decision.

  • F# ships inside Visual Studio and is a .NET language, so if you know that platform/tools, it is an advantage for getting off the ground. Iron Python is a .NET Python implementation that also has some VS support as an add-in.
  • Both languages have REPLs. F# is compiled (even in the REPL it gets compiled on the fly), so has good performance both as a compiled app and in the REPL. (Not sure about Python.)
  • F# is 'more functional' by a variety of criteria, so if you really want "functional", I would choose F# over Python for that reason alone.
  • F# is statically-typed. Python is dynamic.
  • Both languages are often used in science/math domains; I think Python is older and has more (and more mature) numerics libraries.
  • You can use F# and Iron Python together in concert (I've seen a few blogs that show basic demos of this) if you want to do both.
Brian
Interesting list of point. I would like to point out that Python is used way more often in scientific domains than F# (physics, genetics, mechanics, etc.).
EOL
That's almost certainly down to a combination of two factors: availability of Python libraries for scientific programming; and the fact that physicists, geneticists, engineers etc., like everybody else, typically think of programming in imperative "cookery recipe" terms. The popularity of R for statistical analysis shows that the declarative approach can gain significant traction once the benefits become immediately obvious.
Rafe
@Rafe: R is way more similar to Python/Numpy than to pure functional programming, and many of the algorithms implemented are described in the algorithmic "cookery recipe" there (at least the machine learning ones I know of). I agree, however, that R and Python owe more of their current success to their libraries.
Muhammad Alkarouri
#Muhammad: properly written R has a much more declarative flavour (and runs faster). That is, one should prefer coding in R at the applicative matrix/vector level rather than with lots of loops and assignments.
Rafe
@Rafe: The same applies to NumPy. You work at the matrix/vector level and avoid loops as much as possible. In fact, the code is translatable almost line by line. Using Python lists and loops is much less efficient than using Numpy arrays.
Muhammad Alkarouri
+5  A: 

Python is not functional. If you want to use a functional language, you should definitely go with F#.

If you google "python functional programming", you can see there is little stuff there. Python's philosophy does not encourage functional programming either. This is why the new Python 3.0 removes some functional elements of Python 2.x.

Yin Zhu
map() is even being removed from Python 3, because of list comprehensions. That will make it less functional.
Geoffrey Van Wyk
@Geoffrey: Map is being removed!? failtastic!
Paul Nathan
map is not removed from Python 3. see http://docs.python.org/py3k/library/functions.html#map
pillmuncher
`map` and `filter` were not removed. `reduce` is the one affected by being moved to functools rather than being a built in.
Muhammad Alkarouri
+6  A: 

Python isn't really a functional language. Sure, it has functional constructs (first-class functions, etc.) but you're still (generally) programming in a decidedly imperative, procedural style with Python. F# adheres much more closely to the functional paradigm.

mipadi
+31  A: 

I doubt you'll learn much of value from Python. It's a dynamically typed OO language with pleasantly lightweight syntax. Other than giving you even less protection (and speed) than you'd get from C#, you'll be writing the same programs, just in a slightly different dialect.

F# is a different beast altogether. It has a rich, statically checked, polymorphic, algebraic type system. It is mostly functional, which means it strongly encourages you to program declaratively and avoid side effects (such as assignment) wherever possible. This has several benefits:

  • the compiler will catch many more errors than you'll be used to;

  • your programs will be much shorter;

  • your programs will work first time (once the compiler has wrung out all the bugs it can find) about nine times out of ten, in my experience;

  • the compiler can typically generate much, much better code.

I usually reckon it takes an imperative programmer about a month to rotate their thinking into the functional style. The downside is that after you make the adjustment, the programming mainstream just feels rather primitive and awkward.

Go for it, it's eye-opening.

Rafe
There is a lot of value from learning python and dynamically typed languages. Python is used by a lot of the top sites at the moment. its a case of whats the best fit is the main thing
AutomatedTester
There will always be some subjectivity in choosing a language, as well as external concerns -- like marketability of skills, and you won't want to ignore those. However, I completely agree with Rafe about all F#'s good points. Since moving from C# to F# on my current project, I'm coding faster, the code is shorter, and the maintenance is much less. I'm even beginning to find myself thinking about problems in a functional way as a first cut at solving them.
TechNeilogy
+1 for this: `I usually reckon it takes an imperative programmer about a month to rotate their thinking into the functional style. The downside is that after you make the adjustment, the programming mainstream just feels rather primitive and awkward.`
gnucom
AutomatedTester: AutomatedTester: sure, but Jeff was asking about functional programming languages. Python, for me, isn't an FPL because it misses the hallmark of virtually all FPLs (barring the archaic LISP family), namely a rich, statically checked polymorphic type system based around algebraic data types. Moreover, bolting some FPL-like characteristics (first class functions) on to an OO language such as C# or Python, won't teach you how to program in the functional style, not least because the natural style in those languages is to use destructive update.
Rafe
AutomatedTester: I'm also curious about what benefits you think dynamically-typed-by-default languages have. I almost always know what type I expect a variable to hold and I'd rather have the compiler point out my mistakes rather than the runtime. I'm not being critical, just interested in your point of view.
Rafe
@Rafe Hey Rafe, nice to see you here :-) [Mauro from Monash].
Mau
It takes a bit of a bunker mentality to say that Python is in the same league as C#, or those against C. The idea of functional programming against the others is a fallacy.In fact, pure functional is Haskell. The advantage of OCaml/F# is that you have the imperative capabilities as well.
Muhammad Alkarouri
@Rafe: I mentioned the static vs dynamic issue in my answer below if you are interested.
Muhammad Alkarouri
@Muhammed: thanks for the reply. C# and Python really are close neighbours in the language design space, the main difference being C#'s emphasis on stronger, static typing. I have nothing against Python - I think it's elegant, for what it is - but I do think that dynamically typed programs longer than a page are, typically, slow bug piles waiting to bite you. Strong, static typing is your friend because it eliminates whole classes of bugs that otherwise would require laborious (and incomplete) unit testing to detect.
Rafe
To follow on, I'd still like to hear a convincing argument in favour of dynamic typing by default (a la Python). It can't be performance, since the compiler can largely only generate third rate code for dynamically typed objects, and it can't be safety, because no checking happens until the code is executed.There *are* places where dynamic typing is useful, but they are pretty rare in my experience.
Rafe
I won't even try to defend Python here or say something in favour of it (I did elsewhere). My point was that Python and C# fail in entirely different ways. Whether the gap between a static explicitly typed language (C#) and a dynamic one (Python) is much smaller than that between a mainly imperative static explicitly typed language (C#) and a mainly functional static largely implicit typed one (F#) or not is not that obvious to me. Of course, given a program that can be written in F# and Python in the same number of lines, the type guarantees of F# are much more stronger and more useful.
Muhammad Alkarouri
@Rafe: You are in trouble if you wrote a function that takes a page in either static and dynamic language. A code that takes a page in static-type language typically takes 1/3rd of a page in dynamic-language because you don't need to nanny the compiler with all the type signatures and type casting. While dynamic typing is indeed more fragile when the function gets large; dynamic typing keeps your code small and straightforward.
Lie Ryan
@Rafe: on the other hand, while *implicit* static typing like F# does give you the best of both world, it also takes a lot by restricting your code to pure (or near pure) functional codes. While in general pure functional is a great paradigm, in practical purpose, it taxes the mind a little bit more. Some impure functions can save you from the mess that you'd see in Haskell's effort to keep purity.
Lie Ryan
**your programs will work first time (once the compiler has wrung out all the bugs it can find) about nine times out of ten, in my experience;** A pythonista will know that a program written in Python usually works the first time about 9 out of 10 without the compiler/interpreter being chatty. Someone once said: "Python is an *executable pseudocode*"; reflecting that that you generally succeed translating what's in your mind to code in your first try.
Lie Ryan
@Lie Ryan: I've had a lot of experience working in all sorts of programming languages, including Python, and I've worked on compilers for pure languages (including Mercury), and my experience is completely the opposite to what you suggest. In my experience, (1) strong static typing catches about 50% of the bugs in your code, (2) no side-effects catches about 40% of the bugs in your code. These are bugs that *cannot* make it past the compiler that you would otherwise have to do partial spot-checks for with unit testing.
Rafe
@Lie Ryan: Also, from what you say, I really don't think you've had much experience with functional programming. Typically you only explicitly give types for your top-level data structures and functions, leaving the compiler to infer everything else. The types do double duty as documentation as well as being *perfect* unit tests for that aspect of your program. These type annotations are brief. In a *few* cases dynamic typing can lead to a shorter program, but they are very rare. You only have to look at real programs written in Haskell to see how amazingly concise it is.
Rafe
@Rafe: I've written a little bit of Haskell, and knows how concise Haskell can be and still be statically typed through implicit typing. However, I think you're confusing between strong/weak-typing and static/dynamic-typing. Python is a strongly and dynamically typed, the interpreter catches many invalid type conversions. <continued>
Lie Ryan
IME, from the 50% of bugs that strong-static typing catches, about 40% is also caught by strong-dynamic typing. IMO, it is good practice to prefer side-effect free functions even when there is no language guarantee. Python gives flexibility to choose either, while Haskell forces you to choose one.
Lie Ryan
@Lie Ryan: the difference is that with strong, static type checking these bugs are caught before your program ever runs. You don't need to write a single unit test for this class of bugs. I know that Mercury also supports dynamic typing and I would be surprised if Haskell didn't as well, the difference being that these languages require you to be explicit at the points where you use it.
Rafe
@Lie Ryan: regarding brevity and clarity, I think a large part of that comes from having algebraic data types, which, as far as I know, are not supported by Python. ADTs save you so from having to write so much scaffolding and boiler-plate code that it isn't funny.
Rafe
@Rafe: Yes, that's where implicit typing wins. Implicit typing gives you both compile-time checks and conciseness. The only only problem is it also limits you to functional code (ever heard of implicit-typed imperative language?). In Python, you usually avoid type-related bug using duck-typing, 95% type-related bugs simply doesn't cause any erratic behavior if you duck type. The only problem with it is that it makes certain errors more subtle.
Lie Ryan
@Rafe: I agree with Haskell's conciseness. It impresses me the first time I wrote Haskell and it impresses me even more when I realized that it does that while still being strong and statically typed. My biggest hurdle with Haskell was only GHC's error/traceback message, which can often be confounding to interpret. I've been too long using Python which IMHO has an almost perfect clarity (almost perfect, since the only error message that can be in Python is when you have the wrong number of arguments when calling a method in a class, but you quickly learn about that)
Lie Ryan
@Lie Ryan: I'm impressed that you have so much success with dynamic typing. I think I asked elsewhere on this discussion why some people think that dynamic typing has advantages. I have found a few examples in my career where it was useful or necessary, but in almost all other cases it has been a source of bugs. Maybe it's just me! Personally I much prefer *knowing* that my program contains no type bugs (and that I therefore don't have to test for them) rather then simply having faith solely in my unit tests.
Rafe
@Rafe: I agree dynamic language isn't suitable for every program, for example, it's nearly impossible to do formal proof of correctness for a python program is correct; fortunately most of the time, you don't need such formalism, and you just need the program do reasonably sane thing 99.9% of the time. When you understand Python, the type system melts and disappear from your brain and code, you almost never need to bother with types. I find that harder to do in Haskell even when I don't need to write explicit type annotations (or maybe I just have less experience with Haskell).
Lie Ryan
@Rafe consider that for some applications it's okay tobetter to be done in half the time and be 90% sure you don't have a typing bug
John C
@John C -- Well, your mileage may vary, but all experienced functional programmers I know prefer FPLs for the increased speed of coding (you can do more with less) *and* the vastly greater chance of producing a correct result. 90% sure might be fine for a throwaway program, but I doubt that's what you want in anything serious. I'm still genuinely curious to see an example where Python improves on F#.
Rafe
John C
+28  A: 

With respect to Python, I am somewhat shocked at some of the other answers. This is what Andrew Kuchling (Python Functional Programming HOWTO) says:

The designers of some computer languages choose to emphasize one particular approach to programming. This often makes it difficult to write programs that use a different approach. Other languages are multi-paradigm languages that support several different approaches. Lisp, C++, and Python are multi-paradigm; you can write programs or libraries that are largely procedural, object-oriented, or functional in all of these languages. In a large program, different sections might be written using different approaches; the GUI might be object-oriented while the processing logic is procedural or functional, for example.

Dave Mertz presented a more in(1) depth(2) discussion of functional programming, saying,

Summary: Although users usually think of Python as a procedural and object-oriented language, it actually contains everything you need for a completely functional approach to programming. This article discusses general concepts of functional programming, and illustrates ways of implementing functional techniques in Python.

Python fully supports higher order functions (the first example on that wikipedia page is written in Python!). This is a common misconception. Even if map() were not built-in, it is trivially manufactured by

def map(function, l):
    return [function(item) for item in l] # A complete list object is returned

In fact, observing the function written so should immediately inform as to why map() might be considered redundant. The above example can be trivially converted into a form that returns each function evaluation lazily, by changing the list comprehension into a generator:

def map(function, l):
    return (function(item) for item in l) # A generator object is returned

It would be called like so:

def dbl(x):
    return x + x
for answer in map(dbl, [1,2,3,4,5]):
    print answer # Produces 2 4 6 8 10 one per line

The sometimes flammable issue of lambda (please don't debate this with me, this issue has been beaten to death in far more illustrious places than my answer, I am not qualified to debate this point, etc) is another good example:

function = lambda x,y: x + y
print function(2,3) # produces '5'

is completely equivalent to

def f(x,y):
    return x + y
function = f
print function(2,3) # produces '5'

There is no reason to persist with a keyword called lambda, when the syntax of the language itself provides the functionality. Functional programming isn't about what specific functions are called; it is more about how things get done. As far as I am aware, the primary deficiency of Python compared to something like Scheme is the inability to modify the code itself in as easy a way as modifying a list: this code-is-data property is a consequence of using S-expressions, because then all code syntax looks like a list. Python doesn't do that, or not as easily. If this is something you want to get into, then that pretty much decides the case for you and you'll have to focus on a language with S-expressions/prefix notation.

Having said all that, there are some problems with Python as a functional language:

  • The Global Interpreter Lock (GIL) in Python means that dividing up python threads amongst multiple separate CPU cores is not possible. IronPython may or may not get around this (exercise left to reader). The point of having multiple cores available is that functional languages lend themselves to parallelizable execution paradigms, and you just won't see a big benefit of this using stock Python on a multi-core machine. (In practice, many people use the excellent multiprocessing package in the standard library for multi-core concurrency, or even manually launching multiple instances of an app on the command line with shell scripts and so on; but these are practical considerations that have nothing to do with functional programming.)

  • Not being forced to adopt functional programming idioms might hinder your learning. Idiomatic Python is by no means close to the "functional programming paradigm", and you have to go out of your way to stick to a functional "style", simple because more idiomatic ways are easier to do, and more frequently recommended in online documentation and tutorials. The Mertz article should help with that though.

  • Recursion. By default, Python has a recursion limit, and there is the C stack floating around there in the background when using the standard CPython distribution. IronPython may or may no deal with this issue specifically, but I can't say. There is always Stackless. Anyhow, this is something you need to look out for. Python doesn't have tail recursion, for example, so certain kinds of "typical" or "common" functional programming examples (fibo() comes to mind) may present implementation difficulties.

I know Python far, far better than I know F# (as far as "functional" programming goes, I have little-to-moderate experience with PLT Scheme); and my largely uninformed opinion thus far is that F# falls largely in the same camp as Lisp, Scheme and the becoming-rapidly-popular Clojure. These are all fine languages, but you should be aware that working in them means that you are pretty much bound to the "functional programming paradigm" (OOP in Lisp does not look like OOP in any other language I've seen, regardless of what promoters may say). On the other hand, since you said you wanted to learn, with Python you can immediately compare and contrast functional-vs-OOP-vs-procedural all within the same syntax; and even in the same program. That's gotta be worth something.

Comic relief: the Y combinator in Python (ugliest valid Python you'll ever see):

fact = (lambda func:
        (lambda f:
            func(lambda x:
                (f(f))(x)))(lambda f:
                    func(lambda x:
                        (f(f))(x))))(lambda f:
                            lambda n:
                                1 if n < 2 else n*f(n-1))
print fact(10)

>>>
3628800
cjrh
Scheme, Clojure and F# are generally considered functional languages. Common Lisp and Python are generally considered to be non-functional languages with some functional features. It's not a litmus test, but one thing that can generally be used to rule out a language from being functional is how well it supports recursion. Recursion is an essential quality of functional programming. And I know you don't want to debate it, but I just have to note that Python's `lambda` is gimpy.
Chuck
There is no difference between Python's `lambda` and Python's standard function (`def`), except that a `lambda` is restricted to a single line; but for the purposes of implementing closures, the standard python function syntax (`def`) is **completely adequate**. That functionality does not *require* a word called `lambda`. Recursion, *tail-recursion* specifically, remains a problem as you (and I) correctly point out.
cjrh
F# is not solely a functional language, and you are not bound to one paradigm with it. OO in F# looks a lot like OO in C#. The same combination advantage you claim Python provides, of comparing functional vs OO vs whatever else, is also possible with F#. Easy flamewar-retardant solution: learn 'em both? Heheh...
Dan Fitch
Your lazy map example does not implement laziness in the sense usually used in the functional style. Specifically, `it = map(id, [1]); any(True for x in it); any(True for x in it)` displays True, then False; `it` is used up by the second call. This is a bad bug with a longer list and multiple calls to `any`. Also, F#, Common Lisp, Scheme and Clojure are all multi-paradigm languages (in roughly descending order of their multi-paradigm support). There are not many functional languages that are single-paradigm; Haskell and Erlang are the most popular I can think of.
Nathan Sanders
@Dan Fitch: clearly I need to learn more about F#.
cjrh
@Nathan Sanders: you definitely have a point, but you probably didn't highlight the right issue. The problems is not with `map`. The problem is with iterators/generators in Python being more like C++ iterators than F# sequences. In particular, they are destructively consumed. It can be solved for `map`:`from itertools import tee; def map(function, l): return (function(item) for item in tee(l))` but that will still not solve the iterator issue in general.
Muhammad Alkarouri
@Muhammad: I wanted to point out the error in the specific example of laziness via map. You are right about the overall issue.
Nathan Sanders
Most languages allow functional style programming with some syntactic tweaks and compiler optimizations.Though this is a bit debatable, someone once described functional programming as "a subset of imperative programming", and that in fact F# is at its core an imperative language.With that in mind, it probably makes more sense to say "language X is more imperative than language Y" than it does to say "language Y is more functional than language X". In this case, Python is more imperative than F#, but F# isn't necessarily "more functional" than Python.
Rei Miyasaka
@Rei Miyasaka: I think I tend to disagree. Most languages do not support closures (binding local state), for example. Although this is becoming more popular as newer languages come out all the time.
cjrh
@cjrh, Ah, you're right about closures. I do miss them when I'm in OOP languages :)
Rei Miyasaka
+4  A: 

F#, definitely, if you want to stay in the .NET world.

Personally, I'd suggest Common Lisp as well as F#. Haskell is somewhat similar to F#; Lisp is not, not really.

F# is a strongly-typed, type-inferenced language with the default of immutable data (Much like Haskell). F# has the decided advantage of being pushed by Microsoft. F# is very much in the no-side-effect world.

Common Lisp has a somewhat looser type system (But not weakly typed), and its data is not immutable. It also does not guide you towards not having side effects.

Like the other chap, I don't think Python will offer you much in the 'mind-bending' arena (unless you really start digging around the internals), whereas F# will start to expand your mind from declaration one.

Python is not a functional language really. Although it has certain functional aspects (which make it much easier to work in, imho).

Paul Nathan
Could you give an example of something in the 'mind-bending' arena? My brain got quite hammered on *The Little Schemer*, for example, but there is not too much in there that is not reproducible in python. Aside from syntax manipulation (code-is-data), I'm unclear what is missing?
cjrh
@cjrh: Type inference; the data structures, pattern matching, immutable data. Type inference in particular gives my mind fits.
Paul Nathan
@Paul Nathan: ok, I've spent some time trying to digest your answer. Type inference seems to be an implementation detail (something like maybe Shedskin or PyPy are doing?), but I have no idea what the others mean.
cjrh
@cjrh: Type Inference - see the Hadley Milner type algorithm. Pattern matching is how F# handles cases. Immutable data implies the inability to update a variable.
Paul Nathan
A: 

Python ( subjectively and argumentative speaking of course)

OscarRyz
+1  A: 

I think part of a language's strength lies in its standard library. Personally, I don't like Python's set of standard library. Some packages that people consider "standard" are not included in the standard library, and vice versa. I don't know about F#, but it's a .NET language, and the library in .NET is quite well-documented and consistent.

Instead of asking other people for their opinions, why don't you go learn the basics of both languages first, and decide yourself. I know it takes a lot of time to master a language, but learning the basics won't cost you more than one week. Plus, you would then have some experience in both F# and Python. For Python, I suggest you take a look at Dive into Python 3.

Just my two cents.

Hai Minh Nguyen
If you're going to make the claim that Python's standard library is deficient, you're going to have to add *at least a single example* to support that.
cjrh
I can suggest one: Tkinter is Python's de-facto standard GUI package, and I prefer wxPython. But I don't think an example is necessary here, because it's just a matter of personal taste. One could even argue that the deficient is not a problem at all, since there are always alternatives.
Hai Minh Nguyen
+1  A: 

I would like to add some points for Python, in light of the unfavourable opinions given up.

  1. As rightly mentioned, it is useful to know different languages and styles to gain more experience. If you are looking for a functional programming, F# is the one.

  2. However, the concept of variety extend to the libraries involved. F# doesn't give you a lot of variety to the other .Net languages apart from a few immutable data structures. Python is a different language with a different standard library and data structures. I personally regard the selection of default data structures in Python as one of the finest in any language. Lists, dictionaries, heaps, deques, sets, bisection algorithm, etc. All that is available in a very usable and useful way which may serve to introduce you to new techniques that you can then use elsewhere. To demonstrate the effort being put in the language, the sorting algorithm used in Python is an efficient algorithm invented for Python (timsort) and is now also used in Java.

  3. If you want to expand your horizon and get outside of the .Net shell, Python will be more useful.

  4. Python is dynamic and thus gives you less compile time protection than F#. The question is when is this protection more useful. The simple answer is that if you have a clearly defined domain and your design is well specified then you can go for static language like C#. If you are more on the experimenting side then a more forgiving language is needed. F# is way better than C# in this regard due to its type inference, but there are still cases where the flexibility of Python duck typing is more useful.

  5. One case where the languages are different is in their object oriented design. F# would look more like C#. Python has a different and more flexible design with metaclasses among other additions.

  6. Did I say that the Python standard library is marvelous?

  7. All these are points that are currently valid. In the future, F# will likely grow more libraries and given the growth in the .Net space will be even more impressive. Python will become much more quicker due to efforts in different directions including Cython, PyPy and unladen swallow.

My view: if you want to learn F# because it is functional then go for it. If you want to learn it because it is shorter, it typically isn't shorter than Python. If you want to learn it because it is compiled and thus the compiler will catch your errors and make your program work first time, then I am afraid you will be very much misinformed.

Muhammad Alkarouri
+5  A: 

Haskell.

Sorry to throw another wrench into the discussion, but trust me, Haskell will help you learn F# a lot faster.

I learned F# first and then learned Haskell -- and found that it would have been a lot easier if I'd learned Haskell first.

F# is great, but it offers too many shortcuts, so you don't really learn as much. Python is great too, but again, it's a lot more imperative than F# is even, so you won't learn anything at all.

Rei Miyasaka
-1: Irrelevant bad advice not from the trenches. Nice work.
Jon Harrop
Explain how this is irrelevant bad advice, Mr. "from the trenches".
Rei Miyasaka
You seriously want me to explain to you why your blind Haskell advocacy is irrelevant to this question about Python and F#?
Jon Harrop
His question is first and foremost about learning functional programming, not only about learning either F# or Python. The only reason he brings up those two languages is because everything else is an unknown-unknown to him.If a kid came up to you and asked if he should smoke or drink, would you tell him which one is the lesser evil? No, you'd tell him to do neither.When you're learning a language in order to learn the paradigm behind it, it makes a lot more sense to learn a stricter language.By the way, are you going through my profile or something? Sheesh.
Rei Miyasaka
I think Rei's comment is apposite, but, having taught Haskell, I don't really think it's a good place to start. Haskell's lazy evaluation really does make it much harder to reason about basic performance. Just writing, say, a character counting program in Haskell requires the use of "magic" to force early arithmetic evaluation, if you don't want your program to run out of heap on non-trivial inputs.
Rafe
Oh, that's a really good point. Getting used to lazy evaluation is quite an adjustment, as is going back to immediate evaluation.I still think the benefits of learning Haskell outweigh the challenges, but I guess it's not such a clear-cut answer after all.
Rei Miyasaka
Haskell is ten times harder than F#
SHiNKiROU
To use, yeah probably, but I'm not sure that's necessarily a bad thing when you're learning.
Rei Miyasaka
+1  A: 

If you really want to learn a functional programming, you can learn F# or Haskell, Python is not a fully functional programming language, but it's does a good choice if you want to learn something else to refresh your mind.

Hiber
A: 

Learn both.

bobobobo
A: 

All of the other discussions not withstanding: The simple answer is if you want to stay in the MS world stay with F# if you want to learn how to interact with all types of systems and not just MS (MS included) and if you want the additional advantage of joining and using the open source world, go with Python. It is really that simple.

Python is about as close as it comes to a "universal" system available on all operating systems and platforms with huge libraries covering all dimensions of the programming world, and mostly all open source.

dartdog
You can code in both languages on Microsoft and non-Microsoft platforms, though. I think the politics are less important here than how the languages fit into the paradigm. You could argue that they're both multi-paradigm, but Python definitely leans toward OO and F# is definitely a functional language.
John C
Somehow promoting F# as a Linux platform seems a bit far out.. Yes it can be done but the pain may not be worth it. So I'll stand by the statement that F# is pretty MS centric while Python is pretty platform agnostic.
dartdog
A: 

Learning functional programming is about entering a new paradigm (that is, changing the way you expect programs to be written). For that reason, I'd say that the best language is the one that most fully immerses you in the paradigm.

Python doesn't. It has first-class functions and a few things like map and reduce, but it's lacking others, like tail-call optimization, which allow you to use those functions in ways you aren't now used to doing.

So I guess it depends, are you looking for a "gateway language" or to just get started right away with FP? If it's the latter, go for F#.

Although I personally think that you can't do better than Scheme for a first functional language. The first FP book I read was The Little Schemer. Not only did it get me off to a good start, but it got me used to the sort of lessons/revelations that are common with FP. They tend to be less "how do I do task X in language Y" and more "look at this cool concept... you may not have known it was possible before, but once you master it you'll find plenty of places that you want to use it.")

John C