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

Very strange to see the core primitives of functional programming being sold as 'Pythonic'.

I suppose we all look at the world from the perspective of our own experience.



Honestly I suspect that this stems from a perception particularly among people from a non-traditional CS background that "functional programming" is intimidating, whereas Python is seen as approachable in a get-shit-done kind of way for programming novices. Python definitely did co-opt a lot of traditionally functional stuff, but did it in a way that obviates needing to know what a monad is, concern oneself with functional purity, etc., so there's a community of people now who don't care about any of that but are still familiar with some of these idioms, and this post is meant to make Rust look more accessible to them in a way that "Rust supports functional programming idioms" would not.


>Honestly I suspect that this stems from a perception particularly among people from a non-traditional CS background that "functional programming" is intimidating, whereas Python is seen as approachable in a get-shit-done kind of way for programming novices.

Just people from a "non-traditional CS background"? Most CS graduates today will say the same thing with regards to e.g. Python vs Scheme or CL.

>Python definitely did co-opt a lot of traditionally functional stuff, but did it in a way that obviates needing to know what a monad is, concern oneself with functional purity, etc.

If you hanged around HN pre 2010, you'd seen that FP was all about Lisp (and things like map, reduce, macros, first class functions, etc), and few gave a rat's arse about "monads" and "purity" -- it was only starting to emerge in general consciousness, not dominant as it is today in FP circles.


>: If you hanged around HN pre 2010, you'd seen that FP was all about Lisp (and things like map, reduce, macros, first class functions, etc), and few gave a rat's arse about "monads" and "purity" -- it was only starting to emerge in general consciousness, not dominant as it is today in FP circles.

My recollection was a bit different. I got interested in Haskell around 2007 or so. And pre-2010, I recall encountering several articles about that on HN, though obviously there were often articles about the Lisp family.


As someone that learned FP when Haskell did not exist and Miranda papers were still fresh, this mentality that only Haskell matters as FP notion really feels odd.


I personally feel like Haskell makes a good reference implementation for functional programming. Whenever someone is explaining how to do some interesting FP thing in, say, JavaScript, I usually just ignore them and go read about how the same thing is done in Haskell, which is usually clearer and less burdened with the complexity of getting a mutable, proceedural, eager language to behave like an immutable, lazy, functional one.


If you think that immutability and laziness are inherently part of functional, then you're part of the new-school-is-the-only-school problem.

I mean, I'm not saying that immutability and laziness aren't interesting. But FP has a long long history, most of it's not lazy, and immutability is nowhere near universal.


Completely agree. Anyone interested in functional programming should learn Haskell for this reason alone. Skip the blog post that falsely claims a "functor is a box" or a "monad is a burrito" and go read the original papers.


This is tangential to your main point, but:

> did it in a way that obviates needing to know what a monad is, concern oneself with functional purity,

Caring about both of these things in the context of functional programming essentially dates from the early 1990s. According to Wikipedia (I have no better source, but it matches what I know of pre-1990s functional languages),

> Eugenio Moggi first described the general use of monads to structure programs in 1991.

Functional programming existed before then. Scheme, an early functional language, is from the 1970s. It has basically all the FP idioms that you have in Python, is not pure, is dynamically typed, and the doc never once references monads.

I'd actually say the definition of FP has shifted towards pure, category-theory oriented languages, but "traditionally functional stuff" definitely doesn't include monads.


>Functional programming existed before then [1991]. Scheme, an early functional language, is from the 1970s.

Lisp is even older, as was touted as the de facto functional language since forever. And earlier MLs didn't have monads either.

And of course, just because Moggi described monads in 1991, it doesn't mean it didn't take over a decade for them to make any kind of significant dent.

(Assuming that they have made much of a dent today, which outside the world of Haskell, their explicit (as opposed to implicit) use is close to 0, anyway).


The problem with "traditionally functional stuff" was that one could only use functional programming for a subset of problems. Monads allow Haskell programmers to use FP to solve problems involving IO, mutation and effects. This is not redefining FP, it is extending it to a wider class of problems.


You are saying that Python is like the Bill Nye of functional programming: not really a scientist, but does make it accessible to the masses.


Saying someone who was a mechanical engineer was "not really a scientist" kinda does him a bit of a disservice.

What made Bill Nye awesome was not only his passions for the subject matter but a solid background that let him communicate complex topics in a simple and engaging way.


Not to mention I don't recall him really calling himself a "scientist" in any formal sense, but my exposure to him has always been tangential. He was the "Bill Bye the Science Guy" in his original show, and afterwards I've always seem him explained as a science advocate.

I mean, what's a scientist anyway? If it's someone in constant pursuit of knowledge, does a constant reading of new material to learn more count?


I'd say a scientist is someone who advances science, not just someone who reads results by others (unless they publish a study based on those results, like a meta-analysis or similar).


Does that mean the scientist that tests hypothesis that never works out, and never bothers to publish, isn't a scientist?

What about the person that actually does advance knowledge, for their self, but doesn't share it? Are you not a scientist if you don't let everyone know what you found? You would conceivably still be performing science.

Maybe the easiest way to define it as someone that intends to discover something new (or at least add new data to existing data, for corroboration or refutation)? I don't consider myself to be a scientist, but if I wanted to explore some topic in depth, and and started reading about it, and maybe performing my own small scale experiments to confirm what I had read, I think I would be "doing science" and I would then be at a minimum am amateur scientist.


> I suppose we all look at the world from the perspective of our own experience.

Yes, but in addition to that, I think you can likely sell an idea to people much easier when it's couched in something they are already familiar with. There's been lots said about the functional programming capabilities of Rust, but if people don't already equate what they do as following some functional paradigm, they might find themselves uninterested in the discussion.

I think Python especially, with its "one way to do it" and (my perception) how people adhere to "the way to do it in Python", there's a good chance some people don't really know when they are using common functional patterns.


> Python especially, with its "one way to do it"

Despite being a core tenet of the language, Python is _really, really_ bad at following that rule. I agree with everything else you're saying, though. Those are still Python idioms even if they originated elsewhere.


I think people take the "one way to do it" tenet a little too seriously. It comes from PEP20 [1], which to me seems to have a more jestful than dogmatic tone:

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

> Although that way may not be obvious at first unless you're Dutch.

If I remember my history correctly, this was poking fun as Perl's "TIMTOWTDI" [2].

It also says one obvious way to do it. It doesn't preclude there being more than one way.

[1] https://www.python.org/dev/peps/pep-0020/

[2] https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to...


In 2004, "There should be only one way to do it" was a more realistic goal. 2004 puts us at Python 2.4 or so, but I think that's just when it got formalized into a PEP, it was around for a while before then. If we step back two years to 2002, we get to Python 2.1. We are now pre-generators, pre-with statement, pre-itertools, pre-decorators, and a lot of other things (useful itertools, etc.). There more often was only one sensible way to do a thing. Python evolved, but PEP20 didn't.


> 2004 puts us at Python 2.4 or so, but I think that's just when it got formalized into a PEP

I didn't notice the date on the PEP, but I think you're right. I remember reading it when I learned Python circa 2002.

Found this (from 1999): https://mail.python.org/pipermail/python-list/1999-June/0019....


The "obvious way" changes over time, as the language improves.


How so? Comprehensions vs loops vs recursive functions vs in some cases map/reduce/filter is the only example I can think of.


There's also strings.

    'foo ' + bar
    'foo {}'.format(bar)
    'foo %s' % bar
    f'foo {bar}'


As well as the string templates almost nobody knows about (https://docs.python.org/3.6/library/string.html#template-str...):

    Template('$foo bar').substitute(foo='foo')


Python has good facilities for a solid chunk of functional programming “in the small”. List comprehensions, map, filter, and reduce are all there with clear, easy to understand syntax. It’s no Haskell, but these are definitely niceties.

That said, I don’t see where the author put forward the idea that functional programming is Pythonic so much as “these are functional things that are great in python, here are some analogs in rust”.


I feel like list comprehensions have always been emphasized as an important part of writing idiomatic Python. And as Python added more constructs in that vein (generator expressions, dict and set comprehensions) the tutorials people used didn't really keep up.

In the same way, map and filter were often covered, but not always with an explanation of the style of programming they supported, or why that style could be useful. I do remember the original Dive Into Python did a good job of this, and of encouraging people to explore a more functional style, but I don't recall many other resources, at least from the (2004-ish) era when I was first learning Python, doing that.

As a result I have to be a bit careful these days; I still use Python's more functional constructs regularly, but I've learned to go easy on them when collaborating with others, since I know a lot of people who learn Python now are using materials that mostly only touch on list comprehensions.


The "real functional" map/reduce/filter functions tend to be discouraged by programmers and linters too. It is becoming (has become?) an established part of the culture -- "Lambda in a `map`? Use a list comprehension instead."

I guess it's a "sheep as a lamb" thing -- "The 'functional way' is either points-free or pointless."

Maybe it's better in Rust because the method-style `x.filter().map().reduce()` lets you read left-to-right, and the "global function" `reduce(map(filter(x)))` has to be read inside-out. If there is a good reason to do Python's global function way, maybe D's UFCS can bring them the best of both worlds.


It is becoming (has become?) an established part of the culture -- "Lambda in a `map`? Use a list comprehension instead."

Which is annoying, because there are times when using map or filter is cleaner; for example, if you're doing pipeline-y stuff, using the function-based approach is much easier to read and reason about than doing a bunch of nested comprehensions.

I also tend to think people don't use itertools enough. But it catches people by surprise enough that several of my messing-with-interviewers canned solutions to common problems make heavy use of itertools (including a FizzBuzz which contains no 'for' or 'if' statements).


Python had the primitives of functional programming since its conception. Those are not exclusive of pure FP languages.

Some particular names used in the examples were introduced by Python. For example the `enumerate` function or `zip`. I haven't seen those names used in programming languages older than Python, I know I might wrong. The point is that it's not crazy to believe that Rust design does borrow some things from Python (among other languages of course).

The article is comparing some particular Python idioms with Rust. The fact that those are functional I think is not particularly relevant. It's like someone seeing a comparison of Java and Go and saying that those are just the principles of imperative programming, or object oriented programming.


> Some particular names used in the examples were introduced by Python. For example the `enumerate` function or `zip`. I haven't seen those names used in programming languages older than Python, I know I might wrong.

All the ML dialects that I know have a zip function and ML pre-dates Python by about 20 years. This is particularly relevant since Rust is clearly strongly influenced by ML.

> The fact that those are functional I think is not particularly relevant. It's like someone seeing a comparison of Java and Go and saying that those are just the principles of imperative programming, or object oriented programming.

The comparison feels right, but I think it would certainly be odd if somebody explained loops in Go as "a Java idiom".


Python FP primitives came from an early friend or codev of Guido. He had experience in FP or Lisp and felt he needed them. Guido never really wanted that and just left them there.

All these names and ideas are clearly rooted in FP circles


I suppose it makes sense in weird way, since both Python and Rust have these features implemented in similar ways because it stems from more traditional functional programming. You could also compare Java to C++ on account of them both being inspired by C.


It's possible for these constructs to be present in many languages and predate Python's adoption of them, and for it to be simultaneously true that a lot of idiomatic Python relies on these constructs.


Except the article contained non-functional concepts in it also. But hey at least you got to announce the fact you use/like functional programming languages.


I think it's nice that more and more languages take inspiration from the Python community.

For example, I've recently found a way to use Python-like type hints in C++. Crazy, huh? The trick is to replace "auto" with the concrete type name, e.g.:

auto x = 5;

becomes:

int x = 5;


This is a joke right?


Joke? No, you can actually do this in C++!


Of course you can do this in c++. The second form of your declaration is the standard way of doing things. How did you learn c++, that this was a surprise to you?

Secondly, that’s not a ‘type hint’ and c++ did not get this from python. Prior to c++17, there was no auto and all declarations were like this. If anything, Python got the names from c++




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

Search: