class_docstr: Backend program for evaluating a symbolic funsor expression.
  
  Programs depend on the funsor library only via ``funsor.ops`` and op
  registrations; program evaluation does not involve funsor interpretation or
  rewriting. Programs can be pickled and unpickled.
  
  :param iterable expr: A list of built-in constants (leaves).
  :param iterable inputs: A list of string names of program inputs (leaves).
  :param iterable operations: A list of program operations defining
      non-leaf nodes in the program dag. Each operations is a tuple ``(op,
      arg_ids)`` where op is a funsor op and ``arg_ids`` is a tuple of
      positions of values, starting from zero and counting: constants,
      inputs, and operation outputs.
class_docstr_tok: ["Backend","program","for","evaluating","a","symbolic","funsor","expression",".","Programs","depend","on","the","funsor","library","only","via","``","funsor.ops","``","and","op","registrations",";","program","evaluation","does","not","involve","funsor","interpretation","or","rewriting",".","Programs","can","be","pickled","and","unpickled",".",":","param","iterable","expr",":","A","list","of","built-in","constants","(","leaves",")",".",":","param","iterable","inputs",":","A","list","of","string","names","of","program","inputs","(","leaves",")",".",":","param","iterable","operations",":","A","list","of","program","operations","defining","non-leaf","nodes","in","the","program","dag",".","Each","operations","is","a","tuple","``","(","op",",","arg_ids",")","``","where","op","is","a","funsor","op","and","``","arg_ids","``","is","a","tuple","of","positions","of","values",",","starting","from","zero","and","counting",":","constants",",","inputs",",","and","operation","outputs","."]
code: def __call__(self, **kwargs):
      set_backend(self.backend)
  
      # Initialize environment with constants.
      env = list(self.constants)
  
      # Read inputs from kwargs.
      for name in self.inputs:
          value = kwargs.pop(name, None)
          if value is None:
              raise ValueError(f"Missing kwarg: {repr(name)}")
          env.append(value)
      if kwargs:
          raise ValueError(f"Unrecognized kwargs: {set(kwargs)}")
  
      # Sequentially compute ops.
      for op, arg_ids in self.operations:
          args = tuple(env[i] for i in arg_ids)
          value = op(*args)
          env.append(value)
  
      result = env[-1]
      return result
  
imports: from funsor.util import get_backend, set_backend
label_desc: Use image node_id 2 for calling the OpProgram obj's underlying member method code with example usage: obj.__call__() and returns: result