Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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
  ```


> why not also "bye" or "leave" or "close" or "end" or "terminate".

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.


>Python problematically decides that returns diminish after the first --- “first” according to developers, that is --- possibility in all cases

Eh, that feels pretty arbitrary to me. `quit()` and `exit()` both work, and looking at other languages, `exit()` should almost certainly be your first choice

     C: exit(int)
  Java: System.exit(int)
  SBCL: (quit)/(exit)
    C#: Environment.Exit(int)
   PHP: exit(int)/exit(string)
  Rust: std::process::exit(int)
Having `exit` or `quit` without the parens work might accommodate some people whose first choice isn't to call a function (I guess because they're thinking of the REPL as a shell?), but surely if you're going that far `bye` is a reasonable and practical choice. ftp/sftp use it to this day. At some point you make a cutoff, and where you do is pretty arbitrary. You can like that ruby is twice as lenient as python, but I think it's a stretch to say that python using the single most common function call and a very common alias is "problematic" or even surprising. IMO, python's behavior is less surprising because I don't expect `exit` to be a special command that executes inside the REPL. I expect `exit()` because that's what other programing languages do. And python famously ditched the inconsistent `print "Foo"` syntax in favor of `print("Foo")` in python3 exactly because inconsistency in what was and wasn't a function call was surprising.


> Having `exit` or `quit` without the parens work might accommodate some people whose first choice isn't to call a function (I guess because they're thinking of the REPL as a shell?),

In ruby, parentheses are optional for function calls. `exit` is a regular call, not some REPL peculiarity.

EDIT: Nevermind. Just found that despite the `exit` method being already defined, both irb and pry overshadow that with a repl command that does the same thing. Maybe it's so that it can't be redefined.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: