pike.git / lib / modules / Function.pmod

version» Context lines:

pike.git/lib/modules/Function.pmod:81:   //! @endcode   function(mixed...:function(mixed...:mixed|void)) curry(function f)   {    return lambda(mixed ... args1) {    return lambda(mixed ... args2) {    return f(@args1, @args2);    };    };   }    + //! Partially evaluate a function call. + //! + //! This function returns a function that when called will do the + //! specified argument mapping. It is similar to @[curry], but allows + //! more dynamic changes of the argument evaluation, you can leave the + //! first argument unspecified while setting others, or simply change + //! the argument order. + //! + //! The first argument is the function to be called. + //! + //! All other arguments is either a generic value, which will be sent as-is to the funciton + //! or one of the placeholder values define in [Function.Placeholder], + //! or one of your own implementation (inherit + //! Function.Placeholder.Base and implement the value function.). + //! + //! @example + //! This example returns a funciton that limits the given argument + //! to between 0 and 99. + //! @code + //! import Functio.Placeholder; + //! function clip = Function.bind(limit, 0, arg0, 100); + //! @endcode + class bind(function f, mixed ... bind_args) + { +  protected string _sprintf() { +  return sprintf("Function.bind(%O%{, %O%})",f,bind_args); +  }    -  +  protected mixed `()(mixed ... args) +  { +  array processed = ({}); +  for(int i=0; i<sizeof(bind_args);i++) +  { +  if( objectp(bind_args[i]) && bind_args[i]->_is_placeholder ) +  { +  mixed val = bind_args[i]->value(this,args); +  if( bind_args[i]->_splice ) +  processed += val; +  else +  processed += ({val}); +  } +  else +  processed += ({bind_args[i]}); +  } +  return f(@processed); +  } + } +    //! 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...:mixed) uncurry(function f)
pike.git/lib/modules/Function.pmod:142:   //! @endcode   function composite(function ... f)   {    return lambda(mixed args)    {    for(int i; i<sizeof(f); i++)    args = f[-i-1](args);    return args;    };   } +  +  + //! @module Placeholder + //! + //! Placeholder arguments for Function.bind + object Placeholder = class + { +  class Base +  { +  constant _is_placeholder = true; +  //! @decl mixed value(bind x, array args); +  //! +  //! The function that is called to return the argument value. +  } +  +  class Arg(int num) +  //! Arg(x) returns the value of argument X +  { +  inherit Base; +  protected string _sprintf() { +  return sprintf("arg%d",num); +  } +  +  mixed value(bind x, array args) +  { +  if(num>=sizeof(args) || -num>sizeof(args)) +  error("No argument %d given\n",num); +  return args[num]; +  } +  }; +  +  class Splice(int from, void|int end) +  //! Splice(from) adds all arguments starting with argument number @[from], +  //! optionally ending with end. +  //! Equivalent to @args[from..end] +  { +  inherit Base; +  constant _splice = true; +  array(mixed) value(bind x, array args) +  { +  if( end ) +  return args[from..end]; +  return args[from..]; +  } +  } +  +  //! @decl Arg rest; +  //! Return all arguments not used by any @[Arg] or @[Splice]. +  //! +  //! Unlike @[Splice] this will return non-continous unused arguments. +  //! +  //! @example +  //! This creates a version of call_out that has the function argument as +  //! the last argument +  //! @code +  //! import Function.Placeholder; +  //! Function.bind( call_out, Arg(-1), rest) +  //! @endcode +  object rest = class { +  inherit Base; +  constant _splice = true; +  +  array(mixed) value( bind x, array args ) +  { +  array ret = copy_value(args); +  foreach(x->bind_args, mixed arg) +  { +  if( Program.inherits(arg,Arg) ) +  { +  int a = arg->num; +  ret[a] = UNDEFINED; +  } +  else if( Program.inherits(arg,Splice) ) +  { +  int e = min(arg->end+1,sizeof(args)); +  if( e==1 ) e = sizeof(args); +  for(int i=arg->start; i<e; i++) +  ret[i] = UNDEFINED; +  } +  } +  return ret - ({ UNDEFINED }); +  } +  }(); +  +  //! @decl constant arg0; +  //! @decl constant arg1; +  //! @decl constant arg2; +  //! @decl constant arg3; +  //! @decl constant arg4; +  //! @decl constant arg5; +  //! @decl constant arg6; +  //! @decl constant arg7; +  //! @decl constant arg8; +  //! @decl constant arg9; +  //! @decl constant arg...; +  //! arg<n> will return an instance of @[Arg] that returns the n:th arg. +  //! For convenience for c++11 developers _0, _1 etc also works. +  //! +  //! Note that arg0 is the first argument, not arg1 +  +  class Expr(function value) +  //! Expr(x) returns the result of calling @[x]. +  //! The function will be passed the bind instance and the +  //! list of arguments, in that order. +  //! +  //! Function.Placeholder.arg1 is thus more or less equivalent to +  //! @code Expr(lambda(Function.bind b, array args ){return args[1];}); +  //! (however, @[Function.Placeholder.rest] would not know about this usage) +  { +  inherit Base; +  protected string _sprintf() { +  return sprintf("Expr(%O)",value); +  } +  } +  +  private mapping _cache = ([]); +  mixed `[](string name) +  { +  if( _cache[name] ) +  return _cache[name]; +  mixed tmp; +  if(sscanf(name, "arg%d", tmp) || sscanf(name, "_%d", tmp)) +  return _cache[name] = Arg(tmp); +  return ::`[](name); +  }; + }(); +  +  +