Your observations are correct! Elixir modules get compiled by Hologram, but calls to underlying Erlang modules need the corresponding Erlang functions to be manually ported to JavaScript.
Help on porting :sets
module functions is definitely welcome! You can find the manually ported Erlang functions here: https://github.com/bartblast/hologram/tree/dev/assets/js/erlang
These functions are relatively straightforward to port, and I’d be happy to review pull requests. Just please create separate pull requests for each function so I can review them quickly.
Let me walk you through the procedure using :lists.keymember/3
as an example (from lists.mjs
):
Structure of manually ported functions:
Each function follows this pattern:
// Start keymember/3
"keymember/3": (value, index, tuples) => {
return Type.boolean(
Type.isTuple(Erlang_Lists["keyfind/3"](value, index, tuples)),
);
},
// End keymember/3
// Deps: [:lists.keyfind/3]
Key components:
- Start/End comments: These allow the Hologram compiler to extract the source code during compilation
- Deps comment: Lists dependencies on other Erlang functions. This information is currently duplicated in
Hologram.Compiler.CallGraph
module’s@erlang_mfa_edges
attribute, but eventually there will be only one source of this information.
What you’ll typically need:
- Type class: Provides boxed type utilities (
Type.boolean()
,Type.isTuple()
, etc.) - Interpreter class: For function calls, error handling, and comparisons
- Bitstring class: For binary operations (if needed)
Critical requirements for implementation:
-
OTP Consistency: Make sure your functions are consistent with the actual OTP implementation. Check the function documentation in
iex
:iex> h :lists.keymember/3
And refer to the official Erlang documentation: e.g. https://www.erlang.org/docs/26/man/lists
-
Testing Requirements: Each function must have two types of tests:
- JavaScript unit tests: Like the ones here: https://github.com/bartblast/hologram/blob/dev/assets/js/erlang/lists.mjs
- Server-side consistency tests: That mirror the JS tests, like here: https://github.com/bartblast/hologram/blob/dev/test/elixir/hologram/ex_js_consistency/erlang/lists_test.exs
Important guidelines:
- Never mutate the parameters - return new values, or return parameters unchanged
- Follow the existing validation patterns (you’ll notice some duplication in parameter validation, but don’t worry about DRY-ing it up - just follow current conventions for now)
- Use the same error handling patterns as existing functions
- Test thoroughly against the OTP behavior to ensure consistency
For :sets
module functions, you’ll want to look at how similar data structure operations are implemented in the existing maps.mjs
and lists.mjs
files.
Feel free to start with any :sets
function you need and create a PR - I’m here to help with any questions during the implementation!