2

Potential duplicate, but doesn't seem to solve my problem: Using patterns in pure functions

I have a function that returns an InterpolatingFunction, and it works exactly the way I needed for passing to NIntegrate etc.: if I pass on a symbolic argument, the function returns itself; if the argument is numeric, it evaluates and gives a number.

func := Module[{...}, ... (y /. First@NDSolve[{y[1] == 1, y'[x] == x}, y, {x, -1, 1}])]
func[x] (* gives InterpolatingFunction[(-1. 1.),<>](x) *)
func[0.5] (* gives 0.625 *) 

I need a slightly modified behavior: the returned function should return 0 if outside the range instead of attempting to interpolate. Seems easy enough:

func := Module[{interpolation,...}, ...
        interpolation = (y /. First@NDSolve[{y[1] == 1, y'[x] == x}, y, {x, -1, 1}]);
        Function[x,If[Not@IntervalMemberQ[Interval[interpolation[[1, 1]]], x], 0, 
                interpolation[x]]]]
func[0.5] (* gives 0.625 *) 
func[2] (* gives 0 since it's outside the interpolation interval *)
func[x] (* gives 0!! *)

How can one mimic the behavior of InterpolatingFunction such that func[x] for non-numeric x gives something like Function[<>](x) instead?

polyglot
  • 775
  • 8
  • 11
  • From the documentation of Function: "Function][params, body, {attr_1, attr_2, ...}] represents a pure function that is to be treated as having attributes attr_i for the purpose of evaluation". – m_goldberg May 20 '14 at 20:36

1 Answers1

3

This is not neat at all but it gives the bahaviour you need:

ClearAll[func];
func := Module[{interpolation},
  interpolation = (y /. First@NDSolve[{y[1] == 1, y'[x] == x}, y, {x, -1, 1}]);
  Function[x,
    Which[
      ! NumericQ[x], interpolation[x], 
      TrueQ[LessEqual[#, x, #2] & @@ interpolation[[1, 1]]], interpolation[x],
      True, 0]]]

func[0.5] 
func[2] 
func[x] 
0.625
0
InterpolatingFunction[{{-1.,1.}},<>][x]
Kuba
  • 136,707
  • 13
  • 279
  • 740