Horus is a library that extracts an anonymous function's code as well as the code of the all the functions it calls, and creates a standalone version of it in a new module at runtime.
The goal is to have a storable and transferable function which does not depend on the availability of the modules that defined it or were called.
To achieve that goal, Horus extracts the assembly code of the anonymous function, watches all calls it does and recursively extracts the assembly code of other called functions. When complete, it creates a standalone Erlang module based on it. This module can be stored, transfered to another Erlang node and executed anywhere without the presence of the initial anonymous function's module.
If the extracted function calls directly or indirectly modules from the erts
,
kernel
or stdlib
applications, the called functions are not extracted.
That's ok because the behavior of Erlang/OTP modules rarely changes and they
will be available. Therefore, there is little value in extracting that code.
While processing the assembly instructions and watching function calls, Horus can use callbacks provided by the caller to determine if instructions and calls are allowed or denied.
Horus is still under active development and should be considered Alpha at this stage.
- A short tutorial in the Getting started section below
- Documentation and API reference
Add Horus as a dependency of your project:
Using Rebar:
%% In rebar.config
{deps, [{horus, "0.3.1"}]}.
Using Erlang.mk:
# In your Makefile
DEPS += horus
dep_horus = hex 0.3.1
Using Mix:
# In mix.exs
defp deps do
[
{:horus, "0.3.1"}
]
end
To extract an anonymous function, use horus:to_standalone_fun/1
:
Fun = fun() ->
do_something_fancy()
end,
StandaloneFun = horus:to_standalone_fun(Fun).
It works with references to regular functions are well:
Log = fun logger:info/2,
StandaloneLog = horus:to_standalone_fun(Log).
Once extracted, the function can be stored as an Erlang binary, or transfered
to a remote Erlang node. You then use horus:exec/2
to execute it:
receive
{standalone_fun, StandaloneLog} ->
horus:exec(
StandaloneLog,
["~p received and executed function", [self()]])
end.
rebar3 compile
rebar3 edoc
rebar3 xref
rebar3 eunit
rebar3 ct --sname ct
rebar3 as test dialyzer
© 2021-2024 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
This work is dual-licensed under the Apache License 2.0 and the Mozilla Public License 2.0. You can choose between one of them if you use this work.
SPDX-License-Identifier: Apache-2.0 OR MPL-2.0