kachayev / fn.py

Functional programming in Python: implementation of missing features to enjoy FP
Other
3.35k stars 204 forks source link

Method calling from _ not working? #79

Open jni opened 8 years ago

jni commented 8 years ago

Hi,

I'm not sure whether this is supposed to work:

from fn import _ as X
X.endswith('tif')('image.tif')

This prints "False".

Looking at the tests I see this form:

from fn import _ as X
X.call('endswith', '.tif')('image.tif')

This correctly evaluates to True, but is significantly uglier. What's happening in the first form?

Digenis commented 8 years ago

The author of the module chose to treat .call() as a special attribute because the usefulness of being able to create method callers outweighs the usefulness of being able to use this very specific attribute getter.

You can subclass underscore to redefine .call() as an attribute getter. You can also subclass underscore to turn attribute getters into method callers. In no way can this be perfect because this is a hack built on top of python's data model. This is a "can't fix" issue.

jni commented 8 years ago

@Digenis I suspected it would not be fixable, but can you explain to me what is happening in the first form? I would expect it to either fail catastrophically or do the right thing.

Digenis commented 8 years ago

_ is an instance of the underscore class. Retrieving any attribute results in an attribute getter for such an attribute. Calling it invokes this attribute getter with the 'tif' string as its first argument. The endswith attribute of str however is a callable method. You then call it on another string. tif doesn't end in image.tif so the result is false. What happens is attrgetter('endswith')('tif')('image.tif') which is more like 'tif'.endswith('image.tif')