Home > Back-end >  Recommended way to handle callbacks in libraries
Recommended way to handle callbacks in libraries

Time:06-19

I am writing a small parsing library and I would like to let users pass a callback function to process items as they get parsed instead of waiting for the end of the input.

My current (naive) solution is something like:

parse(Input, Callback) ->
  parse(Input, <<>>, Callback).

parse(<<>>, Item, Callback) ->
  Callback(Item);

parse(<<$\n, Rest/binary>>, Item, Callback) ->
  Callback(Item),
  parse(Rest, <<>>, Callback);

parse(<<C/utf8, Rest/binary>>, Item, Callback) ->
  .parse(Rest, <<Item/binary, C/utf8>>, Callback).

Which is then called in the application/module this way:

my_lib:parse(Input, fun do_something/1).

From my understanding of the efficiency guide, this shouldn't be much slower than local calls since:

Calling or applying a fun (Fun(), apply(Fun, [])) is just a little slower than external calls.

When looking at code from some OTP behaviors or applications, passing a Module, Function and Arguments seems to be preferred. Is there any particular reason for that?

Unfortunately, I don't have enough experience to form an option on the usability side of the question and I would like to know the following:

From a usability point of view what is currently the preferred method for libraries to allow users to pass callback functions.

CodePudding user response:

I'm not sure about performance/efficiency, but for usability/maintainability it might be better for you to define your own behaviour, like…

-module parser.
-export [parse/2].

-callback parse_item(binary()) -> term().

-spec parse(binary(), module()) -> term().
parse(Input, CallbackModule) ->
  parse(Input, <<>>, CallbackModule).

parse(<<>>, Item, CallbackModule) ->
  CallbackModule:parse_item(Item);

…
  • Related