Explicitly Calling Return in a Function or Not

Explicitly calling return in a function or not

Question was: Why is not (explicitly) calling return faster or better, and thus preferable?

There is no statement in R documentation making such an assumption.

The main page ?'function' says:

function( arglist ) expr
return(value)

Is it faster without calling return?

Both function() and return() are primitive functions and the function() itself returns last evaluated value even without including return() function.

Calling return() as .Primitive('return') with that last value as an argument will do the same job but needs one call more. So that this (often) unnecessary .Primitive('return') call can draw additional resources.
Simple measurement however shows that the resulting difference is very small and thus can not be the reason for not using explicit return. The following plot is created from data selected this way:

bench_nor2 <- function(x,repeats) { system.time(rep(
# without explicit return
(function(x) vector(length=x,mode="numeric"))(x)
,repeats)) }

bench_ret2 <- function(x,repeats) { system.time(rep(
# with explicit return
(function(x) return(vector(length=x,mode="numeric")))(x)
,repeats)) }

maxlen <- 1000
reps <- 10000
along <- seq(from=1,to=maxlen,by=5)
ret <- sapply(along,FUN=bench_ret2,repeats=reps)
nor <- sapply(along,FUN=bench_nor2,repeats=reps)
res <- data.frame(N=along,ELAPSED_RET=ret["elapsed",],ELAPSED_NOR=nor["elapsed",])

# res object is then visualized
# R version 2.15

Function elapsed time comparison

The picture above may slightly difffer on your platform.
Based on measured data, the size of returned object is not causing any difference, the number of repeats (even if scaled up) makes just a very small difference, which in real word with real data and real algorithm could not be counted or make your script run faster.

Is it better without calling return?

Return is good tool for clearly designing "leaves" of code where the routine should end, jump out of the function and return value.

# here without calling .Primitive('return')
> (function() {10;20;30;40})()
[1] 40
# here with .Primitive('return')
> (function() {10;20;30;40;return(40)})()
[1] 40
# here return terminates flow
> (function() {10;20;return();30;40})()
NULL
> (function() {10;20;return(25);30;40})()
[1] 25
>

It depends on strategy and programming style of the programmer what style he use, he can use no return() as it is not required.

R core programmers uses both approaches ie. with and without explicit return() as it is possible to find in sources of 'base' functions.

Many times only return() is used (no argument) returning NULL in cases to conditially stop the function.

It is not clear if it is better or not as standard user or analyst using R can not see the real difference.

My opinion is that the question should be: Is there any danger in using explicit return coming from R implementation?

Or, maybe better, user writing function code should always ask: What is the effect in not using explicit return (or placing object to be returned as last leaf of code branch) in the function code?

Does every Javascript function have to return a value?

The short answer is no.

The real answer is yes: the JS engine has to be notified that some function has finished its business, which is done by the function returning something. This is also why, instead of "finished", a function is said to "have returned".

A function that lacks an explicit return statement will return undefined, like a C(++) function that has no return value is said (and its signature reflects this) to return void:

void noReturn()//return type void
{
printf("%d\n", 123);
return;//return nothing, can be left out, too
}

//in JS:
function noReturn()
{
console.log('123');//or evil document.write
return undefined;//<-- write it or not, the result is the same
return;//<-- same as return undefined
}

Also, in JS, like in most every language, you're free to simply ignore the return value of a function, which is done an awful lot:

(function()
{
console.log('this function in an IIFE will return undefined, but we don\'t care');
}());
//this expression evaluates to:
(undefined);//but we don't care

At some very low level, the return is translated into some sort of jump. If a function really returned nothing at all, there would be no way of knowing what and when to call the next function, or to call event handlers and the like.

So to recap: No, a JS function needn't return anything as far as your code goes. But as far as the JS engines are concerned: a function always returns something, be it explicitly via a return statement, or implicitly. If a function returns implicitly, its return value will always be undefined.

is it possible to not return anything from a function in python?

Functions always return something (at least None, when no return-statement was reached during execution and the end of the function is reached).

Another case is when they are interrupted by exceptions.
In this case exception handling will "dominate over the stack" and you will return to the appropriate except or get some nasty error :)

