Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrictons of Python compared to Ruby: lambda's

I was going over some pages from WikiVS, that I quote from:

because lambdas in Python are restricted to expressions and cannot contain statements

I would like to know what would be a good example (or more) where this restriction would be, preferably compared to the Ruby language.

Thank you for your answers, comments and feedback!

like image 429
Shyam Avatar asked Apr 16 '10 16:04

Shyam


People also ask

What can Ruby do that Python can t?

Python support multiple inheritance, while Ruby support single inheritance. Python is mainly used for academic, AI, machine learning, and scientific programming, while Ruby is used for web development and functional programming.

Is Python slower than Ruby?

There is a perception that Python is faster than Ruby, and this has often led teams to prefer it over Ruby for web development. The Ruby community is painfully aware of this, and Ruby has gotten way faster over the years. Now, in benchmarks, Ruby performs just about as well as Python, if not better.

Can Python replace Ruby?

While there is potential, Ruby must tweak its machine learning and AI libraries to do as well as Python in this field. Ruby won't replace Python anytime soon. TLDR: Python is a long-standing resource for machine learning programming. Thinking about machine learning in the context of Ruby vs.

What lambda function does in Python?

A lambda function is a small anonymous function. A lambda function can take any number of arguments, but can only have one expression.


3 Answers

I don't think you're really asking about lambdas, but inline functions.

This is genuinely one of Python's seriously annoying limitations: you can't define a function (a real function, not just an expression) inline; you have to give it a name. This is very frustrating, since every other modern scripting language does this and it's often very painful to have to move functions out-of-line. It's also frustrating because I have a feeling Python bytecode can represent this trivially--it's just the language syntax that can't.

Javascript:

responses = {
        "resp1": {
                "start": function() { ...  },
                "stop": function() { ... },
        },
        "resp2": {
                "start": function() { ...  },
                "stop": function() { ... },
        },
        ...
}
responses["resp1"]["start"]();

Lua:

responses = {
        resp1 = {
                start = function() ...  end;
                end = function() ...  end;
        };
        ...
}
responses.resp1.start();

Ruby:

responses = {
    "resp1" => {
        "start" => lambda { },
        "stop" => lambda { },
    },
}
responses["resp1"]["start"].call

Python:

def resp1_start():
    pass
def resp1_stop():
    pass
responses = {
    "resp1": {
        "start": resp1_start,
        "stop": resp1_stop,
    },
}
responses["resp1"]["start"]()

Note that JavaScript and Lua don't have lambdas: they have no reason to exist, since inline functions cover them in a much more natural and general way.

I'd probably rate this as the single most annoying day-to-day Python limitation.

like image 169
Glenn Maynard Avatar answered Oct 17 '22 09:10

Glenn Maynard


The most commonly encountered situation regarding statements is probably Python 2.X's print statement.

For example,

say_hi = lambda name: "Hello " + name

works as expected.

But this will not compile:

say_hi = lambda name: print "Hello " + name

because print is not a proper function in Python 2.

>>> say_hi = lambda name: "Hello " + name
>>> say_hi("Mark")
'Hello Mark'
>>> 
>>> say_hi = lambda name: print "Hello " + name
SyntaxError: invalid syntax

The rest of the statements besides print can be found in the Python documentation online:

simple_stmt ::=  expression_stmt
                 | assert_stmt
                 | assignment_stmt
                 | augmented_assignment_stmt
                 | pass_stmt
                 | del_stmt
                 | print_stmt
                 | return_stmt
                 | yield_stmt
                 | raise_stmt
                 | break_stmt
                 | continue_stmt
                 | import_stmt
                 | global_stmt
                 | exec_stmt

You can try the rest of these out in the REPL if you want to see them fail:

>> assert(True)
>>> assert_lambda = lambda: assert(True)
SyntaxError: invalid syntax
>>> pass
>>> pass_lambda = lambda: pass
SyntaxError: invalid syntax

I'm not sure what parallels there are between Python's lambda restrictions and Ruby's proc or lambda. In Ruby, everything is a message, so you don't have keywords (okay, you do have keywords, but you don't have keywords that appear to be functions like Python's print). Off the top of my head, there's no easily-mistaken Ruby constructs that will fail in a proc.

like image 41
Mark Rushakoff Avatar answered Oct 17 '22 09:10

Mark Rushakoff


An example that has sometimes come up with me is something like this:

def convert(value):
    n = expensive_op(value)
    return (n, n + 1)

new_list = map(convert, old_list)

Although it is short and sweet enough, you can't convert it to a lambda without having to run expensive_op() twice (which, as the name suggests, you don't want to), i.e. you would have to do

new_list = map(lambda v: (expensive_op(v), expensive_op(v) + 1), old_list)

because assignment (n = ...) is a statement.

like image 27
balpha Avatar answered Oct 17 '22 08:10

balpha