mini_lambda (original) (raw)

python-mini-lambda (mini_lambda)

Simple Lambda functions without lambda x: and with string conversion capability

Python versions Build Status Tests Status codecov

Documentation PyPI Downloads Downloads per week GitHub stars

repr is now enabled by default for expressions and functions! More details here

mini_lambda allows developers to write simple expressions with a subset of standard python syntax, without the lambda x: prefix. These expressions can easily be transformed into functions. It is possible to get a string representation of both.

Among many potential use cases, the original motivation came from valid8 where we want to let users provide their own validation functions, while still being able to raise user-friendly exceptions "showing" the formula that failed.

Installing

> pip install mini_lambda

Usage

a- Principles

Three basic steps:

For example with a numeric variable:

`# -- expressions -- from mini_lambda import x my_expr = x ** 2 my_expr # <LambdaExpression: x ** 2>

my_expr(12) # beware: calling an expression is still an expression ! # <LambdaExpression: (x ** 2)(12)>

-- functions --

from mini_lambda import _ my_func = _(x ** 2)
my_func # <LambdaFunction: x ** 2>

assert my_func(12) == 144 # calling a function executes it as expected `

Or with a string variable:

`# create or import a magic variable, here we import 's' from mini_lambda import s

write an expression and wrap it with _() to make a function

from mini_lambda import _ say_hello_function = _('Hello, ' + s + ' !')

use the function with any input

say_hello_function('world') # Returns "Hello, world !"

the function's string representation is available

print(say_hello_function) # "'Hello, ' + s + ' !'" `

b- Capabilities

The variable can represent anything, not necessarily a primitive. If you wish to use another symbol just define it using InputVar:

`from mini_lambda import InputVar z = InputVar('z')

from logging import Logger l = InputVar('l', Logger) `

Note that the type information is optional, it is just for your IDE's autocompletion capabilities.

Most of python syntax can be used in an expression:

`from mini_lambda import x, s, _ from mini_lambda.symbols.math_ import Log

various lambda functions

is_lowercase = _( s.islower() ) get_prefix_upper_shebang = _( s[0:4].upper() + ' !' ) numeric_test_1 = _( -x > x ** 2 ) numeric_test_2 = _( ((1 - 2 * x) <= -x) | (-x > x ** 2) ) complex_identity = _( Log(10 ** x, 10) )

use the functions

is_lowercase('Hello') # returns False get_prefix_upper_shebang('hello') # returns 'HELL !' numeric_test_1(0.5) # returns False numeric_test_2(1) # returns True complex_identity(10) # returns 10

string representation

print(is_lowercase) # s.islower() print(get_prefix_upper_shebang) # s[0:4].upper() + ' !' print(numeric_test_1) # -x > x ** 2 print(numeric_test_2) # (1 - 2 * x <= -x) | (-x > x ** 2) print(complex_identity) # log(10 ** x, 10) `

If you know python you should feel at home here, except for two things:

Note that the printed version provides the minimal equivalent representation taking into account operator precedence. Hence numeric_test_2 got rid of the useless parenthesis. This is not a mathematical simplification like in SymPy, i.e. x - x will not be simplified to 0.

There are of course a few limitations to mini_lambda as compared to full-flavoured python lambda functions, the main ones being that

Check the Usage page for more details.

New: repr now enabled by default

Starting in version 2.0.0, the representation of lambda expressions does not raise exceptions anymore by default. This behaviour was a pain for developers, and was only like this for the very rare occasions where repr was needed in the expression itself.

So now

`>>> from mini_lambda import x, F

x ** 2 <LambdaExpression: x ** 2> F(x ** 2) <LambdaFunction: x ** 2> `

If you wish to bring back the old exception-raising behaviour, simply set the repr_on attribute of your expressions to False:

`>>> from mini_lambda import x

x.repr_on = False x ** 2 (...) mini_lambda.base.FunctionDefinitionError: repr is not supported by this Lambda Expression. (...) `

c- How to support mini-lambda expressions in your libraries.

You may wish to support mini-lambda expressions (not functions) directly into your code. That way, your users will not even have to convert their expressions into functions - this will bring more readability and ease of use for them.

You can do this with as_function: this will convert expressions to functions if needed, but otherwise silently return its input.

`from mini_lambda import _, s, as_function

def call_with_hello(f): """An example custom method that is lambda_friendy"""

# transform mini-lambda expression to function if needed.
f = as_function(f)

return f('hello')

it works with a normal function

def foo(s): return s[0] assert call_with_hello(foo) == 'h'

with a mini-lambda Function (normal: this is a function)

assert call_with_hello(_(s[0])) == 'h'

and with a mini-lambda Expression too (this is new and easier to read)

assert call_with_hello(s[0]) == 'h' `

In addition a is_mini_lambda_expr helper is also provided, if you wish to perform some reasoning:

`from mini_lambda import x, is_mini_lambda_expr, as_function

mini lambda: true

assert is_mini_lambda_expr(x ** 2)

standard lambda: false

assert not is_mini_lambda_expr(lambda x: x)

standard function: false

def foo(): pass assert not is_mini_lambda_expr(foo)

mini lambda as function: false

f = as_function(x ** 2) assert not is_mini_lambda_expr(f) `

Main features

See Also

The much-broader debate in the python community about alternate lambda syntaxes is interesting, see here

Equivalent (python-first)

I found the following libraries somehow covering the same use case, with more or less success/features:

A bit far from the topic but related: * letexpr for let expression like Haskell * calchylus: lisp-like expressions in python based on Hy * MiniOperators

String expression-first

These libraries create functions from string expressions. Therefore you cannot rely on your favourite IDE to check your expressions, but it might not be a problem for some users/use cases.

Others

Do you like this library ? You might also like my other python libraries

Want to contribute ?

Details on the github page: https://github.com/smarie/python-mini-lambda