1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
120
  
121
  
122
  
123
  
124
  
125
  
126
  
127
  
128
  
129
  
130
  
131
  
132
  
133
  
134
  
#pike __REAL_VERSION__ 
 
constant defined = __builtin.function_defined; 
 
//! Calls the given function with the @[args] array plus the optional 
//! extra arguments as its arguments and returns the result. 
//! 
//! Most useful in conjunction with @[map], and particularly in combination 
//! with @[sscanf] with @expr{"...%{...%}..."@} scan strings (which indeed 
//! was what it was invented for in the first place). 
//! 
//! @param args 
//!  The first arguments the function @[f] expects. 
//! @param f 
//!  The function to apply the arguments on. 
//! @param extra 
//!  Optional extra arguments to send to @[f]. 
//! @returns 
//!  Whatever the supplied function @[f] returns. 
//! 
//! @example 
//! @code 
//!   class Product(string name, string version) 
//!   { 
//!     string _sprintf() 
//!     { 
//!       return sprintf("Product(%s/%s)", name, version); 
//!     } 
//!   } 
//!   map(({ ({ "pike",   "7.1.11" }), 
//!          ({ "whitefish", "0.1" }) }), 
//!       Function.splice_call, Product); 
//!   ({ /* 2 elements */ 
//!    Product(pike/7.1.11), 
//!    Product(whitefish/0.1) 
//!   }) 
//! @endcode 
mixed splice_call(array args, function f, mixed|void ... extra) 
{ 
  return f(@args, @extra); 
} 
 
 
//! The dreaded fixpoint combinator "Y". 
//! 
//! The Y combinator is useful when writing recursive lambdas.  It 
//! converts a lambda that expects a self-reference as its first argument 
//! into one which can be called without this argument. 
//! 
//! @example 
//! This example creates a lambda that computes the faculty function. 
//! @code 
//!   Function.Y(lambda(function f, int n) { return n>1? n*f(n-1) : 1; }) 
//! @endcode 
function Y(function f) 
{ 
  return lambda(function p) { 
           return lambda(mixed ... args) { 
                    return f(p(p), @args); 
                  }; 
         } (lambda(function p) { 
              return lambda(mixed ... args) { 
                       return f(p(p), @args); 
                     }; 
            }); 
} 
 
 
//! Partially evaluate a function call. 
//! 
//! This function allows N parameters to be given to a function taking 
//! M parameters (N<=M), yielding a new function taking M-N parameters. 
//! 
//! What is actually returned from this function is a function taking N 
//! parameters, and returning a function taking M-N parameters. 
//! 
//! @example 
//! This example creates a function adding 7 to its argument. 
//! @code 
//!   Function.curry(`+)(7) 
//! @endcode 
function(mixed...:function(mixed...:mixed|void)) curry(function f) 
{ 
  return lambda(mixed ... args1) { 
           return lambda(mixed ... args2) { 
                    return f(@args1, @args2); 
                  }; 
         }; 
} 
 
 
//! This function, given a function taking N parameters, returns a new 
//! function taking N+1 parameters. The first argument will be 
//! ignored. 
//! 
//! @example 
//! @code 
//!  >  Function.uncurry(`+)(7,2,3) 
//!  Result: 5 
//! @endcode 
function(mixed...:function(mixed...:mixed|void)) uncurry(function f) 
{ 
  return lambda(mixed ... args1) { 
       return f(@args1[1..]); 
   }; 
} 
 
//! Call a callback function, but send throws from the callback 
//! function (ie, errors) to master()->handle_error. 
//! Also accepts if f is zero (0) without error. 
//! 
//! @example 
//! @code 
//!   Functions.call_callback(the_callback,some,arguments); 
//! @endcode 
//! equals  
//! @code 
//!   { 
//!      mixed err=catch { if (the_callback) the_callback(some,arguments); }; 
//!      if (err) master()->handle_error(err); 
//!   } 
//! @endcode 
//! (Approximately, since call_callback also calls handle_error 
//! if 0 were thrown.) 
void call_callback(function f,mixed ... args) 
{ 
   if (!f) return; 
   mixed err=catch { f(@args); return; }; 
   handle_error(err); 
} 
 
private function handle_error = master()->handle_error;