-
Notifications
You must be signed in to change notification settings - Fork 372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Return expression #739
Comments
This could be implemented with a decorator and an Exception, like the tail
|
It would indeed encourage a non functional style, but I still think this
|
I think there's no need for a future import... why not just include it as an option, then strongly encourage using the other pattern instead? I do think there are points in code where not using a (return) is hard, especially without abusing exceptions or resulting in nested ifs that aren't really ideal. They're comparatively rare, but still. Some other lisps have ways of getting around this; for example, in Common Lisp I have blocks, so I can do (defun foo ()
(block
got-result
1
2
(return-from got-result 3)
4)) Sometimes, especially in Python code, bailing out early is nice. We should encourage other forms in Hy, but why prevent users from using this function? I might understand more if it breaks other complicated-scoping code, but is that really the reason? |
Actually, it turns out common lisp sets up the function as a block, so:
|
Can I also vote for the return expression? I think Hy should be able to do anything Python can. I should be able to translate any Python code I see into near-equivalent Hy. Automatically even, with some kind of py2hy (de)compiler. This would be really hard without return. You would have to rewrite any Python code with multiple exits. I'm fine with having an implicit return at the tail position. I'd prefer not to have to spell it out if I don't have to. The return statement is Rossum's recommended way of breaking out of nested loops. This isn't possible with only an implicit return. If I'm writing the code myself from scratch, I'd prefer using higher-order functions over explicit nested loops anyway, but that doesn't mean I want to translate someone's working algorithm into that style just to insert some Hy macros. |
@hylang/core opinions? Might be a good idea for the cleanup |
I'm -1 on return, but let's open a bug and discuss. Basically, I'm worried On Fri, Jul 24, 2015 at 11:02 AM, Morten Linderud [email protected]
:wq |
I'm also -1 on return. Mixing explicit and implicit returns would be confusing, in my opinion. |
I really don't think explicit returns are any more confusing than |
I feel pretty strongly that Hy functions really ought to have multiple exits, because this is something Python already does, and "We're still Python(TM).". After re-reading my last comment I had another idea. While I have absolutely no problem with mixing implicit and explicit returns, if that's the main sticking point preventing Hy from having multiple exit capability then, then why not offer both, but cleanly separate them to avoid any mixing? We could have Unlike Python, the One complaint I would have with this arrangement is that if we ideally want to prefer and encourage the implicit forms in Hy code, then between |
I'm also -1 on return. I really like building code where last value of function is returned, without having to have |
I think a neat idea would be to have metadata inside functions. Clojure (defn function [a b c]
"Function with explicit return"
{:return True}
(return [a b c])) Thoughts? On Fri, Jul 24, 2015 at 01:49:09PM -0700, Tuukka Turto wrote:
|
Metadata sounds like a interesting approach, if we indeed want to have explicit return statements. We wouldn't have to have multiple different forms for almost same thing. Just have to make sure, that is somebody for some funky reason wants to return a dict |
The line could be done before a comment or something. It's a suggestion, syntax isn't that important yet. |
I am generally opposed to having multiple forms for almost the same thing, at least in the core. Adding new forms is easy with macros. Subtracting cruft, not so much. But I do think it's okay in this case because Python already has
Me too, but in neither of my proposals would you lose this ability.
One can always work around such cases, but that doesn't mean we should have to. Writing new Hy from scratch is one thing, but this commonly comes up when translating existing Python into Hy. For most of Python this is easy, but it's a pain to rewrite the flow so there's only one exit. Python has no goto, and no labeled break--even though it's helpful for nested loops. I think the main argument for not adding this to Python is that you can break out if any amount of nesting with a return. So that's how it's done. But in Hy I can't even do that. The only thing left in Hy to penetrate deep nesting is to raise an exception.
If that's the only way I get multiple exits, I can live with that, but I still like either of my proposals better than this. Metadata has to live somewhere. More runtime overhead I suppose. Python already allows getattr/setattr for functions, so you can store metadata that way. It seems like a better, more Pythonic approach than tacking on a new Clojure-style metadata system. |
My main objection is not ascetic. Two ways to do something is something I'd
|
Yeah no. That's just horrible. |
@ez47 your attitude is entirely unwelcome and that you're not constructively adding to the conversation.
Is not appropriate. I also feel like these comments are not adding any signal to this bug. |
Locking this issue. Folks can prod me about this but I'm not enjoying the way this went. |
Can this be closed now? Evidently, this did not go well... |
We may want to reevaluate whether an explicit |
@algernon Same here. I'm indifferent either way. In Lisp languages, explicit returna are rarely used anyway, since you break up problems into smaller functions. |
Thus spake @paultag:
Or as stated in the Zen of Python:
If you're willing to break this rule, you get Perl. I get it. We should be very reluctant to add feature bloat, and should remove as much cruft as we can given this rare opportunity to break API. But don't forget, Hy is a Lisp. There's a lesson we've learned from the history of Scheme: the users will build what they need (using macros if necessary!) when the language doesn't have it--in a myriad of incompatible ways! There should be one-- and preferably only one --obvious way to do it. Zero is not one either. I think we should be very cautious about deciding to diverge from Python itself. We're dependent on Python. Python does add features from time to time--features that may depend on existing Python syntax, like If Python gets too far past us, Hy becomes more and more obsolete as new software is written that depends on these features that Hy can't use. Why use Hy at all when we already have Common Lisp, Scheme, and Clojure? The main reason: Hy is a Lisp that can work with Python's libraries as easily as its own. Hy must be able to do anything Python can to remain relevant. Anything Python can do that Hy can't do is a reason not to use it. Sometimes it only takes one good reason. Hy doesn't have a big enough ecosystem to compete on its own. Those are the principles. I'm less certain about the solution, but I'm open to ideas. My best idea so far: Add a
It's a little troubling that the special-case syntax |
@gilch Huh...That's an interesting idea. I'm personally torn. On one hand, implicit returns are awesome. On the other hand, they do have problems like you said. One idea could be to make returns explicit inside a generator and make a clear distinction via |
Implicit returns are great in my opinion and most of the time explicit (defn add [a b]
(+ a b))
vs.
(defn add [a b]
(return (+ a b))) However, there are cases where explicit return is really useful (for example, returning a value from inside of a If we add |
That's pretty much what I suggested before with different names, though to be clear, the explicit-return form would still allow Python to implicitly return |
What I tried to explain is that I think it would be good idea to let But @gilch has an interesting point about how |
Another option: Keep the implicit tail return, but modify the compiler to suppress the It's not that confusing; other languages (like Rust) have both explicit and implicit returns. I don't think an optional explicit |
I like this latest proposal. |
👍 for @gilch's latest idea! |
Three's a quorum/three's a veto. Unless someone has a better idea, we can push this through. But how exactly is this supposed to compile? I don't think Hy has ever had a (defn foo [x]
(if x
pass
"spam")) I think this is a sensible output: def foo(x):
if x:
pass
else:
return 'spam' But, given the way Hy already works it might be easier to do this: def foo(x):
if x:
pass
_hy_anon_var_1 = None
else:
_hy_anon_var_1 = 'spam'
return _hy_anon_var_1 But we still need to suppress the return when (defn foo [x]
(if x
pass
pass)) def foo(x):
if x:
pass
_hy_anon_var_1 = None
else:
pass
_hy_anon_var_1 = None Now we have a wasted assignment. Hy already seems to do that though. |
I'm thinking of the simple approach to this, which I don't think has been mentioned yet: add a |
Heresy? But maybe we should provide:
The text was updated successfully, but these errors were encountered: