https://github.com/mauro3/unpack.jl
`@pack!` and `@unpack` macros
https://github.com/mauro3/unpack.jl
datatypes dictionaries helpers macros
Last synced: 4 months ago
JSON representation
`@pack!` and `@unpack` macros
- Host: GitHub
- URL: https://github.com/mauro3/unpack.jl
- Owner: mauro3
- License: mit
- Created: 2019-11-23T21:18:56.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-11-18T13:51:37.000Z (over 2 years ago)
- Last Synced: 2024-10-12T10:31:16.831Z (9 months ago)
- Topics: datatypes, dictionaries, helpers, macros
- Language: Julia
- Homepage:
- Size: 32.2 KB
- Stars: 85
- Watchers: 4
- Forks: 13
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# UnPack
[](https://github.com/mauro3/UnPack.jl/actions)
[](https://ci.appveyor.com/project/mauro3/UnPack-jl)
[](https://codecov.io/gh/mauro3/UnPack.jl)
[](https://juliahub.com/ui/Packages/UnPack/zm2TF)[](https://juliahub.com/ui/Packages/UnPack/zm2TF?t=2)
[](https://juliahub.com/ui/Packages/UnPack/zm2TF)It is often convenient to unpack some or all of the fields of a type,
and pack, in the case of mutable datatypes (for immutables use
[Setfield.jl](https://github.com/jw3126/Setfield.jl)). This is often
the case when a struct is passed into a function.The `@unpack` and `@pack!` macros work to unpack
types, modules, and dictionaries (and can be customized for other
types too, see next section).```julia
using UnPackmutable struct Para
a::Float64
b::Int
endfunction f!(var, pa::Para)
@unpack a, b = pa # equivalent to: a,b = pa.a,pa.b
out = var + a + b
b = 77
@pack! pa = b # equivalent to: pa.b = b
return out, pa
endout, pa = f!(7, Para(1,2)) # -> 10.0, Para(1.0, 77)
```Example with a dictionary:
```julia
d = Dict{Symbol,Any}(:a=>5.0, :b=>2, :c=>"Hi!")
@unpack a, c = d
a == 5.0 #true
c == "Hi!" #trued = Dict{String,Any}()
@pack! d = a, c
d # -> Dict{String,Any}("a"=>5.0,"c"=>"Hi!")
```## Customization of `@unpack` and `@pack!`
What happens during the (un-)packing of a particular datatype is
determined by the functions `UnPack.unpack` and `UnPack.pack!`.The `UnPack.unpack` function is invoked to unpack one entity of some
`DataType` and has signature:```julia
unpack(dt::Any, ::Val{property}) -> value of property
```Note that `unpack` (and `pack!`) works with `Base.getproperty`. By
default this means that all the fields of a type are unpacked but if
`getproperty` is overloaded, then it will unpack accordingly.Three method definitions are included in the package to unpack a
composite type/module/NamedTuple, or a dictionary with Symbol or
string keys:```julia
@inline unpack(x, ::Val{f}) where {f} = getproperty(x, f)
@inline unpack(x::AbstractDict{Symbol}, ::Val{k}) where {k} = x[k]
@inline unpack(x::AbstractDict{<:AbstractString}, ::Val{k}) where {k} = x[string(k)]
```The `UnPack.pack!` function is invoked to pack one entity into some
`DataType` and has signature:```julia
pack!(dt::Any, ::Val{field}, value) -> value
```Three definitions are included in the package to pack into a mutable composite
type or into a dictionary with Symbol or string keys:```julia
@inline pack!(x, ::Val{f}, val) where {f} = setproperty!(x, f, val)
@inline pack!(x::AbstractDict{Symbol}, ::Val{k}, val) where {k} = x[k]=val
@inline pack!(x::AbstractDict{<:AbstractString}, ::Val{k}, val) where {k} = x[string(k)]=val
```More methods can be added to `unpack` and `pack!` to allow for
specialized unpacking/packing of datatypes. Here is a MWE of customizing
`unpack`, so that it multiplies the values by 2:```julia
using UnPack
struct Foo
a
b
end
p = Foo(1, 2)
@unpack a, b = p
a, b # gives (1, 2)# Now we specialize unpack for our custom type, `Foo`
@inline UnPack.unpack(x::Foo, ::Val{f}) where {f} = 2 * getproperty(x, f)
@unpack a, b = p
a, b # now gives (2, 4)
```# Related
- Julia issue on unpacking of function arguments
https://github.com/JuliaLang/julia/issues/28579
- setting immutables https://github.com/jw3126/Setfield.jl