Fan

 

final class

sys::Func

sys::Obj
  sys::Func
//
// Copyright (c) 2007, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   9 Jul 07  Brian Frank  Split from Method
//

**
** Func models an executable subroutine.  Functions are typed by a
** formal parameter list and return value (or Void if no return).
** Functions are typically defined as method slots on a type, but
** may also be defined via functional programming constructs such
** closures and the '&' operator.
**
** An immutable function is guaranteed to not capture any
** state from its thread, and is safe to execute on other threads.
** The compiler marks functions as immutable based on the following
** analysis:
**   - static methods are always automatically immutable
**   - instance methods on a const class are immutable
**   - instance methods on a non-const class are never immutable
**   - closures which don't capture any variables from their
**     scope are automatically immutable
**   - curried functions which only capture const variables
**     from their scope are automatically immutable
**
** See `docLang::Functions` for details.
**
final class Func
{

//////////////////////////////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////////////////////////////

  **
  ** Private constructor.
  **
  private new make()

//////////////////////////////////////////////////////////////////////////
// Signature
//////////////////////////////////////////////////////////////////////////

  **
  ** Type returned by the function or sys::Void if no return value.
  **
  Type returns()

  **
  ** Get the formal parameters of the function.
  **
  Param[] params()

  **
  ** Return the associated method if this function implements a
  ** method slot.  If this function a is curried method using the
  ** "&" operator method call syntax, it will return the associated
  ** method.  Otherwise return 'null'.
  **
  ** Examples:
  **   f := Int#plus.func
  **   f.method           =>  sys::Int.plus
  **   (&10.plus).method  =>  sys::Int.plus
  **   (&f(10)).method    =>  null
  **
  Method? method()

//////////////////////////////////////////////////////////////////////////
// Reflection
//////////////////////////////////////////////////////////////////////////

  **
  ** Dynamically invoke this function with the specified arguments and return
  ** the result.  If the function has Void return type, then null is returned.
  ** The argument list must match the number and type of required parameters.
  ** If this function represents an instance method (not static and not a
  ** constructor) then the first argument must be the target object.  If the
  ** function supports default parameters, omit arguments to use the defaults.
  ** It is permissible to pass more arguments then the number of method
  ** parameters - the additional arguments are ignored.  If no arguments are
  ** required, you may pass null for args.
  **
  virtual R callList(Obj?[]? args)

  **
  ** Convenience for dynamically invoking an instance method with
  ** specified target and arguments.  If this method maps to an
  ** instance method, then it is semantically equivalent to
  ** 'callList([target, args[0], args[1] ...])'.  Throw UnsupportedErr
  ** if called on a function which is not an instance method.
  **
  virtual R callOn(Obj? target, Obj?[]? args)

  **
  ** Optimized convenience for `callList` for zero to eight parameters.
  **
  virtual R call(A a := null, B b := null, C c := null, D d := null,
                 E e := null, F f := null, G g := null, H h := null)

  **
  ** Perform a functional curry by binding the specified
  ** arguments to this function's parameters.  Return a new
  ** function which takes the remaining unbound parameters.
  ** The '&' operator is used as a shortcut for currying.
  **
  Func curry(Obj?[] args)

  **
  ** Return a new function which wraps this function but with
  ** a different reflective type signature.  No verification is
  ** done that this function actually conforms to new signature.
  ** Throw ArgErr if 't' isn't a parameterized function type.
  **
  ** Examples:
  **   f := |a,b->Obj| { "$a, $b" }
  **   g := f.retype(|Int,Int->Str|#)
  **   f.type  =>  |Obj?,Obj?->Obj|
  **   g.type  =>  |Int,Int->Str|
  **
  Func retype(Type t)

  **
  ** If this function is immutable then return this,
  ** otherwise throw NotImmutableErr.
  **
  Func toImmutable()

}