0

Is there any way to implement the following function as a lambda:

def z(s,f):
 for c in s:
  if c in f:f.remove(c)
  else:return 0
 return 1

My biggest trouble is the f.remove(c):

z=lambda s,f:f.remove(c) if c in f else 0 for c in s;1

The above code just complains with a syntax error.

Note that I am not using this for any serious purpose, just for recreational code golfing.

6
  • You should ask this question in codereview.stackexchange.com Commented Sep 28, 2014 at 7:09
  • 1
    Your syntax error has nothing to do with the remove; its that you're trying to use list comprehension/generator expression syntax without being in a list comprehension or a generator expression. Commented Sep 28, 2014 at 7:12
  • 1
    First, why do you want it to be a lambda instead of a def? Second, it's a really bad idea to use comprehensions, conditional expressions, lambda, etc. for things only being run for side effects. Commented Sep 28, 2014 at 7:13
  • @abarnert The lambda is being used for golfing Commented Sep 28, 2014 at 7:14
  • 1
    If you're code-golfing, then (a) add that in your question, and (b) this is a silly way to do it. Why not just, e.g., use set intersection and then len and == to get the 0 or 1? Commented Sep 28, 2014 at 7:23

3 Answers 3

3

An equivalent lambda:

lambda s, f: int(all(c in f and f.remove(c) is None for c in s))

This uses lazy evaluation of and and all to remove only the appropriate characters.

Sign up to request clarification or add additional context in comments.

2 Comments

I think it worth explaining that the lazy evaluation is possible only when using generators and not lists
@Elisha all is still evaluated lazily on a lists, too; the fewest possible elements are tested to be certain of the result. If you made the generator expression a list comprehension by adding square brackets then the code would work differently, sure, but that's true of many different changes to the code!
2

You could write this as a lambda, but you really, really shouldn't.

First, you have to convert each statement to an expression. There are multiple steps here, and every single one of them is a bad idea.

if c in f: f.remove(c) becomes f.remove(c) if c else 0. It's very unpythonic to use functions called only for their side-effects inside an expression like this, but it's not illegal. We just have to take into account the fact that f.remove(c) always returns None, and pick something else we can put in the other branch.

Now, that doesn't do an early return, because that's impossible; you can't have a return statement, or any statement, inside an expression. We'll get back to that later.

Next, the for statement has to become some kind of comprehension, in this case a generator expression: (f.remove(c) if c in f else 0 for c in s). Notice that we're putting the values None and 0 into an iterator, even though we don't actually care about those values, so this is a misuse of comprehensions, but again not illegal.

And now we can handle the "early return" by using the all function: all(value is None for value in (f.remove(c) if c in f else 0 for c in s)). That will be True if every value is None, but as soon as it finds one that isn't (because c in f was false) it will stop, and evaluate to False. And we can turn that False into 0 and True into 1 just by calling int on it (or using 1 if foo else 0, but why bother trying to be Pythonic at this point?) so:

z = lambda s, f: int(all(value is None for value in 
                     (f.remove(c) if c in f else 0 for c in s))

Of course this is a misuse of lambda, since the entire point of lambda is that it gives us an anonymous function that can be defined in the middle of an expression; if you want to define it in a statement and give it a name, all you're doing by using lambda instead of def is obfuscating your code.

You can collapse the two loops into one if you want, and make various other changes to make it more concise if you're going for code golf.

Comments

0

If we're looking for silly ideas, I thought of way to actually return early from an expression. First we need a bit of reusable scaffolding:

class Return(Exception): pass

def throw(e): raise e

def early(f):
    try:
        return f()
    except Return as e:
        return e.args[0]

Now:

z = lambda s, f: early(lambda: [f.remove(c) if c in f else throw(Return(0)) 
                                for c in s])

That early function won't be necessary if PEP 463 is accepted, and neither will the inner lambda:

z = lambda s, f: [f.remove(c) if c in f else throw(Return) 
                  for c in s] except Return: 0

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.