Regarding your problem I must say there are two possibilities:
Either you have something to return or you do not have.

  • If you have something to return then do so, if not then don't.
  • If you rely on something being returned that has a certain type but you cannot return anything meaningful of this type then None will tell the caller that this was the case (
    There is no better way to tell the caller that "nothing" is returned then by None, so check for it and you will be fine)

function return in R programming language

  1. return is the explicite way to exit a function and set the value that shall be returned. The advantage is that you can use it anywhere in your function.

  2. If there is no explicit return statement R will return the value of the last evaluated expression

  3. returnValueis only defined in a debugging context. The manual states:

the experimental returnValue() function may be called to obtain the
value about to be returned by the function. Calling this function in
other circumstances will give undefined results.

In other words, you shouldn't use that except in the context of on.exit. It does not even work when you try this.

justReturnValue <- function(){
returnValue('returnValue')
2
}

This function will return 2, not "returnValue". What happened in your example is nothing more than the second approach. R evaluates the last statement which is returnValue() and returns exactly that.

If you use solution 1 or 2 is up to you. I personally prefer the explicit way because I believe it makes the code clearer. But that is more a matter of opinion.

What does it mean when a function does not return a value?

The potential effects of a function include:

  • Returning a value.
  • Modifying an object, including either objects the function can access through pointers or objects with external linkage.
  • Accessing a volatile object, as above.1
  • Modifying a file (a stream).

So, if a function does not return a value, it can still modify an object, as in:

void SetState(SomeStructure *S, int Value)
{
S->State = Value;
}

or it can modify a stream:

void PrintValue(FILE *Stream, int Value)
{
fprintf(Stream, "%d", Value);
}

You can tell the compiler that a function does not return a value by declaring it with return type void. However, the C standard also permits functions with non-void return types not to return a value. For example, you can have a function that sets or gets a value depending upon a command parameter:

int AccessState(int Command, SomeStructure *S,...)
{
switch (Command)
{
case 0: // Get the state.
return S->Value;
case 1: // Set the state from the optional int parameter following S.
va_list ap;
va_start(ap, S);
S->Value = va_arg(S, int);
va_end(ap);
break;
}
}

In this case, there is no way to tell the compiler that the function sometimes does not return a value, but you do not need to. However, you should tell humans that use and read the code that the function sometimes does and sometimes does not return a value with clear documentation in comments or elsewhere.

Footnote

1 Accessing a volatile object is one way for C programs to do things outside the C standard, such as sending commands or data to physical devices.

Return statement in expression to be used as function body

Regardless of my recommendation not to use return in R except when early access is explicitly required, the following should work:

memoize = function (cache_filename, expr) {
if (file.exists(cache_filename)) {
message('reading ', cache_filename)
readRDS(cache_filename)
} else {
message(cache_filename, ' not found, rerunning computation')
f = local(function () NULL, envir = .GlobalEnv)
body(f) = substitute(expr)
result = f()
saveRDS(result, cache_filename)
result
}
}

Note in particular that using do.call(f, list()) isn’t necessary and doesn’t really make sense: it’s a regular function, just call it using f().

What your current solution does is actually quite interesting: it evaluates expr at the point of use and assigns the result to the function body of f. In fact, this only happens to work when the result is a simple R value, not when it’s a complex object. And in that case you don’t need the nested function at all, you can evaluate expr on its own, and this is in fact a fairly common pattern (used, for example, in the implementations of try and tryCatch!). In other words, the following would be an idiomatic implementation (but doesn’t support using control flow such as return():

memoize = function (cache_filename, expr) {
if (file.exists(cache_filename)) {
message('reading ', cache_filename)
readRDS(cache_filename)
} else {
message(cache_filename, ' not found, rerunning computation')
result = expr
saveRDS(result, cache_filename)
result
}
}

Why does is.recursive return TRUE for a function

A function actually is a recursive structure, I think just for safety reasons they decided not to provide a default method for the [[ function. You can get the more list-like representation with as.list()

str(as.list(mean))
# $ x : symbol
# $ ...: symbol
# $ : language UseMethod("mean")

So what you get is a list for your parameters and then the function body. If you want to get the body directly you can do

body(mean)
body(mean)[[1]]

and that does return the body as an expression that you can subset.

So functions are basically stored as lists of lists, therefore they are recursive.



Related Topics



Leave a reply



Submit