docs: function _parse_function_predicate(ObjType, q, def_op, o, ret_type, traits) {
  	debug.assert(o).is('array');
  
  	ret_type = ret_type || 'boolean';
  
  	var func = ARRAY(o).find(is.func);
  
  	debug.assert(func).is('function');
  
  	var i = o.indexOf(func);
  	debug.assert(i).is('number');
  
  	var input_nopg_keys = o.slice(0, i);
  	var js_input_params = o.slice(i+1);
  
  	debug.assert(input_nopg_keys).is('array');
  	debug.assert(js_input_params).is('array');
  
  	//debug.log('input_nopg_keys = ', input_nopg_keys);
  	//debug.log('func = ', func);
  	//debug.log('js_input_params = ', js_input_params);
  
  	var _parse_predicate_key_epoch = FUNCTION(_parse_predicate_key).curry(ObjType, {'traits': traits, 'epoch':true});
  	var input_pg_keys = ARRAY(input_nopg_keys).map(_parse_predicate_key_epoch);
  
  	var pg_items = input_pg_keys.map(function(i) { return i.getString(); }).valueOf();
  	var pg_params = input_pg_keys.map(function(i) { return i.getParams(); }).reduce(function(a, b) { return a.concat(b); });
  
  	debug.assert(pg_items).is('array');
  	debug.assert(pg_params).is('array');
  
  	//debug.log('input_pg_keys = ', input_pg_keys);
  
  	//var n = arg_params.length;
  	//arg_params.push(JSON.stringify(FUNCTION(func).stringify()));
  	//arg_params.push(JSON.stringify(js_input_params));
  
  	var call_func = 'nopg.call_func(array_to_json(ARRAY['+pg_items.join(', ')+"]), $::json, $::json)";
  
  	var type_cast = parse_predicate_pgcast_by_type(ret_type);
  
  	return new Predicate(type_cast(call_func), pg_params.concat( [JSON.stringify(FUNCTION(func).stringify()), JSON.stringify(js_input_params)] ));
  }