| On the one hand, being generous in your inputs is always appreciated. On the other hand, the fact that both exit and quit will terminate ruby means the answer to "how do I quit ruby" now has two answers (technically 4 because `quit()` and `exit()` also work, and if we're talking about "least surprise" if you accept "exit" and "quit", why not also "bye" or "leave" or "close" or "end" or "terminate". Python might be surprising, but in this example, it's only surprising once, and helpful when it surprises you. Now you know quitting requires calling a function and that function is named exit() (although amusingly python3 anyway also accepts quit()). And being fully pedantic it doesn't know what you mean, it is assuming what you mean and making a suggestion, but that's not the same as knowing. From here on I'm not arguing the point anymore, just recording some of the interesting things I discovered exploring this in response to your comment: You can do this in python (which IMO is surprising, but in a different way): ```
>>> quit
Use quit() or Ctrl-D (i.e. EOF) to exit
>>> quit=True
>>> quit
True
>>> quit()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'bool' object is not callable
>>> exit()
```
But this also gives some sense to python's behavior. `quit` and `exit` are symbol names, and they have default assignments, but they're re-assignable like any other symbol in python. So the behavior it exhibits makes sense if we assume that they're not special objects beyond just being built int.`exit` is a class isntance according to type. So we should be able to create something similar, and indeed we can: ```
>>> class Bar:
... def __repr__(self):
... return "Type bar() to quit!"
... def __call__(self):
... print("I quit!")
...
>>> bar = Bar()
>>> bar
Type bar() to quit!
>>> bar()
I quit!
>>>
```
Interestingly this suggests we should be able to replace exit with our own implementation that does what ruby does if we really wanted too: ```
>>> class SuperExit:
... def __init__(self, real):
... self.real_exit=real
... def __repr__(self):
... print("Exiting via repr")
... self.real_exit()
... def __call__(self):
... print("Exiting via call")
... self.real_exit()
...
>>> exit = SuperExit(exit)
>>> exit
Exiting via repr
```
|
We can include these as well, but each keyword that you include brings diminishing returns at the cost of clutter and inconsistence in the API. Python problematically decides that returns diminish after the first --- “first” according to developers, that is --- possibility in all cases. Ruby anticipates that everyone's first choice will be different and practically maximizes comfort of users.