anchor.diff:  -type(mr_job() :: {Round::pos_integer(),
                      map | reduce,
                      {erlanon | jsanon, binary()},
  -                   Keep::boolean(),
                      Data::[tuple()]}).
   
   -type(generic_job() :: {erlanon | jsanon, binary(), [tuple()]}).
  
positive.code:             start_worker(Source, Workload, {Max, NewWorking, Rest})
      end.
  
  %% actual worker functions
  -spec init_worker(pid_groups:groupname(), job()) -> {ok, pid()}.
  init_worker(DHTNodeGroup, Workload) ->
      Pid = spawn_link(?MODULE, work, [DHTNodeGroup, Workload]),
      {ok, Pid}.
  
  %% do the actual work
  -spec work(pid_groups:groupname(), job()) -> ok.
  work(DHTNodeGroup, {_Round, map, {erlanon, FunBin}, Data}) ->
      %% ?TRACE("worker: should apply ~p to ~p~n", [FunBin, Data]),
  
negative.code: work(DHTNodeGroup, {_Round, map, {jsanon, FunBin}, Data}) ->
      %% ?TRACE("worker: should apply ~p to ~p~n", [FunBin, Data]),
      {ok, VM} = js_driver:new(),
      return(DHTNodeGroup, lists:flatten([apply_js(FunBin, [X], VM) || X <- Data]));
  work(DHTNodeGroup, {_Round, reduce, {jsanon, FunBin}, Data}) ->
      {ok, VM} = js_driver:new(),
      return(DHTNodeGroup, apply_js(FunBin, [Data], VM)).
  
  %% @doc applies Fun with Args.
  -spec apply_erl(Fun::fun((Arg::term()) -> Res::A), Args::term()) -> A.
  apply_erl(Fun, Data) ->
      Fun(Data).
  
  %% @doc applies Fun with Args withing JSVM.
  -spec apply_js(Fun::binary(), Args::[term()], JSVM::port()) -> term().
  apply_js(FunBin, Data, VM) ->
      AutoJS = define_auto_js(FunBin, Data),
      {ok, Result} = js:eval(VM, AutoJS),
      Result.
  
  %% @doc create a self calling JS function.
  %%      takes a anonymous JS function (as a binary string) and a list of
  %%      arguments and returns a self calling JS (`function(arg) {...}(args)') 
  %%      function as a binary string.
  -spec define_auto_js(Fun::binary(), [term()]) -> binary().
  define_auto_js(FunBin, Args) ->
      EncodedArgs = encode_args(Args, []),
      iolist_to_binary([FunBin, "(", EncodedArgs, ")"]).
  
  %% @doc build argument list for JS function.
  %%      takes a list of terms and returns an iolist of the encoded (mochijson2)
  %%      terms with commas in between.
  -spec encode_args([term()], [term()]) -> term().
  encode_args([], Acc) ->
      lists:reverse(Acc);
  encode_args([H | []], Acc) ->
      encode_args([], [js_mochijson2:encode(H) | Acc]);
  encode_args([H | T], Acc) ->
      encode_args(T, [[js_mochijson2:encode(H), ","] | Acc]).
  
  %% send results back to wpool
  -spec return(pid_groups:groupname(), any()) -> ok.
  