Compiling with If
The reason f1 does not work is that
Block[{a, b}, {a, b} = point; If[t > 0., a*b*Sin[t], 0.]]
evaluates to
If[t > 0., a b Sin[t], 0.]
That happens because If is HoldRest and t > 0. does not evaluate to True or False. When compiled, there are MainEvaluate calls to evaluate a and b, which will give an error if a or b is not a real numeric quantity. So while f1[2.] gives an error, the following
Block[{a, b}, {a, b} = point; f1[2.]]
yields
1.81859
Note what happens if a third argument is supplied to If:
f3 = Compile[{{t, _Real}},
Evaluate[Block[{a, b}, {a, b} = point;
If[t > 0., a*b*Sin[t], 0., -200.]]]]
(* CompiledFunction[{t}, -200., -CompiledCode-] *)
The value of f3[-1.], f3[2.] etc. will always be -200.
Compiling with Piecewise
While Piecewise is HoldAll, it evaluates each piece in turn until one of the conditions is True. What actually seems to happen is a little complicated and not completely described in the reference page Piecewise (more below). The behavior of Compile can be understood by the same means as for If:
Block[{a, b}, {a, b} = point; Piecewise[{{a * b * Sin[t], t > 0.}, {0., True}}]]
(* Piecewise[{{2.*Sin[t], t > 0.}}, 0.] *)
The values of a and b are substituted, and this is the expression that is compiled. So in both cases, If and Piecewise, there is not a problem with Compile. The difference is explained by the expression that is compiled.
The behavior of Piecewise:
Why are do values of a, b end up in the Piecewise expression that is the output of Block?
Consider
Piecewise[{{val$1, cond$1},
{val$2, cond$2},
...
]
Each condition cond$n is evaluated in turn. If cond$n evaluates to False, Piecewise proceeds to the next condition. If cond$n does not evaluate to False, then val$n is evaluated; if the condition evaluates to neither True nor False, then the values of val$n and cond$n become part of a Piecewise expression that is returned after evaluation. That is how the values of a and b end up in the output.
Applying this procedure to the OP's f2, we see that a*b*Sin[t] will be evaluated during the evaluation of Piecewise and the values of a and b will replace the variables.
Example: The first condition evaluates to False and x is not incremented by 1. The next evaluates to -3 > a; x is incremented by 10, printed, and the value {2. 10} becomes a value in the final Piecewise expression that is returned. Finally, the last condition is True, so the third value is evaluated; since not all the preceding conditions evaluated to False, a Piecewise expression is returned.
Clear[a, t];
x = 0;
t = -3;
Piecewise[{{Print[x += 1]; {1., x}, t > 0.},
{Print[x += 10]; {2., x}, t > a},
{Print[x += 100]; {3., x}, True}
}]
(* 10 *)
(* 110 *)
(* Piecewise[{{{2., 10}, -3 > a}}, {3., 110}] *)
I might note that Piecewise is described in the reference manual as representing "a piecewise function", but it's not a function in the Mathematica sense: if
f = Piecewise[..]
then f[x] does not evaluate to the value of the piecewise function at x.
That's an explanation of why OP's code behaves the way it does. Your f2 already works the way you expected, but if you'd like another way, then consider this:
point = {1., 2.};
f4 = With[{a = point[[1]], b = point[[2]]},
Compile[{{t, _Real}}, If[t > 0., a*b*Sin[t], 0.]]];
f4[2.]
(* 1.81859 *)
Evaluatebecause in my real code there are some piecewise functions I want to expand before compile, which makes the code run 2x faster in my case. $\endgroup$Pieceswiseas an argument to a function that will return theCompiledFunction? $\endgroup$PiecewiseExpandin place ofEvaluate? $\endgroup$