Use let expression in Python

Packaged-> hachibeeDI / letexpr

It is a story

State monad in Python I was writing this article and wanted a let expression like Haskell in Python, so I thought about it.

Then, in the related post Make let's one-line programming Because there was something like that, I will make it feel good to divert it. I thought, but I gave up diversion because it looks like apply. So I will do my best.

The let expression seems to bind inside the let and evaluate the expression with in. Also, it seems that variables bound in let can be referenced from the entire let expression.

For the time being, let's bind the result to something variable so that it can be used in

class let(object):
    def __init__(self, action=None):
        if action is None:
            name, act = action
            self.lets = {name: act()}
        else:
            self.lets = {}

    def __or__(self, action):
        ''' :type action: (str, func) '''
        name, f = action
        self.lets[name] = f()
        return self

    def in_(self, func):
        return func(**self.lets)

if __name__ == '__main__':
    x = let(('xx', lambda : 1 + 2)) | ('y', lambda : 'yyy') | ('z', lambda : 5)
    print x.in_(lambda xx, y, z: str(xx) + y + str(z))

It became a form for the time being. However, as it is, it is not possible to refer to the value between let expressions, so I will make it feel good.

As mentioned above, in Python you can pass a value to the argument corresponding to the key by passing a ** dictionary to the argument of the function, but unlike some popular languages, the argument An error will be thrown for excess or deficiency of. In other words, you only need to pass the values that each needs in the results stored in self.lets_.

In such a case, the ʻinspect module is convenient, so we use the getargspec` function to pass only the necessary arguments.

from inspect import getargspec


class let(object):
    def __init__(self, action=None):
        if action is not None:
            name, act = action
            self.lets = {name: act()}
        else:
            self.lets = {}

    def __or__(self, action):
        ''' :type action: (str, func) '''
        name, f = action
        require_arg_keys = getargspec(f).args
        self.lets[name] = f(
            **self.__extract_require_args(require_arg_keys)
        )
        return self

    def __extract_require_args(self, arg_keys):
        return {k: v for k, v in self.lets.iteritems() if k in arg_keys}

    def in_(self, func):
        require_arg_keys = getargspec(func).args
        return func(
            **self.__extract_require_args(require_arg_keys)
        )

Now, let's try by passing an expression that actually requires various arguments. Let's make the indentation cool.

    measure = \
        (let()
            | ('x', lambda : 10)
            | ('y', lambda : 20)
            | ('size', lambda x, y: x * y)
            | ('hoge', lambda x, y: 'fooo')
        ) \
        .in_(lambda x, y, size:
             'x = {x}, y = {y}, x * y = {size}'.format(x=x, y=y, size=size))
    print measure  # => x = 10, y = 20, x * y = 200

You did it, did not you. In the current situation, we are evaluating from top to bottom, so we can not get the upper value from the lambda below, but if we do our best to delay the evaluation of the expression, we will be able to do that as well. I agree. I thought that normal is the best because the one who wrote it normally can read it normally.

Recommended Posts

Use let expression in Python
Use config.ini in Python
Use print in a Python2 lambda expression
Use dates in Python
Use Valgrind in Python
Use profiler in Python
Regular expression in Python
Regular expression in Python
Let's use def in python
Use Measurement Protocol in Python
Use callback function in Python
Use parameter store in Python
Use HTTP cache in Python
Use MongoDB ODM in Python
Use list-keyed dict in Python
Use Random Forest in Python
Use regular expressions in Python
Use Spyder in Python IDE
Use fabric as is in python (fabric3)
How to use SQLite in Python
Use rospy with virtualenv in Python3
How to use Mysql in python
Use Python in pyenv with NeoVim
How to use ChemSpider in Python
How to use PubChem in Python
Use OpenCV with Python 3 in Window
Python in optimization
CURL in python
Metaprogramming in Python
[Introduction to Python] How to use class in Python?
Python 3.3 in Anaconda
Geocoding in python
Meta-analysis in Python
Unittest in python
Easily use your own functions in Python
Start / end match in python regular expression
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Easy way to use Wikipedia in Python
Plink in Python
Constant in python
Don't use \ d in Python 3 regular expressions!
Lifegame in Python.
FizzBuzz in Python
How to use __slots__ in Python class
Sqlite in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
Use pathlib in Maya (Python 2.7) for upcoming Python 3.7
nCr in Python.