1

I'd like to write kind of CPS code higher functions. They should take a function code, encapsulate it in the object and add means for combining this objects.

Something like this:

myFunction=MyFunction(
  a = b+c
  print(c)
  return a)

But there is only one pythonic expression for anonymous functions - lambda statement. It suits not too well.

Python is a powerful language, it has different expressions: decorators, eval, etc... Is there a good way to write anonymous functions like in the mentioned example?

Other way is to extend lambda expressions with special functions like monadic bind and return, and other higher-order functions for writing complex expressions single-lined.

The main purpose is to create custom throw control expressions.

class TimeoutExpression:
  def __init__(self,name,function,timeout):
    ...
  def eval(self):
    """ eval functions, print result and error message
      if functions failed to calculate in time """
    ...
  def andThen(self,otherExpression):
    """ create complex sequential expression"
    ...
  def __call__(self):
    ...

And it is used in the follow way:

TimeoutExpression( time consuming calculation ).andThen(
  file object access).andThen(
    other timer consuming calcualtion )

What is the best python idiomatic way for creating custom control flow constructions?

I've read the discussion: How to make an anonymous function in Python without Christening it? There were mentioned several decisions with same approach: generating function from triple quoted strings. It is seemed quite cumbersome while absolutely correctly behave. Is it the best approach engineered for now?

Update:

I was told there is no problem, python allows you use def in any context. I've assumed that my python experience tricks me and tried to use def in any scope as suggested. I've got an error. How exactly should I place def in any context?

def compose(f):
    return lambda k: lambda x: f(k(x))

test = compose( def sqr(x) :
                print ("sqr "+str(x))
                return x*x
                return sqr) ( def x2(x):
                              print("x2 "+str(x))
                              return x*2
                              return x2 )

The error:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "anonFunction.py", line 4
    test = compose( def sqr(x) :
                  ^
SyntaxError: invalid syntax
Community
  • 1
  • 1
ayvango
  • 5,867
  • 3
  • 34
  • 73

3 Answers3

3

There is no advantage in using lambda's w.r.t Python. Lambda's and Anonymous functions are generally used for simple functions, and if you need a more complex multi-line functions, its more readable to write a named function.

As Functions are first class objects, you can simply define it, assign it to a variable and use it and pass it around. Unless otherwise you need a throwaway simple function for which you may opt for lambda's, named function is favorable. Also nevertheless using lambda in never quite Pythonic.

Coming back to your example,

myFunction=MyFunction(
  a = b+c
  print(c)
  return a)

In Python, writing it similarly as

def MyFunction:
    a =b + c
    print c
    return a

and then passing it around your code as MyFunction is quite Pythonic. I have seen codes in Javascripts where Callbacks are written as anonymous. But each languages have them own philosophy and Python's philosophy is readability.

---Readability counts.

Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • Named functions is useful if they are used by names more then once. I'd like to write something like this: Fun(some expr).bind(some expr).bind(other expr) for creating non-standard control flow such as parallel execution or calculations with timeouts and so on. – ayvango Apr 19 '12 at 19:16
  • @ayvango: Even using Named Function for a single use is not a bad option. – Abhijit Apr 19 '12 at 19:21
  • 1
    @ayvango Note also that you can use `def` in any scope you want, not just at the top level; they also have full closures and so on. There's not much advantage to have "multiline lambdas"; the only difference is that you can't write it directly as an argument to another function, which is generally syntactically pretty confusing anyway. – Danica Apr 19 '12 at 19:26
  • @Dougal can you give examples with using def in any scope? I've added my example in the question – ayvango Jul 29 '12 at 20:01
  • 1
    @ayvango Sorry, when I said "any scope" I didn't mean "anywhere at all"; I think it's only places where full statements are allowed, not expressions like in your example. What you would do there is put `def sqr` and `def x2` as standalone expressions and then pass in `sqr` and `x2`; what I meant by that was that you can do a `def` inside another `def` and use things in the enclosing scope. – Danica Jul 29 '12 at 20:29
  • @Dougal Sorry, I was quite a verbalist. My example should be expanded further for combination of 5 and more functions. In this case separating function definition from its usage become obscuring. Using anonymous expressions in not only shorter but also a cleaner way. – ayvango Jul 29 '12 at 20:36
  • @ayvango Well, what you're trying to do just isn't possible in python without putting the function body in strings or doing disgusting nested lambdas. IMO if you assign reasonable names to the functions, it's still more readable to create them separately beforehand and then make the call shorter and more comprehensible instead of being weirdly concatenated like in your example above. – Danica Jul 29 '12 at 21:13
  • @Dougal The primary goal is to create a custom control declarations. For example create control structure that can deal with monads nicely. You can't convert all expressions in monadic code to named functions: your code would blow up. Using """ is grievous but still better than nothing – ayvango Jul 29 '12 at 21:25
  • @ayvango I haven't seen any Python code that actually needs this; I'd be interested in seeing a real example where you need five-plus full functions and using `def`s is actually worse than putting them inline. Putting code in strings is gross, probably slower, and just asking for trouble IMO. – Danica Jul 29 '12 at 23:00
1

In Python, using the lambda keyword, you can only make a function object that evaluates a single expression and returns the result. To make a function using statements or with multiple lines, you must use the def keyword, which requires a name.

The reasons for the restrictions on lambda are mostly based on the fact that Python treats end-of-line as a significant thing:

No Multiline Lambda in Python: Why not?

However, the name is not important. You can make a convention that every one of your "anonymous" functions will all be defined with the name anon or something. If you really care, you can erase all trace of the name:

y = 5
def anon(x):
    return x + y  # note "closure" over the current value of y

myFunction = anon

# if you really care, you can erase all evidence of name "anon"
anon.__name__ = ''  # wipe the record of original name "anon"
del(anon)  # unbind the name "anon"

So, for functional programming, Python can create first-class function objects, pass them around, etc. The one thing Python cannot do is create a complex function object that never has a name, but there is really no reason why that should matter.

Community
  • 1
  • 1
steveha
  • 74,789
  • 21
  • 92
  • 117
  • Python can create arbitrary complex function objects with lambda constructions, using lambda programming technique, but it is rather tiresome and should be used only if there is no other choice (e.g. lisp) – ayvango Apr 19 '12 at 19:50
  • All right, lawyer mode engaged: instead of saying you can write "simple functions" the answer now says "you can only make a function object that evaluates a single expression and returns the result." Yes, it is possible to write a complex function object using a complex expression but it would be a very bad idea, or as you said, "rather tiresome and should be used only if there is no other choice". – steveha Apr 19 '12 at 19:55
1

I have a hack -- and that's truly the only proper term for it -- using nested functions that gives the sort of functionality that a multi-line lambda might give. You can check out my GitHub repository here.

Basically it allows you to do things like:

fibonacci = f('result = t(a-1)+t(a-2) if a>2 else 1; return result')
fibonacci(6) #Output: 8

Or more to the point of anonymous functions:

cube = f('result = a**3; return result')(4)
print(cube) #Output: 64

There are obviously limitations with this hack; for example, I still have not figured out a way to implement more complicated indented constructs like if or while, but again, this is a really cheap hack.

whaatt
  • 31
  • 2