Skip to content
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

Add a generic 'no return' value to GAP #829

Closed
wants to merge 1 commit into from

Conversation

ChrisJefferson
Copy link
Contributor

This pull request is an experiment in adding a generic, "no return" value to GAP. This adds a new (currently boolean) value 'NoReturn', and any function which appears to have no return value in fact returns 'NoReturn'.

Here are some examples:

gap> f := function() end;
function(  ) ... end
gap> f();
gap> f() = NoReturn;
true
gap> x := f();
<no return value>
gap> x;
<no return value>
gap> Print(x);
<no return value>
gap> f() = NoReturn

This should make no change to any working GAP code, either run interactively or not. The only difference is if you try to assign the result of a function to a variable when the function doesn't return, previously that was an error, now that variable is assigned NoReturn.

@olexandr-konovalov
Copy link
Member

I am thinking whether it is ok to write

f:=function() return NoReturn end;

or this should be forbidden?

@ChrisJefferson
Copy link
Contributor Author

Obvious bikeshedding:

  • The name: I already don't like it.. maybe NoValue? None would be best, but might already be used by somebody for something else (isn't in GAP or libraries).
  • Should it be a boolean? Could add another TNUM, but is it worthwhile?

@ChrisJefferson
Copy link
Contributor Author

We could forbid returning NoReturn, but (for example) Python allows returning None. We could just say return NoReturn; is the same as return;.

@fingolfin
Copy link
Member

If you forbid returning it, how would that work? Or rather, how could one "use" this return value then? Think of this example:

f := function()
   local x;
   x := Print("x");  # returns nothing, so x = NoReturn
   return x;
end;

Is that allowed or forbidden? If it is allowed, does it return the value NoReturn, or does it return "nothing"? If it is forbidden, does that mean we insert an extra check at every return to raise an error if the return value is equal to NoReturn

I guess this boils down to asking: What is an actual use case of this?

@markuspf
Copy link
Member

I am against making another Boolean value, it's bad enough as it is with true, false, and fail.

I think NoValue is better than NoReturn, even though NoValue is a value. We could call it Void, not sure about None, Empty is out because it has other meaning.

@ChrisJefferson
Copy link
Contributor Author

I think I agree it shouldn't be a boolean, that was just quick for a hack :)

@olexandr-konovalov
Copy link
Member

  1. I mildly against making one more boolean. We are trying to get rid of SuPeRfail, but now want to have another one?

  2. My name choice may be NULL, but I am staying away from the bikeshedding :)

  3. After @fingolfin's example I am confused even more whether return NoReturn; is allowed or forbidden. I am even becoming concerned that wrong code which previously was triggering an error will now silently work:

gap> x := Print("");
Error, Function call: <func> must return a value
not in any function at line 4 of *stdin*

so if one writes a function with several execution branches and will forget to put return into some of them, this may remain unnoticed. Maybe I need to re-read some comments under #464 ...

@ChrisJefferson
Copy link
Contributor Author

I good guide is None in python. You can always write return None;, which means the same thing as Return, or having no return value. Python programmers don't seem to get too upset by it, and copying what they did (if we like it) seems like a good idea.

@olexandr-konovalov
Copy link
Member

olexandr-konovalov commented Jun 16, 2016

Continuing (3) from my comment above: As @fingolfin wrote in #464,

@frankluebeck The reason why I want to make it annoying (and perhaps eventually, forbid it outright) for a function to sometimes return a value, and sometimes not, is precisely the one @stevelinton outlines: A caller has no safe way to figure out which will happen. Of course you can work around that by programming the caller with knowledge of when the called function will behave either way.

Isn't this PR a step in the opposite direction? We now ensure that every function automatically returns a value. This is quite a change. I am not against it, and maybe this would be a good design choice to make early enough. But now even the distinction between procedures and functions for documentation purposes should be adjusted, as otherwise we will not have procedures any more (http://www.gap-system.org/Manuals/doc/ref/chap4.html#X825803DE78251DA6) - perhaps we should then say that procedure returns only this None object, but never anything else.

@fingolfin is right that we need to hear more about use cases. Maybe the answer would be to adjust the code that calls such functions to be tolerant when nothing s returned.

@fingolfin
Copy link
Member

Frank has an alternatve PR #831 with which there is no "real" return value for procedures, but instead, if the "return value" of procedure is assigned to something, that something is implicitly unbound -- this kind of matches the behaviour of Python's None, too.

On the up side, this avoids introducing a special NoValue or None global variable. Also, we can then still claim that procedures return nothing.

On the downside, the problem (? if it is one) that code which previously could trigger an error might now pass (when it shouldn't). However, I think in practice it would still error, just a bit later -- though this might make debugging such problems harder.

@ChrisJefferson
Copy link
Contributor Author

I slightly worry that people might get confused when their variables appear to not take a value when they are assigned the return value of a function. I think that patch is better than this one, so the answer is if it's a good idea in general to make a big change to the language, or just provide a simple extension to CallFuncList and leave everything else alone.

@fingolfin
Copy link
Member

I still like the general idea of replicating Python's None. I do not like the name NoReturn, because it artificially ties this special value to returning something, while in Python, it is perfectly acceptable to assign this value to variables, list entries, etc.; it can be used to unbind things, in effect (at least list entries ...). So, I think None is a better name, esp. because it would be already familiar to people from the Python world.

That said, it feels like a somewhat bigger change to the language than CallListFuncWrap from PR #824 -- in the sense that it might have more ramifications, and cause people to expect things about it... Also, people might use None already in their code (though at least no GAP package seems to do so)

@ChrisJefferson
Copy link
Contributor Author

I think this is too big a change, without sufficient support, so I'm closing it. It will still be here if anyone ever wants it.

@ChrisJefferson ChrisJefferson deleted the noreturn branch June 2, 2017 17:22
@fingolfin fingolfin mentioned this pull request Jun 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants