Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "StructHelpers"
uuid = "4093c41a-2008-41fd-82b8-e3f9d02b504f"
authors = ["Jan Weidner <jw3126@gmail.com> and contributors"]
version = "1.5.1"
version = "1.6.0"

[deps]
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
Expand Down
54 changes: 53 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![Build Status](https://github.com/jw3126/StructHelpers.jl/workflows/CI/badge.svg)](https://github.com/jw3126/StructHelpers.jl/actions)
[![Coverage](https://codecov.io/gh/jw3126/StructHelpers.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/jw3126/StructHelpers.jl)

Sometimes defining a new struct is accompanied by a bit of boilerplate. For instance the default definition of `Base.hash` is by object id. Often a `hash` that is based on the object struture is preferable however. Similar for `==`.
Sometimes defining a new struct is accompanied by a bit of boilerplate. For instance the default definition of `Base.hash` is by object id. Often a `hash` that is based on the object structure is preferable however. Similar for `==`.
StructHelpers aims to simplify the boilerplate required for such common tweaks.

# Usage
Expand All @@ -19,7 +19,59 @@ end
@batteries S
@batteries S hash=false # don't overload `Base.hash`
@batteries S kwconstructor=true # add a keyword constructor
@batteries S kwconstructor # bare-symbol shorthand for `kwconstructor=true`
```

If you want only a hand-picked subset of batteries (no defaults), use
`@battery`:

```julia
@battery S kwconstructor # only the keyword constructor
@battery S eq isequal hash # only structural ==, isequal, hash
```

To share a configuration across many structs, pass a `NamedTuple`:

```julia
const config = (kwshow=true, kwconstructor=true, eq=false)

@batteries S1 config
@batteries S2 config typesalt=0xdeadbeef # config + per-struct override
@battery S3 config # opt-in form, same config
```

A config only *overrides* the keys it mentions. With `@batteries`, every
key the config doesn't set keeps its default value (e.g. `S1` above
still gets the default structural `isequal`, `hash`, `selfconstructor`
etc.). With `@battery` the same config picks exactly the listed
batteries and nothing else, since `@battery`'s baseline has every flag
turned off.

Useful configs could look like this:

```julia
# Value-like records: nice display + keyword construction, structural
# `==` / `isequal` / `hash` from the defaults.
const value_like = (kwshow=true, kwconstructor=true)

# Plain data you also want to (de)serialize via StructTypes.jl / JSON3.
const serializable = (kwshow=true, kwconstructor=true, StructTypes=true)

# Identity semantics: keep ergonomic show/construction, but opt out of
# structural equality and hashing (e.g. for mutable handles or types
# whose fields aren't meaningfully comparable).
const identity_like = (kwshow=true, kwconstructor=true,
eq=false, isequal=false, hash=false)

# Reproducible cross-machine hashes: combine with a per-struct typesalt.
const stable_hash = (kwshow=true, kwconstructor=true)

@batteries Point value_like
@batteries Config serializable
@batteries FileHandle identity_like
@batteries CacheKey stable_hash typesalt=0xdeadbeefcafebabe
```

For all supported options and defaults, consult the docstring:
```julia
julia>?@batteries
Expand Down
Loading
Loading