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);
…