

Underscore.py / a python port of underscore.js - serkanyersen
http://serkanyersen.github.com/underscore.py/

======
serkanyersen
Hi Everyone,

First of all, thank you all for your comments. I have to clarify the purpose
of this library. I'm originally a JavaScript developer and I didn't write a
single line of python code before this project.

I needed a project to learn python and I choose something I'm already familiar
with. Underscore.js has almost everything you want to learn on a new language
and it thought me a lot.

When I completed the project I figured I can post it online and other clueless
javascript developers like myself can learn python from a familiar place.

I'm fully aware that python already has most of the tools underscore has and
this code is not pythonic at all. It was built that way intentionally. I
wanted it to be the same as underscore.js.

Now I need your advice to write a better python code and maybe create a useful
library after all.

Thank you all.

PS: I wrote this comment from mobile phone so please excuse any errors.

~~~
tebeka
Also note that _ has a meaning in the Python REPL - it's the value of the last
expression.

~~~
malandrew
_ is also used in the node.js REPL to mean the last expression. This means
that you can't require() underscore.js as you normally would and must instead
choose a different name.

------
jmagnusson
Why, oh why?

map(str.upper, ['foo', 'bar']) == _(["foo", "bar"]).invoke("upper")

[w for w in ["foo", "hello", "bar", "world"] if len(w) > 3] ==
_.filter(["foo", "hello", "bar", "world"], lambda x, _a: len(x) > 3)

sorted([i _ 2 for i in [10, 48, 56, 30, 20] if i > 20]) == _([10, 48, 56, 30,
20]).chain().filter(lambda x, _a: x > 20).map(lambda x, _a: x *
2).sortBy().value()

~~~
rmc
I even don't like using map, pefering comprehension.

    
    
        [w.upper() for w in ["foo", "bar"]]
    

This underscore.py is not pythonic. Don't use it.

~~~
jmagnusson
I completely agree with you. I only used map as he pointed out in the examples
how "easy" it was to call it dynamically.

~~~
masklinn
An other option if you use map is `operator.methodcaller`, which is also
slightly closer in semantics to underscore's invoke (function name specified
by string, ability to specify argument to apply to the method, duck-typed).

------
michaelhoffman
I hesitate to add to the negative response to what is surely a well-meaning
free project for the world. But `_` is really a poor choice for a variable
name in Python. It is already used as:

* the value of the last expression in the REPL

* a conventional abbreviation for `gettext.gettext` (<http://docs.python.org/library/gettext.html>)

* a conventional throwaway variable (for `str.partition` and other functions that return a larger tuple than you want)

And for most of these features, invoking them through a object/class method
rather than a standalone function is unwieldy (and unpythonic)

~~~
j_baker
From the page itself:

 _Please keep in mind that this is just a port of a javascript library, please
don't get started with the "but it's not pythonic" stuff. This library has no
intentions to be pythonic, infact it tries to bring same underscore experience
from javascript to python._

You have to give the author credit for his candor at least.

That said, I like that the author of this is trying new things out. We can't
let Python become petrified by rigid definitions of "pythonic".

~~~
sitkack
Only by being constructively critically reflective can we continue to grow.
Pythonic is bandied about like a hammer. If people understood the intent of
_pythonic_ I think they wouldn't use the term unpythonic so loosely.

------
djacobs
It is hilarious that someone would have the knowledge to build this but not
know that it was already implemented as part of the language.

Is this a parody?

~~~
serkanyersen
I posted a comment to clear this up. Sorry for the confusion.

~~~
StavrosK
I'm sorry about all the negativity. Python includes all these things, sure,
and the code is not great, but it's a learning project. Can we treat it as
such and not criticize it so much?

~~~
djacobs
I'm not sure the responses are expressing negativity as much as they are
expressing confusion. This was a learning project, sure, but it was also
posted to Hacker News (and without that caveat).

------
stephen_mcd
Most of the methods provided are functions already built into Python (map,
filter, reduce, all, any, min, max)

Also the underscore variable name conflicts with the common convention of
using an underscore as the i18n translation function.

Those issues aside, the templating looks handy, and I'm sure the whole thing
was fun to write.

------
FuzzyDunlop

        VERSION = "0.1.2"
        """
        Version of the library
        """
    

This is a good example of unnecessary commenting.

But I think this port misses the point of Underscore.js, which is to make the
same functional features of the language available to all browser
implementations, because not all browsers have forEach, or filter, or reduce,
etc. In Python, or other languages? The features are already there.

~~~
serkanyersen
Haha :) I don't know what I was thinking by putting that comment.

Underscore.py is not trying to fill any gap in Python. It's just a port. Maybe
a useful collection of tools. But I agree it's mostly pointless when there are
itertools and functools.

------
draegtun
Other Underscore.js ports (that I know of):

Perl - <http://vti.github.com/underscore-perl/>

Lua - <http://mirven.github.com/underscore.lua/>

PHP - <http://brianhaveri.github.com/Underscore.php/>

Actionscript 3 - <https://github.com/amacdougall/underscore.as>

------
borntyping
There is absolutely no reason to use this. As far as I can tell, it's a direct
port of underscore.js, and implements nothing but functionality that's already
in python.

~~~
serkanyersen
I should put this on the project description :) you are exactly right.

------
yoduh
My opinion: Anytime you share code by posting it publicly, you should always
be prepared for negative feedback. In some cases that might be the whole point
of posting it: you want to learn from your mistakes.

------
why-el
Good job! I know that some of these functions maybe have already occurred to
Python developers (map et al), but this probably lead you to a broader
understanding of underscore.js itself.

~~~
masklinn
> I know that some of these functions maybe have already occurred to Python
> developers

Some? Pretty much all of them are already either builtins or in the stdlib…

~~~
why-el
I am pretty sure they are. The "some" is due to my lack of Python knowledge.
:)

------
mark_story
While I can understand this might have been fun from a hacking/building
experience, I don't understand why do it. Everything except the micro
templating already exists in python.

------
victorlin
This doesn't bring anything good to Python. Python can do those things nicely.
I can't see any point of this library. Also, underscore already has its
meaning in some places, such as for i18n. For example, _('Text to be
localized'). Another use of underscore is to store the previous output in
console. Although you can rename it, still, it's pointless.

------
sontek
I think the biggest benefit of this is having the template language ported to
python so you can use the same templates server side or client side.

~~~
apendleton
This template language is only superficially the same, but the code between
the <% and %> would need to be python in this version, not JS, so you can't
actually share anything. You would need to combine something like this with a
JS-to-Python transpiler for that to work.

------
cpylua
Collection functions are not that useful in Python. For Function functions I'd
prefer using decorators.

~~~
sophacles
How are collection functions not useful in python? I use map and sort (or the
comprehension equivalent) daily. The rest I use at least once a week, with the
possible exception of groupBy - as my workload doesn't really need it very
often.

~~~
masklinn
I think he means _the underscore_ collection functions are not very useful
because for the most part they already exist in Python.

