Description
Steps
- Start a toy project using TypedStruct and a plugin-to-be
- Find a plugin idea
- Start the plugin project
- Define the plugin API and try concepts (try Plugin system #12)
- Merge Plugin system #12
- Adapt to the final v0.2.0 API while trying the implementation
- Write documentation
- Write tests
Rationale
Structs are used to represent many things in Elixir. Other libraries sometimes provide their own macros to define special functions alongside the struct. While integrating them with TypedStruct could sometimes be handy, there are two main issues:
- there is potentially a large number of libraries to integrate and maintain compatibility with,
- it would add code to TypedStruct that would be use by only a restricted number of projects.
There are already features request for Ecto (#7) and lens libraries (#8). More could come, so I think a plugin system would be a better solution. While I do not see currently how it would fit for the Ecto case, simpler cases like defining special functions from the struct fields could be handled by a function:
defmodule MyStruct do
use TypedStruct
# This would contain the define_lenses/? function.
# Its parameters and return type are yet to define.
import LensPlugin
typedstruct do
plugin :define_lenses
field :name, String.t()
field :age, integer(), some: :option
end
end
Plugin functions would be called after the field
s have been processed, with any option like some: :option
made available to it. The complete API is to define, but here is a first idea. It could be interesting to provide some helpers for users to define their own top-level macros to replace typedstruct
or extending it. Integration with Ecto could be explored in such a way.
API definition
In its PR #12, @uberbrodt defines the plugin API as a behaviour. This seems to be a good start.
Plugin definition
A TypedStruct plugin is a module that implements the TypedStruct.Plugin
behaviour. This behaviour is made of several callbacks, all optional to let some flexibility to the user:
@macrocallback init(opts)
: lets the user inject some code in the module before the fields are processed. This can be used to register attributes or adding new macros in the scope.@callback field(name, type, opts)
: called on each field, after it has been processed by TypedStruct.@callback after_fields(opts)
: called after the fields, but before the struct and type definition.
Plugin usage
defmodule MyStruct do
use TypedStruct
typedstruct do
plugin FirstPlugin
plugin WithOptions, some: :option, another: "option"
field :name, String.t()
field :age, integer(), some: :option
end
end
Options passed to the plugins are passed to the callbacks. The field/4
callbacks gets both the field-specific options and the plugin general option in its opts
keyword.
Metadata
Metadata
Assignees
Labels
Projects
Status