Unexpected behavior of Compile, Return and ;

10

1

Could somebody explain why

test = Compile[{{x}},
      Return[x];
    ];
test[0.]

returns

Compile::cret: "The type of return values in Return[x]; are different. Evaluation will use the uncompiled function. "

while

test = Compile[{{x}},
      Return[x]
    ];
test[0.]

works as expected? Notice that the only difference is the semicolon at the end of Return.

Ajasja

Posted 2012-06-22T07:09:47.947

Reputation: 13 114

Answers

8

This question is closely related. See ruebenkoe's answer in particular.

I think you get this behaviour because:

  1. Compiled code is typed, so Compile can only return one type of result (and the type needs to be a number, not a symbol)

  2. When Compile analyses the code, it perceives it as something that returns Null. fun[x]; is equivalent to fun[x]; Null. So even though you have a single Return which will always break out of the function (returning a number), Compile is not able to realize this.

    Further proof that this is the case is that the following compiles fine:

    test = Compile[{{x}}, Return[x]; 0.0]
    

Szabolcs

Posted 2012-06-22T07:09:47.947

Reputation: 213 047

@Ajasja f = Function[x, Return[x, CompoundExpression]]; f[0.]. And there are no bugs in Compile, only undocumented features. ;) – Oleksandr R. – 2014-04-17T21:56:36.127

Aha (I suspected as much), but then I would argue this is a bug in Compile. Since the return value is x and not 0.0. So it does not matter what comes after return. – Ajasja – 2012-06-22T08:07:47.080

Also this is strange as well f = Function[x, Return[x];]; f[0.] – Ajasja – 2012-06-22T08:08:12.167

test = Compile[{{x}}, x]; on the other hand seems to work fine. – image_doctor – 2012-06-22T08:20:31.757

@image_doctor Yes, because in that case there return type can clearly only be one thing---a number. – Szabolcs – 2012-06-22T08:24:49.577

@Ajasja In a slightly different situation such as If[condition, Return[x]]; 0.0 it does matter what comes after return. My suspicion is that it's not so easy for the compiler to tell these cases apart. It's not smart enough to be able to analyse your example and conclude that everything after the Return can be ignored. All it sees is that there are two potential exit points: one in Return and one after. They have different return types, and in fact one of them has an illegal return type (a symbol). – Szabolcs – 2012-06-22T08:27:41.650

@Ajasja Re your second comment: Return behaves differently in and outside Compile ... and I don't understand it entirely outside Compile ... – Szabolcs – 2012-06-22T08:29:59.540

@Szabolcs This seems to behave as though there is an implicit return in compiled functions, so the use of Return is superfluous? – image_doctor – 2012-06-22T08:30:38.900

@image_doctor: "the use of Return[] is superfluous?" - not really, you might for instance want to break out of a loop within a compiled function with Return[], for example. – J. M.'s ennui – 2012-06-22T08:34:54.270

@image_doctor Isn't there an implicit return in every function? The last value in a CompoundExpression is returned. Am I misunderstanding you? Too see what a compiled function is made of precisely, use <<CompiledFunctionTools` then CompilePrint. In the low level instruction meant for the MVM there is indeed an explicit return. – Szabolcs – 2012-06-22T08:35:33.247

@J.M. ...Loop, functionally I do not understand ;) – image_doctor – 2012-06-22T08:36:32.353

@Szabolcs Yes, that was the point I was trying to form, I think. – image_doctor – 2012-06-22T08:39:08.277

@Szabolcs More explicitly, there is an implicit Return at the end of the function ( in this case returning Null because of the ;) and when you code a second Return which returns a number the two types do not match. – image_doctor – 2012-06-22T08:46:44.240

@image_doctor Yes, just like with any other Mathematica function, for example f[] := (1;) also returns Null (even if it's not printed) – Szabolcs – 2012-06-22T08:49:49.093

@Szabolcs Is the implication that Null is not a number, so a compiled function can in fact return a type which is not a number ? – image_doctor – 2012-06-22T08:53:31.123

@Szabolcs "My suspicion is that it's not so easy for the compiler to tell these cases apart." I agree, it's not easy, but probably not impossible, this is why I would call this behaviour a bug. (But I'm very biased after one hour of wasted time wondering why my function does not compile :) – Ajasja – 2012-06-22T09:01:43.783