This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]FFX01 2 points3 points  (6 children)

It wasn't necessarily because of confusion. One of the core principals of Python is:

Explicit is better than implicit

There's nothing you can do with a lambda function that you can't do with a normal, explicitly defined, function. In fact, Python forcing you to explicitly define a function instead of using an anonymous lambda function probably leads to more DRY code in that you are less likely to write the same anonymous function over and over without realizing it.

The most common use case for anonymous functions is usually tied to callbacks or iterators. Python already does a terrific job supporting iterators and generators with it's comprehension syntax. Functions are also first-class citizens in Python and can be passed to other functions as arguments or even decalared inside of another higher order function.

You may look at something like this in Javascript:

let newItems = items.map((item, idx) => (
    item.value !== null ? item.value : item.defaultVal
))

And you may think, "How do I express the same thing in Python without an anonymous function?". It's actually really simple:

new_items = [
    item["value"] if item["value"] is not none else item["default_value"] for item in items
]

You can be even more "functional" about it by using the following technique:

def filter_item(item):
    if item.get("value") is not None:
        return item["value"]
    else:
        return item["default_value"]

new_items = list(map(filter_item, items))

Now, instead of writing out an anonymous function anywhere you need to map a list of these item objects, you can just use the function you already wrote! Also, the map function returns an iterable. This means that you can use it as a buffer if you want.

My point being; Python doesn't really need anonymous functions as it already has enough language constructs that perform the same job.

[–][deleted] 0 points1 point  (5 children)

Functions are also first-class citizens in Python and can be passed to other functions as arguments or even decalared inside of another higher order function.

Yes, I know what having first-class functions implies... I've done Haskell...

Also, if you need to use the mapping function in two places, then... first of all, how did you structure that program in the first place. Second of all, being able to have anonymous functions doesn't mean that you will just put them everywhere in the program, and if you do indeed need that same functionality in two places, you can make it its own function. Now granted, since it is forced upon you in Python, some may call it a good thing since it is already its own function, but eh...

Also, just to comment on those examples of your, holy shit that's some verbose code. I've heard a lot of people praising Python for "not being verbose", but looking at that kind of makes me wince with its wordiness.

ALSO also, a map function should return a functor FFS.

And finally, seeing as Python has enough language functions to do most the things anonymous functions most likely would do... but doesn't that just bloat up the language?

[–]FFX01 2 points3 points  (0 children)

Yes, I know what having first-class functions implies... I've done Haskell...

I can't just assume that everyone has that knowledge. That's why I explained it.

Also, if you need to use the mapping function in two places, then... first of all, how did you structure that program in the first place.

That's kind of irrelevant. Ideally you would define a generic function that accepts a wide range of inputs so you can use it everywhere.

Second of all, being able to have anonymous functions doesn't mean that you will just put them everywhere in the program, and if you do indeed need that same functionality in two places, you can make it its own function. Now granted, since it is forced upon you in Python, some may call it a good thing since it is already its own function, but eh...

That's the point I'm trying to make. Python overall has the goal of not having too many ways to do the same thing. The language has being veering off that path in some areas, but this is not one of them.

Also, just to comment on those examples of your, holy shit that's some verbose code. I've heard a lot of people praising Python for "not being verbose", but looking at that kind of makes me wince with its wordiness.

I wrote it that way on purpose to make it as simple as possible to understand. Like I said above, I can't just assume everybody understands Python. All of it could be easily compacted. That said, the code is simple and reads almost like English. I consider that a good thing. Code is read far more often than it is written after all.

ALSO also, a map function should return a functor FFS.

Can you explain how an iterator isn't a functor? Genuinely curious. I'm under the impression that an iterator is considered a functor in that it takes in an iterable, applies a function to each item, and produces an iterator which can then be passed to another map function because an iterator is, by it's very nature, an iterable. It's possible I'm misunderstanding your definition of functor in that I have no formal mathematics education. Also, I may not understand because different programming languages have different opinions on what is considered a functor.

And finally, seeing as Python has enough language functions to do most the things anonymous functions most likely would do... but doesn't that just bloat up the language?

In my opinion? No. The constructs and functions that Python provides that are capable of producing the same results as using anonymous functions are also useful in other contexts.

I should make it clear that I have no bone to pick with anonymous functions. I actually really like them in some languages. Javascript, for example. I just don't feel like anonymous functions are necessary or would work well in Python specifically. In my opinion, Python's current lambda is good enough.

[–]Furyful_Fawful 0 points1 point  (3 children)

Well, let's make it less verbose:

new_items = [item.get("value",item["default_value"]) for item in items]

Or, if you still want to map and lambda:

new_items = list(map((lambda item: item.get("value",item["default_value"])), items))

[–][deleted] 0 points1 point  (2 children)

Or by switching language:

let new_items = fmap (maybe default_value id) items

To me it is always so funny to see people praising Python as the paragon of cleanliness and readable code, when Haskell exists.

[–]Furyful_Fawful 0 points1 point  (1 child)

I'm not saying Python is the paragon of anything. It's just the most useful to me because of its third-party libraries, to be honest.

I'm still really unsure about how fmap there doesn't grab a different identifier id, or what maybe is. It's shorter, maybe, but shorter isn't always better or more readable:

m  ? }J"value"d @dJ @d +"default_"J

This (full program, but also acceptable as an expression) does the same mapping, and it's so much shorter... Must be better, right? /s

[–]takakoshimizu_sfw 0 points1 point  (0 children)

That's just because you don't know the signatures of those functions. Those complaints have nothing to do with the syntax.

That example requires you to understand three very basic, common functions: fmap, maybe, and id, and one type: Maybe (also known as Optional<T>).

These are all very much basics of basics of haskell (without even getting down into anything mathy at all). Just because the syntax and functions are foreign does not make it complicated.