-7

Is there a philosophical reason why the second code snippet toto would be rejected in python while the first one titi is ok ?

def titi():
    for m in range(5):
      if m < 4:
        yield m 


toto = for m in range(5):
            if m < 4:
                yield m

edit :

I would have expected the body of a function to be a valid expression, and to be able to define equally

def titi():
   toto  
nicolas
  • 9,549
  • 3
  • 39
  • 83
  • 7
    This question can be asked for any kind of invalid syntax I guess. – sashaaero Nov 02 '19 at 11:49
  • 1
    This is invalid syntax, use a list comprehension for the second case. – Dos Nov 02 '19 at 11:51
  • What do you mean with 'philosophical reason'? Yes, there are reasons why this can not be parsed easily (e.g indentation inside expressions is not meaningful). – MegaIng Nov 02 '19 at 11:52
  • What is the reason you believe that it is possible? – Austin Nov 02 '19 at 11:53
  • 2
    It's no more meaningful than having a `return` statement outside a function – snakecharmerb Nov 02 '19 at 11:54
  • 1
    Why would you expect to be able to take a whole function body and stick it on the right side of an `=` sign? – user2357112 Nov 02 '19 at 11:54
  • added some precision. It's not syntax per se. – nicolas Nov 02 '19 at 11:57
  • @user2357112 that's usually what we can do with *closed* expression in most language out there. a function declaration's role is usually to declare additional *bindings*, nothing more. `toto` does not depend on anything.. – nicolas Nov 02 '19 at 11:58
  • 2
    Most languages don't let you do this, even languages with expression-oriented rather than statement-oriented syntax, and Python's syntax is statement-oriented. – user2357112 Nov 02 '19 at 12:03
  • @snakecharmerb I see. that's actually where my confusion lied. in other languages, `yield` or `return` are just expressions. but in python it's a statement ! – nicolas Nov 02 '19 at 12:06
  • @user2357112 exactly. thanks – nicolas Nov 02 '19 at 12:06
  • There actually is syntax to use `yield` as an expression (you just stick parentheses around it, like `(yield whatever)`). The bigger problems are that it makes no sense outside a function, and that `for` and `if` statements aren't expressions. – user2357112 Nov 02 '19 at 12:12
  • @user2357112 I don't want to go against The Pythonic Zen, but to grasp its essence to adapt to it. I forgot how statement are everywhere in "practical languages". same with "async" in a few languages out there. – nicolas Nov 02 '19 at 12:22

2 Answers2

2

Well, one reason is that the assignment operator = must have an expression on the right, not a (series of) statement(s). You might then ask why this is so, and I guess it is chosen to limit the complexity of the parser, and to disallow what one might consider confusing code.

Note that your toto can be spelled out in a valid way like so:

toto = (
            m
    for m in range(5)
        if m < 4
)

(line breaks and indentation only there to emphasize that this is very close to the same structure as in your invalid code).

jmd_dk
  • 12,125
  • 9
  • 63
  • 94
  • You are right about the reason. I thought there was a deeper root. i dont buy the 2 root causes you mentioned : It still has to parse it. limiting the complexity of the parser would mean to parse it in the same way irrespectively of the context. also regular languages tend to be less confusing (SML is quite good at that). It is however easier to bolt on a fixed ad-hoc sequence monad : you get the benefit of monadic style (imperative looking code) limited to that one special hardwired case. – nicolas Nov 02 '19 at 16:31
0

I think it is mostly the idea that, in programming languages, loops of any sort cannot be assigned to variables, because I guess there is some deterministic notion associated to variables that loops can lack. Your example is a special case, in the sense that the structure is pretty simple and that you include the keyword yield. So yes, your example could be valid, but then it would mean that some loops could be assigned to variables and not others, which lacks consistency. Python makes up for that in the sense of list comprehensions and generators (your first snippet) for example. In these cases, the loops are actually encapsulated in some sort of a parent object, which gives them a more deterministic, or bounded, aspect. And indeed, not any loop can be part of a generator or a list comprehension, which nicely provides a special status to those loops like yours which could pretend to be assigned to variables.

Patol75
  • 4,342
  • 1
  • 17
  • 28
  • Quite a few languages allow you to talk about "the sequence of integers" for example, and pass that as an argument, return it as a value, etc.. with no particular prescribed context or restriction – nicolas Nov 02 '19 at 12:27
  • This sounds to me like what list comprehensions and generators are in Python. But, for these other languages, do you achieve this with loops? – Patol75 Nov 02 '19 at 12:31
  • It is.. once defined in the context of a function. You can not talk directly about "the sequence of integers", and, say, save it to disk as such, or send it to another computer. You can define something that will produce (by *running python*) integers. – nicolas Nov 02 '19 at 12:37
  • hence question like this https://stackoverflow.com/questions/5737196/is-there-an-expression-for-an-infinite-generator – nicolas Nov 02 '19 at 12:49
  • Yeah, so basically it has to be wrapped into something else. Otherwise you break the logic and consistency of your algorithmic. – Patol75 Nov 02 '19 at 13:18
  • It's just a choice to support that in the language or not – nicolas Nov 02 '19 at 13:26