├── .dockerignore ├── .gitattributes ├── .gitignore ├── .yamllint ├── CHANGELOG.md ├── Dockerfile ├── LICENSE.txt ├── Makefile ├── README.md ├── doc ├── README.md ├── edoc-info ├── erlang.png ├── index.html ├── lenses.jpg ├── modules-frame.html ├── optic.html ├── optic.md ├── optic_array.html ├── optic_array.md ├── optic_dict.html ├── optic_dict.md ├── optic_gb_sets.html ├── optic_gb_sets.md ├── optic_gb_trees.html ├── optic_gb_trees.md ├── optic_generic.html ├── optic_generic.md ├── optic_lists.html ├── optic_lists.md ├── optic_maps.html ├── optic_maps.md ├── optic_orddict.html ├── optic_orddict.md ├── optic_ordsets.html ├── optic_ordsets.md ├── optic_path.html ├── optic_path.md ├── optic_proplists.html ├── optic_proplists.md ├── optic_sets.html ├── optic_sets.md ├── optic_tuples.html ├── optic_tuples.md ├── overview-summary.html ├── overview.edoc └── stylesheet.css ├── docker-compose.yml ├── include └── optic_tuples.hrl ├── rebar.config ├── rebar.lock ├── requirements.txt ├── src ├── optic.app.src ├── optic.erl ├── optic_array.erl ├── optic_dict.erl ├── optic_gb_sets.erl ├── optic_gb_trees.erl ├── optic_generic.erl ├── optic_lists.erl ├── optic_maps.erl ├── optic_orddict.erl ├── optic_ordsets.erl ├── optic_path.erl ├── optic_proplists.erl ├── optic_sets.erl └── optic_tuples.erl └── test ├── test_optic.erl ├── test_optic_array.erl ├── test_optic_dict.erl ├── test_optic_gb_sets.erl ├── test_optic_gb_trees.erl ├── test_optic_generic.erl ├── test_optic_lists.erl ├── test_optic_maps.erl ├── test_optic_orddict.erl ├── test_optic_ordsets.erl ├── test_optic_path.erl ├── test_optic_proplists.erl ├── test_optic_sets.erl └── test_optic_tuples.erl /.dockerignore: -------------------------------------------------------------------------------- 1 | # Docker build instructions. 2 | Dockerfile 3 | .dockerignore 4 | 5 | # Revision control. 6 | .git/ 7 | **/.gitignore 8 | 9 | # Vim files. 10 | tags 11 | **/*.sw[po] 12 | 13 | # Build tools in base image. 14 | ./rebar3 15 | 16 | # Local build artifacts. 17 | ./_build 18 | .virtualenv 19 | log 20 | logs 21 | test/.rebar3 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Erlang build and crash files. 2 | *.beam 3 | *.o 4 | *.plt 5 | .erlang.cookie 6 | .idea 7 | _build 8 | ebin 9 | erl_crash.dump 10 | log 11 | logs 12 | rebar3 13 | rebar3.crashdump 14 | .rebar3 15 | 16 | # CI secrets. 17 | codeship.aes 18 | deploy/dockercfg.json 19 | deploy/env.env 20 | config/test.config 21 | 22 | # Optional python dependencies. 23 | .virtualenv 24 | 25 | # Optional node.js dependencies. 26 | node_modules/ 27 | package-lock.json 28 | 29 | # Vim files. 30 | *.swo 31 | *.swp 32 | tags 33 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | ignore: | 2 | /_build 3 | /.virtualenv 4 | /docker/.volumes 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [3.1.0] - 2019-04-28 11 | ### Added 12 | - The `optic_array` module was added to work with the corresponding 13 | container. 14 | 15 | ## [3.0.0] - 2019-04-26 16 | ### Changed 17 | - The argument order of `optic:map/3`, `optic:fold/4`, `optic:mapfold/4` and 18 | `optic:put/3` was changed to be the same as the corresponding lists module 19 | order; subject last. 20 | 21 | ## [2.1.0] - 2019-04-26 22 | ### Added 23 | - The `optic_dict`, `optic_orddict`, `optic_gb_trees`, `optic_sets`, 24 | `optic_ordsets` and `optic_gb_sets` modules were added to work with the 25 | corresponding containers. 26 | 27 | ## [2.0.0] - 2019-02-24 28 | ### Added 29 | - The `optic:wrap/2` and `optic:wrap/3` functions were added to enable 30 | modifying optics without exposing the internal representation. 31 | - The `optic:chain/1` function was added to enable explicit optic composition. 32 | - The `optic:is_optic/1` function was added. 33 | - The `optic:create/3` optic wrapper was exposed as a public interface. 34 | - The `optic:lax/1` optic wrapper was exposed as a public interface. 35 | - The `optic:error/1` generic optic was added. 36 | - The `optic:filter/1` generic optic was added. 37 | - The `optic:require/1` generic optic was added. 38 | 39 | ### Changed 40 | - The `optic:from/1` function was renamed to `optic:merge/1` to better 41 | distinguish it from chaining. 42 | - The `optic_generic:id/0` optic was moved to `optic:id/0`. 43 | - The internal `optic:'%extend'/3` interface was renamed to `optic:variations/3`. 44 | 45 | ## [1.0.0] - 2019-02-20 46 | ### Added 47 | - Initial release. 48 | 49 | [Unreleased]: https://github.com/jkrukoff/optic/compare/v3.1.0...HEAD 50 | [3.1.0]: https://github.com/jkrukoff/optic/compare/v3.0.0...v3.1.0 51 | [3.0.0]: https://github.com/jkrukoff/optic/compare/v2.1.0...v3.0.0 52 | [2.1.0]: https://github.com/jkrukoff/optic/compare/v2.0.0...v2.1.0 53 | [2.0.0]: https://github.com/jkrukoff/optic/compare/v1.0.0...v2.0.0 54 | [1.0.0]: https://github.com/jkrukoff/optic/releases/tag/v1.0.0 55 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM erlang:21 2 | 3 | # Install build and test dependencies. 4 | # python3-pip: for installing python build dependencies. 5 | RUN set -xe && apt-get update && apt-get install -y python3-pip 6 | 7 | RUN mkdir -p /usr/src/app 8 | WORKDIR /usr/src/app 9 | 10 | COPY ./requirements.txt ./ 11 | RUN pip3 install -r requirements.txt 12 | 13 | COPY . ./ 14 | RUN make compile 15 | 16 | ENTRYPOINT ["make"] 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += --warn-undefined-variables 2 | .DEFAULT_GOAL := all 3 | 4 | PYTHON := python3 5 | REBAR ?= ${if ${wildcard ./rebar3}, ./rebar3, rebar3} 6 | 7 | .PHONY: all 8 | ## Build everything. 9 | all: test-unit doc 10 | ${MAKE} compile 11 | 12 | .PHONY: clean 13 | ## Delete intermediate files. 14 | clean: 15 | ${REBAR} clean -a 16 | 17 | .PHONY: compile 18 | ## Compile all profiles. 19 | compile: 20 | ${REBAR} compile 21 | ${REBAR} as test compile 22 | 23 | .PHONY: doc 24 | ## Build documentation. 25 | doc: require-pic2plot $(addsuffix .png,$(basename $(wildcard doc/*.pic))) 26 | ${REBAR} edoc 27 | ${REBAR} as markdown edoc 28 | 29 | doc/%.png: doc/%.pic 30 | pic2plot --font-size=0.010 --bitmap-size=4096x4096 --line-width=0.00097656 -Tpng $< > $@ 31 | 32 | .SILENT: help 33 | .PHONY: help 34 | ## This help screen. 35 | help: 36 | # Extracts help from the Makefile itself, printing help for any rule 37 | # which matches the defined regular expression and that has a double 38 | # hash (##) comment on the line above. 39 | printf "Available Targets:\n\n" 40 | awk '/^[a-zA-Z\-\_0-9]+:/ { \ 41 | helpMessage = match(lastLine, /^## (.*)/); \ 42 | if (helpMessage) { \ 43 | helpCommand = substr($$1, 0, index($$1, ":")); \ 44 | helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ 45 | printf "%-18s %s\n", helpCommand, helpMessage; \ 46 | } \ 47 | } \ 48 | { lastLine = $$0 }' ${MAKEFILE_LIST} 49 | 50 | rebar.lock: rebar.config 51 | ${REBAR} update 52 | ${REBAR} unlock 53 | ${REBAR} upgrade 54 | 55 | REQUIREMENTS = $(addprefix require-,pic2plot yamllint virtualenv) 56 | 57 | .PHONY: ${REQUIREMENTS} 58 | ${REQUIREMENTS}: what=$(patsubst require-%,%,$@) 59 | ${REQUIREMENTS}: require-%: 60 | @which $(what) > /dev/null || \ 61 | (printf "%s%s%s\n" "$$(tput setaf 3)" '"$(what)" is required, please install.' "$$(tput sgr0)"; exit 1) 62 | 63 | rebar3: 64 | curl -o rebar3 https://s3.amazonaws.com/rebar3/rebar3 65 | chmod 755 rebar3 66 | 67 | .PHONY: test 68 | ## Run all test suites. 69 | test: test-unit test-integration 70 | 71 | .PHONY: test-integration 72 | ## Run the integration test suite. 73 | test-integration: 74 | envsubst < config/test.config.template > config/test.config 75 | if ! ${REBAR} as test do ct --config=config/test.config; then \ 76 | grep -lr 'CT Error Notification' _build/test/logs/ | xargs -n 1 html2text; \ 77 | fi 78 | 79 | .PHONY: test-unit 80 | ## Run the unit test suite. 81 | test-unit: require-yamllint 82 | ${REBAR} as prod dialyzer 83 | ${REBAR} as test do dialyzer, eunit, proper, geas #, lint 84 | yamllint -s . 85 | 86 | .virtualenv: requirements.txt 87 | ${MAKE} require-virtualenv 88 | virtualenv --clear --download --always-copy -p "$$(which ${PYTHON})" .virtualenv 89 | .virtualenv/bin/pip install --force-reinstall --upgrade pip setuptools wheel 90 | .virtualenv/bin/pip install -r requirements.txt 91 | @printf "\n\n%s%s%s\n" "$$(tput setaf 3)" "To activate virtualenv run: source .virtualenv/bin/activate" "$$(tput sgr0)" 92 | -------------------------------------------------------------------------------- /doc/edoc-info: -------------------------------------------------------------------------------- 1 | %% encoding: UTF-8 2 | {application,optic}. 3 | {modules,[optic,optic_array,optic_dict,optic_gb_sets,optic_gb_trees, 4 | optic_generic,optic_lists,optic_maps,optic_orddict,optic_ordsets, 5 | optic_path,optic_proplists,optic_sets,optic_tuples]}. 6 | -------------------------------------------------------------------------------- /doc/erlang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkrukoff/optic/4aa37630fd37e43af3ccfa0c947f9c8a27d77154/doc/erlang.png -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The optic application 5 | 6 | 7 | 8 | 9 | 10 | 11 | <h2>This page uses frames</h2> 12 | <p>Your browser does not accept frames. 13 | <br>You should go to the <a href="overview-summary.html">non-frame version</a> instead. 14 | </p> 15 | 16 | 17 | -------------------------------------------------------------------------------- /doc/lenses.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkrukoff/optic/4aa37630fd37e43af3ccfa0c947f9c8a27d77154/doc/lenses.jpg -------------------------------------------------------------------------------- /doc/modules-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The optic application 5 | 6 | 7 | 8 |

Modules

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
optic
optic_array
optic_dict
optic_gb_sets
optic_gb_trees
optic_generic
optic_lists
optic_maps
optic_orddict
optic_ordsets
optic_path
optic_proplists
optic_sets
optic_tuples
24 | 25 | -------------------------------------------------------------------------------- /doc/optic_array.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_array 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_array

13 | 14 | A set of optics specific to arrays. 15 | 16 | 17 |

Description

18 | A set of optics specific to arrays. 19 |

Function Index

20 | 21 | 23 | 24 | 26 |
all/0
all/1 22 | Focus on all values of an array.
nth/1
nth/2 25 | Focus on the nth value of an array.
27 | 28 |

Function Details

29 | 30 |

all/0

31 |
32 |

all() -> optic:optic()

33 |
34 |

See also: all/1.

35 | 36 |

all/1

37 |
38 |

all(Options) -> optic:optic() 39 |

40 |

Options: Common optic options.
41 |

42 |

returns: An opaque optic record.

43 |

44 | Focus on all values of an array.

45 | 46 |

Example:

47 | 48 |
  > optic:get([optic_array:all()], array:from_list([1,2,3])).
49 |   {ok,[1,2,3]}

50 | 51 |

nth/1

52 |
53 |

nth(N) -> optic:optic() 54 |

55 |
56 |

See also: nth/2.

57 | 58 |

nth/2

59 |
60 |

nth(N, Options) -> optic:optic() 61 |

62 |

N: The index of the array value to focus on.
63 | Options: Common optic options.
64 |

65 |

returns: An opaque optic record.

66 |

67 | Focus on the nth value of an array. Like lists, but unlike the 68 | standard array operations, indexing begins at 1.

69 | 70 |

Example:

71 | 72 |
  > optic:get([optic_array:nth(1)], array:from_list([1,2,3])).
73 |   {ok,[1]}

74 |
75 | 76 | 77 |

Generated by EDoc

78 | 79 | 80 | -------------------------------------------------------------------------------- /doc/optic_array.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_array # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to arrays. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1 16 | Focus on all values of an array.
nth/1
nth/2 17 | Focus on the nth value of an array.
18 | 19 | 20 | 21 | 22 | ## Function Details ## 23 | 24 | 25 | 26 | ### all/0 ### 27 | 28 |

29 | all() -> optic:optic()
30 | 
31 |
32 | 33 | __See also:__ [all/1](#all-1). 34 | 35 | 36 | 37 | ### all/1 ### 38 | 39 |

40 | all(Options) -> optic:optic()
41 | 
42 | 43 | 44 | 45 | `Options`: Common optic options.
46 | 47 | returns: An opaque optic record. 48 | 49 | Focus on all values of an array. 50 | 51 | Example: 52 | 53 | ``` 54 | > optic:get([optic_array:all()], array:from_list([1,2,3])). 55 | {ok,[1,2,3]} 56 | ``` 57 | 58 | 59 | 60 | ### nth/1 ### 61 | 62 |

63 | nth(N) -> optic:optic()
64 | 
65 | 66 | 67 | 68 | __See also:__ [nth/2](#nth-2). 69 | 70 | 71 | 72 | ### nth/2 ### 73 | 74 |

75 | nth(N, Options) -> optic:optic()
76 | 
77 | 78 | 79 | 80 | `N`: The index of the array value to focus on.
`Options`: Common optic options.
81 | 82 | returns: An opaque optic record. 83 | 84 | Focus on the nth value of an array. Like lists, but unlike the 85 | standard array operations, indexing begins at 1. 86 | 87 | Example: 88 | 89 | ``` 90 | > optic:get([optic_array:nth(1)], array:from_list([1,2,3])). 91 | {ok,[1]} 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /doc/optic_dict.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_dict 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_dict

13 | 14 | A set of optics specific to dicts. 15 | 16 | 17 |

Description

18 | A set of optics specific to dicts. 19 |

Function Index

20 | 21 | 22 | 23 | 25 | 26 | 28 | 29 | 31 | 32 | 34 | 35 | 37 |
all/0
all/1
association/1
association/2 24 | Focus on the association for a dict key.
associations/0
associations/1 27 | Focus on all associations of a dict.
key/1
key/2 30 | Focus on the value of a dict key.
keys/0
keys/1 33 | Focus on all keys of a dict.
values/0
values/1 36 | Focus on all values of a dict.
38 | 39 |

Function Details

40 | 41 |

all/0

42 |
43 |

all() -> optic:optic()

44 |
45 |

See also: values/1.

46 | 47 |

all/1

48 |
49 |

all(Options) -> optic:optic() 50 |

51 |
52 |

See also: values/1.

53 | 54 |

association/1

55 |
56 |

association(Key) -> optic:optic() 57 |

58 |
59 |

See also: association/2.

60 | 61 |

association/2

62 |
63 |

association(Key, Options) -> optic:optic() 64 |

65 |

Key: The key to focus on.
66 | Options: Common optic options.
67 |

68 |

returns: An opaque optic record.

69 |

70 | Focus on the association for a dict key. An association is the 71 | tuple of a dict key and value. If the key is modified, the optic is 72 | no longer well behaved.

73 | 74 |

Example:

75 | 76 |
  > optic:get([optic_dict:association(first)],
 77 |               dict:from_list([{first, 1}, {second, 2}])).
 78 |   {ok,[{first,1}]}

79 | 80 |

associations/0

81 |
82 |

associations() -> optic:optic()

83 |
84 |

See also: associations/1.

85 | 86 |

associations/1

87 |
88 |

associations(Options) -> optic:optic() 89 |

90 |

Options: Common optic options.
91 |

92 |

returns: An opaque optic record.

93 |

94 | Focus on all associations of a dict. An association is a tuple of 95 | the key and value for each entry.

96 | 97 |

Example:

98 | 99 |
  > optic:get([optic_dict:associations()],
100 |               dict:from_list([{first, 1}, {second, 2}])).
101 |   {ok,[{first,1},{second,2}]}

102 | 103 |

key/1

104 |
105 |

key(Key) -> optic:optic() 106 |

107 |
108 |

See also: key/2.

109 | 110 |

key/2

111 |
112 |

key(Key, Options) -> optic:optic() 113 |

114 |

Key: The key to focus on.
115 | Options: Common optic options.
116 |

117 |

returns: An opaque optic record.

118 |

119 | Focus on the value of a dict key.

120 | 121 |

Example:

122 | 123 |
  > optic:get([optic_dict:key(first)],
124 |               dict:from_list([{first, 1}, {second, 2}])).
125 |   {ok,[1]}

126 | 127 |

keys/0

128 |
129 |

keys() -> optic:optic()

130 |
131 |

See also: keys/1.

132 | 133 |

keys/1

134 |
135 |

keys(Options) -> optic:optic() 136 |

137 |

Options: Common optic options.
138 |

139 |

returns: An opaque optic record.

140 |

141 | Focus on all keys of a dict.

142 | 143 |

Example:

144 | 145 |
  > optic:get([optic_dict:keys()],
146 |               dict:from_list([{first, 1}, {second, 2}])).
147 |   {ok,[first,second]}

148 | 149 |

values/0

150 |
151 |

values() -> optic:optic()

152 |
153 |

See also: values/1.

154 | 155 |

values/1

156 |
157 |

values(Options) -> optic:optic() 158 |

159 |

Options: Common optic options.
160 |

161 |

returns: An opaque optic record.

162 |

163 | Focus on all values of a dict.

164 | 165 |

Example:

166 | 167 |
  > optic:get([optic_dict:values()],
168 |               dict:from_list([{first, 1}, {second, 2}])).
169 |   {ok,[1,2]}

170 |
171 | 172 | 173 |

Generated by EDoc

174 | 175 | 176 | -------------------------------------------------------------------------------- /doc/optic_dict.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_dict # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to dicts. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1
association/1
association/2 16 | Focus on the association for a dict key.
associations/0
associations/1 17 | Focus on all associations of a dict.
key/1
key/2 18 | Focus on the value of a dict key.
keys/0
keys/1 19 | Focus on all keys of a dict.
values/0
values/1 20 | Focus on all values of a dict.
21 | 22 | 23 | 24 | 25 | ## Function Details ## 26 | 27 | 28 | 29 | ### all/0 ### 30 | 31 |

 32 | all() -> optic:optic()
 33 | 
34 |
35 | 36 | __See also:__ [values/1](#values-1). 37 | 38 | 39 | 40 | ### all/1 ### 41 | 42 |

 43 | all(Options) -> optic:optic()
 44 | 
45 | 46 | 47 | 48 | __See also:__ [values/1](#values-1). 49 | 50 | 51 | 52 | ### association/1 ### 53 | 54 |

 55 | association(Key) -> optic:optic()
 56 | 
57 | 58 | 59 | 60 | __See also:__ [association/2](#association-2). 61 | 62 | 63 | 64 | ### association/2 ### 65 | 66 |

 67 | association(Key, Options) -> optic:optic()
 68 | 
69 | 70 | 71 | 72 | `Key`: The key to focus on.
`Options`: Common optic options.
73 | 74 | returns: An opaque optic record. 75 | 76 | Focus on the association for a dict key. An association is the 77 | tuple of a dict key and value. If the key is modified, the optic is 78 | no longer well behaved. 79 | 80 | Example: 81 | 82 | ``` 83 | > optic:get([optic_dict:association(first)], 84 | dict:from_list([{first, 1}, {second, 2}])). 85 | {ok,[{first,1}]} 86 | ``` 87 | 88 | 89 | 90 | ### associations/0 ### 91 | 92 |

 93 | associations() -> optic:optic()
 94 | 
95 |
96 | 97 | __See also:__ [associations/1](#associations-1). 98 | 99 | 100 | 101 | ### associations/1 ### 102 | 103 |

104 | associations(Options) -> optic:optic()
105 | 
106 | 107 | 108 | 109 | `Options`: Common optic options.
110 | 111 | returns: An opaque optic record. 112 | 113 | Focus on all associations of a dict. An association is a tuple of 114 | the key and value for each entry. 115 | 116 | Example: 117 | 118 | ``` 119 | > optic:get([optic_dict:associations()], 120 | dict:from_list([{first, 1}, {second, 2}])). 121 | {ok,[{first,1},{second,2}]} 122 | ``` 123 | 124 | 125 | 126 | ### key/1 ### 127 | 128 |

129 | key(Key) -> optic:optic()
130 | 
131 | 132 | 133 | 134 | __See also:__ [key/2](#key-2). 135 | 136 | 137 | 138 | ### key/2 ### 139 | 140 |

141 | key(Key, Options) -> optic:optic()
142 | 
143 | 144 | 145 | 146 | `Key`: The key to focus on.
`Options`: Common optic options.
147 | 148 | returns: An opaque optic record. 149 | 150 | Focus on the value of a dict key. 151 | 152 | Example: 153 | 154 | ``` 155 | > optic:get([optic_dict:key(first)], 156 | dict:from_list([{first, 1}, {second, 2}])). 157 | {ok,[1]} 158 | ``` 159 | 160 | 161 | 162 | ### keys/0 ### 163 | 164 |

165 | keys() -> optic:optic()
166 | 
167 |
168 | 169 | __See also:__ [keys/1](#keys-1). 170 | 171 | 172 | 173 | ### keys/1 ### 174 | 175 |

176 | keys(Options) -> optic:optic()
177 | 
178 | 179 | 180 | 181 | `Options`: Common optic options.
182 | 183 | returns: An opaque optic record. 184 | 185 | Focus on all keys of a dict. 186 | 187 | Example: 188 | 189 | ``` 190 | > optic:get([optic_dict:keys()], 191 | dict:from_list([{first, 1}, {second, 2}])). 192 | {ok,[first,second]} 193 | ``` 194 | 195 | 196 | 197 | ### values/0 ### 198 | 199 |

200 | values() -> optic:optic()
201 | 
202 |
203 | 204 | __See also:__ [values/1](#values-1). 205 | 206 | 207 | 208 | ### values/1 ### 209 | 210 |

211 | values(Options) -> optic:optic()
212 | 
213 | 214 | 215 | 216 | `Options`: Common optic options.
217 | 218 | returns: An opaque optic record. 219 | 220 | Focus on all values of a dict. 221 | 222 | Example: 223 | 224 | ``` 225 | > optic:get([optic_dict:values()], 226 | dict:from_list([{first, 1}, {second, 2}])). 227 | {ok,[1,2]} 228 | ``` 229 | 230 | -------------------------------------------------------------------------------- /doc/optic_gb_sets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_gb_sets 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_gb_sets

13 | 14 | A set of optics specific to gb_sets. 15 | 16 | 17 |

Description

18 | A set of optics specific to gb_sets. 19 |

Function Index

20 | 21 | 23 |
all/0
all/1 22 | Focus on all elements of a gb_set.
24 | 25 |

Function Details

26 | 27 |

all/0

28 |
29 |

all() -> optic:optic()

30 |
31 |

See also: all/1.

32 | 33 |

all/1

34 |
35 |

all(Options) -> optic:optic() 36 |

37 |

Options: Common optic options.
38 |

39 |

returns: An opaque optic record.

40 |

41 | Focus on all elements of a gb_set.

42 | 43 |

Example:

44 | 45 |
  > optic:get([optic_gb_sets:all()], gb_sets:from_list([1,2,3])).
46 |   {ok,[1,2,3]}

47 |
48 | 49 | 50 |

Generated by EDoc

51 | 52 | 53 | -------------------------------------------------------------------------------- /doc/optic_gb_sets.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_gb_sets # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to gb_sets. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1 16 | Focus on all elements of a gb_set.
17 | 18 | 19 | 20 | 21 | ## Function Details ## 22 | 23 | 24 | 25 | ### all/0 ### 26 | 27 |

28 | all() -> optic:optic()
29 | 
30 |
31 | 32 | __See also:__ [all/1](#all-1). 33 | 34 | 35 | 36 | ### all/1 ### 37 | 38 |

39 | all(Options) -> optic:optic()
40 | 
41 | 42 | 43 | 44 | `Options`: Common optic options.
45 | 46 | returns: An opaque optic record. 47 | 48 | Focus on all elements of a gb_set. 49 | 50 | Example: 51 | 52 | ``` 53 | > optic:get([optic_gb_sets:all()], gb_sets:from_list([1,2,3])). 54 | {ok,[1,2,3]} 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /doc/optic_gb_trees.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_gb_trees 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_gb_trees

13 | 14 | A set of optics specific to gb_trees. 15 | 16 | 17 |

Description

18 | A set of optics specific to gb_trees. 19 |

Function Index

20 | 21 | 22 | 23 | 25 | 26 | 28 | 29 | 31 | 32 | 34 | 35 | 37 |
all/0
all/1
association/1
association/2 24 | Focus on the association for a gb_tree key.
associations/0
associations/1 27 | Focus on all associations of a gb_tree.
key/1
key/2 30 | Focus on the value of a gb_tree key.
keys/0
keys/1 33 | Focus on all keys of a gb_tree.
values/0
values/1 36 | Focus on all values of a gb_tree.
38 | 39 |

Function Details

40 | 41 |

all/0

42 |
43 |

all() -> optic:optic()

44 |
45 |

See also: values/1.

46 | 47 |

all/1

48 |
49 |

all(Options) -> optic:optic() 50 |

51 |
52 |

See also: values/1.

53 | 54 |

association/1

55 |
56 |

association(Key) -> optic:optic() 57 |

58 |
59 |

See also: association/2.

60 | 61 |

association/2

62 |
63 |

association(Key, Options) -> optic:optic() 64 |

65 |

Key: The key to focus on.
66 | Options: Common optic options.
67 |

68 |

returns: An opaque optic record.

69 |

70 | Focus on the association for a gb_tree key. An association is the 71 | tuple of a gb_tree key and value. If the key is modified, the optic is 72 | no longer well behaved.

73 | 74 |

Example:

75 | 76 |
  > optic:get([optic_gb_trees:association(first)],
 77 |               gb_trees:from_orddict([{first, 1}, {second, 2}])).
 78 |   {ok,[{first,1}]}

79 | 80 |

associations/0

81 |
82 |

associations() -> optic:optic()

83 |
84 |

See also: associations/1.

85 | 86 |

associations/1

87 |
88 |

associations(Options) -> optic:optic() 89 |

90 |

Options: Common optic options.
91 |

92 |

returns: An opaque optic record.

93 |

94 | Focus on all associations of a gb_tree. An association is a tuple of 95 | the key and value for each entry.

96 | 97 |

Example:

98 | 99 |
  > optic:get([optic_gb_trees:associations()],
100 |               gb_trees:from_orddict([{first, 1}, {second, 2}])).
101 |   {ok,[{first,1},{second,2}]}

102 | 103 |

key/1

104 |
105 |

key(Key) -> optic:optic() 106 |

107 |
108 |

See also: key/2.

109 | 110 |

key/2

111 |
112 |

key(Key, Options) -> optic:optic() 113 |

114 |

Key: The key to focus on.
115 | Options: Common optic options.
116 |

117 |

returns: An opaque optic record.

118 |

119 | Focus on the value of a gb_tree key.

120 | 121 |

Example:

122 | 123 |
  > optic:get([optic_gb_trees:key(first)],
124 |               gb_trees:from_orddict([{first, 1}, {second, 2}])).
125 |   {ok,[1]}

126 | 127 |

keys/0

128 |
129 |

keys() -> optic:optic()

130 |
131 |

See also: keys/1.

132 | 133 |

keys/1

134 |
135 |

keys(Options) -> optic:optic() 136 |

137 |

Options: Common optic options.
138 |

139 |

returns: An opaque optic record.

140 |

141 | Focus on all keys of a gb_tree.

142 | 143 |

Example:

144 | 145 |
  > optic:get([optic_gb_trees:keys()],
146 |               gb_trees:from_orddict([{first, 1}, {second, 2}])).
147 |   {ok,[first,second]}

148 | 149 |

values/0

150 |
151 |

values() -> optic:optic()

152 |
153 |

See also: values/1.

154 | 155 |

values/1

156 |
157 |

values(Options) -> optic:optic() 158 |

159 |

Options: Common optic options.
160 |

161 |

returns: An opaque optic record.

162 |

163 | Focus on all values of a gb_tree.

164 | 165 |

Example:

166 | 167 |
  > optic:get([optic_gb_trees:values()],
168 |               gb_trees:from_orddict([{first, 1}, {second, 2}])).
169 |   {ok,[1,2]}

170 |
171 | 172 | 173 |

Generated by EDoc

174 | 175 | 176 | -------------------------------------------------------------------------------- /doc/optic_gb_trees.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_gb_trees # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to gb_trees. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1
association/1
association/2 16 | Focus on the association for a gb_tree key.
associations/0
associations/1 17 | Focus on all associations of a gb_tree.
key/1
key/2 18 | Focus on the value of a gb_tree key.
keys/0
keys/1 19 | Focus on all keys of a gb_tree.
values/0
values/1 20 | Focus on all values of a gb_tree.
21 | 22 | 23 | 24 | 25 | ## Function Details ## 26 | 27 | 28 | 29 | ### all/0 ### 30 | 31 |

 32 | all() -> optic:optic()
 33 | 
34 |
35 | 36 | __See also:__ [values/1](#values-1). 37 | 38 | 39 | 40 | ### all/1 ### 41 | 42 |

 43 | all(Options) -> optic:optic()
 44 | 
45 | 46 | 47 | 48 | __See also:__ [values/1](#values-1). 49 | 50 | 51 | 52 | ### association/1 ### 53 | 54 |

 55 | association(Key) -> optic:optic()
 56 | 
57 | 58 | 59 | 60 | __See also:__ [association/2](#association-2). 61 | 62 | 63 | 64 | ### association/2 ### 65 | 66 |

 67 | association(Key, Options) -> optic:optic()
 68 | 
69 | 70 | 71 | 72 | `Key`: The key to focus on.
`Options`: Common optic options.
73 | 74 | returns: An opaque optic record. 75 | 76 | Focus on the association for a gb_tree key. An association is the 77 | tuple of a gb_tree key and value. If the key is modified, the optic is 78 | no longer well behaved. 79 | 80 | Example: 81 | 82 | ``` 83 | > optic:get([optic_gb_trees:association(first)], 84 | gb_trees:from_orddict([{first, 1}, {second, 2}])). 85 | {ok,[{first,1}]} 86 | ``` 87 | 88 | 89 | 90 | ### associations/0 ### 91 | 92 |

 93 | associations() -> optic:optic()
 94 | 
95 |
96 | 97 | __See also:__ [associations/1](#associations-1). 98 | 99 | 100 | 101 | ### associations/1 ### 102 | 103 |

104 | associations(Options) -> optic:optic()
105 | 
106 | 107 | 108 | 109 | `Options`: Common optic options.
110 | 111 | returns: An opaque optic record. 112 | 113 | Focus on all associations of a gb_tree. An association is a tuple of 114 | the key and value for each entry. 115 | 116 | Example: 117 | 118 | ``` 119 | > optic:get([optic_gb_trees:associations()], 120 | gb_trees:from_orddict([{first, 1}, {second, 2}])). 121 | {ok,[{first,1},{second,2}]} 122 | ``` 123 | 124 | 125 | 126 | ### key/1 ### 127 | 128 |

129 | key(Key) -> optic:optic()
130 | 
131 | 132 | 133 | 134 | __See also:__ [key/2](#key-2). 135 | 136 | 137 | 138 | ### key/2 ### 139 | 140 |

141 | key(Key, Options) -> optic:optic()
142 | 
143 | 144 | 145 | 146 | `Key`: The key to focus on.
`Options`: Common optic options.
147 | 148 | returns: An opaque optic record. 149 | 150 | Focus on the value of a gb_tree key. 151 | 152 | Example: 153 | 154 | ``` 155 | > optic:get([optic_gb_trees:key(first)], 156 | gb_trees:from_orddict([{first, 1}, {second, 2}])). 157 | {ok,[1]} 158 | ``` 159 | 160 | 161 | 162 | ### keys/0 ### 163 | 164 |

165 | keys() -> optic:optic()
166 | 
167 |
168 | 169 | __See also:__ [keys/1](#keys-1). 170 | 171 | 172 | 173 | ### keys/1 ### 174 | 175 |

176 | keys(Options) -> optic:optic()
177 | 
178 | 179 | 180 | 181 | `Options`: Common optic options.
182 | 183 | returns: An opaque optic record. 184 | 185 | Focus on all keys of a gb_tree. 186 | 187 | Example: 188 | 189 | ``` 190 | > optic:get([optic_gb_trees:keys()], 191 | gb_trees:from_orddict([{first, 1}, {second, 2}])). 192 | {ok,[first,second]} 193 | ``` 194 | 195 | 196 | 197 | ### values/0 ### 198 | 199 |

200 | values() -> optic:optic()
201 | 
202 |
203 | 204 | __See also:__ [values/1](#values-1). 205 | 206 | 207 | 208 | ### values/1 ### 209 | 210 |

211 | values(Options) -> optic:optic()
212 | 
213 | 214 | 215 | 216 | `Options`: Common optic options.
217 | 218 | returns: An opaque optic record. 219 | 220 | Focus on all values of a gb_tree. 221 | 222 | Example: 223 | 224 | ``` 225 | > optic:get([optic_gb_trees:values()], 226 | gb_trees:from_orddict([{first, 1}, {second, 2}])). 227 | {ok,[1,2]} 228 | ``` 229 | 230 | -------------------------------------------------------------------------------- /doc/optic_generic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_generic 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_generic

13 | 14 | A set of generic optics that can be applied to multiple container 15 | types. 16 | 17 | 18 |

Description

19 | A set of generic optics that can be applied to multiple container 20 | types.

21 | 22 |

Intended both as a convenience and to support optic creation from 23 | parsed paths in optic_path.

24 | 25 | Because of the ambiguous types they support, these optics do not 26 | support the standard optic options. Instead, they always skip 27 | unexpected types and never create missing values. 28 |

Function Index

29 | 31 | 33 |
index/1 30 | Focus on an element of a list like container.
key/1 32 | Focus on the value of many different key/value like mappings.
34 | 35 |

Function Details

36 | 37 |

index/1

38 |
39 |

index(Index) -> optic:optic() 40 |

41 |

Index: The one based index of the element to focus on.
42 |

43 |

returns: An opaque optic record.

44 |

45 | Focus on an element of a list like container. Indexing begins at 1. 46 | Understands how to focus on lists and tuples. Does not support the 47 | usual optic options.

48 | 49 |

Example:

50 | 51 |
  > optic:get([optic_generic:index(3)], [1, 2, 3]).
52 |   {ok,[3]}

53 | 54 |

key/1

55 |
56 |

key(Key) -> optic:optic() 57 |

58 |

Key: The key to focus on.
59 |

60 |

returns: An opaque optic record.

61 |

62 | Focus on the value of many different key/value like mappings. 63 | Understands how to focus on maps, property lists, dicts, orddicts 64 | and gb_trees. Does not support the usual optic options.

65 | 66 |

Example:

67 | 68 |
  > optic:get([optic_generic:key(first)], #{first => 1}).
69 |   {ok,[1]}

70 |
71 | 72 | 73 |

Generated by EDoc

74 | 75 | 76 | -------------------------------------------------------------------------------- /doc/optic_generic.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_generic # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of generic optics that can be applied to multiple container 9 | types. 10 | 11 | 12 | 13 | ## Description ## 14 | 15 | Intended both as a convenience and to support optic creation from 16 | parsed paths in optic_path. 17 | 18 | Because of the ambiguous types they support, these optics do not 19 | support the standard optic options. Instead, they always skip 20 | unexpected types and never create missing values. 21 | 22 | ## Function Index ## 23 | 24 | 25 |
index/1 26 | Focus on an element of a list like container.
key/1 27 | Focus on the value of many different key/value like mappings.
28 | 29 | 30 | 31 | 32 | ## Function Details ## 33 | 34 | 35 | 36 | ### index/1 ### 37 | 38 |

39 | index(Index) -> optic:optic()
40 | 
41 | 42 | 43 | 44 | `Index`: The one based index of the element to focus on.
45 | 46 | returns: An opaque optic record. 47 | 48 | Focus on an element of a list like container. Indexing begins at 1. 49 | Understands how to focus on lists and tuples. Does not support the 50 | usual optic options. 51 | 52 | Example: 53 | 54 | ``` 55 | > optic:get([optic_generic:index(3)], [1, 2, 3]). 56 | {ok,[3]} 57 | ``` 58 | 59 | 60 | 61 | ### key/1 ### 62 | 63 |

64 | key(Key) -> optic:optic()
65 | 
66 | 67 | 68 | 69 | `Key`: The key to focus on.
70 | 71 | returns: An opaque optic record. 72 | 73 | Focus on the value of many different key/value like mappings. 74 | Understands how to focus on maps, property lists, dicts, orddicts 75 | and gb_trees. Does not support the usual optic options. 76 | 77 | Example: 78 | 79 | ``` 80 | > optic:get([optic_generic:key(first)], #{first => 1}). 81 | {ok,[1]} 82 | ``` 83 | 84 | -------------------------------------------------------------------------------- /doc/optic_lists.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_lists 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_lists

13 | 14 | A set of optics specific to lists. 15 | 16 | 17 |

Description

18 | A set of optics specific to lists. 19 |

Function Index

20 | 21 | 23 | 24 | 26 | 27 | 29 | 30 | 32 |
all/0
all/1 22 | Focus on all elements of a list.
head/0
head/1 25 | Focus on the head of a list.
nth/1
nth/2 28 | Focus on the nth element of a list.
tail/0
tail/1 31 | Focus on the tail of a list.
33 | 34 |

Function Details

35 | 36 |

all/0

37 |
38 |

all() -> optic:optic()

39 |
40 |

See also: all/1.

41 | 42 |

all/1

43 |
44 |

all(Options) -> optic:optic() 45 |

46 |

Options: Common optic options.
47 |

48 |

returns: An opaque optic record.

49 |

50 | Focus on all elements of a list.

51 | 52 |

Example:

53 | 54 |
  > optic:get([optic_lists:all()], [1,2,3]).
 55 |   {ok,[1,2,3]}

56 | 57 |

head/0

58 |
59 |

head() -> optic:optic()

60 |
61 |

See also: head/1.

62 | 63 |

head/1

64 |
65 |

head(Options) -> optic:optic() 66 |

67 |

Options: Common optic options.
68 |

69 |

returns: An opaque optic record.

70 |

71 | Focus on the head of a list. The list must have at least one 72 | element to have a head.

73 | 74 |

Example:

75 | 76 |
  > optic:get([optic_lists:head()], [1,2,3]).
 77 |   {ok,[1]}

78 | 79 |

nth/1

80 |
81 |

nth(N) -> optic:optic() 82 |

83 |
84 |

See also: nth/2.

85 | 86 |

nth/2

87 |
88 |

nth(N, Options) -> optic:optic() 89 |

90 |

N: The index of the list element to focus on.
91 | Options: Common optic options.
92 |

93 |

returns: An opaque optic record.

94 |

95 | Focus on the nth element of a list. As with lists:nth/2, indexing 96 | begins at 1.

97 | 98 |

Example:

99 | 100 |
  > optic:get([optic_lists:nth(1)], [1,2,3]).
101 |   {ok,[1]}

102 | 103 |

tail/0

104 |
105 |

tail() -> optic:optic()

106 |
107 |

See also: tail/1.

108 | 109 |

tail/1

110 |
111 |

tail(Options) -> optic:optic() 112 |

113 |

Options: Common optic options.
114 |

115 |

returns: An opaque optic record.

116 |

117 | Focus on the tail of a list. A list must have at least one element 118 | to have a tail.

119 | 120 |

Example:

121 | 122 |
  > optic:get([optic_lists:tail()], [1,2,3]).
123 |   {ok,[2,3]}

124 |
125 | 126 | 127 |

Generated by EDoc

128 | 129 | 130 | -------------------------------------------------------------------------------- /doc/optic_lists.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_lists # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to lists. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1 16 | Focus on all elements of a list.
head/0
head/1 17 | Focus on the head of a list.
nth/1
nth/2 18 | Focus on the nth element of a list.
tail/0
tail/1 19 | Focus on the tail of a list.
20 | 21 | 22 | 23 | 24 | ## Function Details ## 25 | 26 | 27 | 28 | ### all/0 ### 29 | 30 |

 31 | all() -> optic:optic()
 32 | 
33 |
34 | 35 | __See also:__ [all/1](#all-1). 36 | 37 | 38 | 39 | ### all/1 ### 40 | 41 |

 42 | all(Options) -> optic:optic()
 43 | 
44 | 45 | 46 | 47 | `Options`: Common optic options.
48 | 49 | returns: An opaque optic record. 50 | 51 | Focus on all elements of a list. 52 | 53 | Example: 54 | 55 | ``` 56 | > optic:get([optic_lists:all()], [1,2,3]). 57 | {ok,[1,2,3]} 58 | ``` 59 | 60 | 61 | 62 | ### head/0 ### 63 | 64 |

 65 | head() -> optic:optic()
 66 | 
67 |
68 | 69 | __See also:__ [head/1](#head-1). 70 | 71 | 72 | 73 | ### head/1 ### 74 | 75 |

 76 | head(Options) -> optic:optic()
 77 | 
78 | 79 | 80 | 81 | `Options`: Common optic options.
82 | 83 | returns: An opaque optic record. 84 | 85 | Focus on the head of a list. The list must have at least one 86 | element to have a head. 87 | 88 | Example: 89 | 90 | ``` 91 | > optic:get([optic_lists:head()], [1,2,3]). 92 | {ok,[1]} 93 | ``` 94 | 95 | 96 | 97 | ### nth/1 ### 98 | 99 |

100 | nth(N) -> optic:optic()
101 | 
102 | 103 | 104 | 105 | __See also:__ [nth/2](#nth-2). 106 | 107 | 108 | 109 | ### nth/2 ### 110 | 111 |

112 | nth(N, Options) -> optic:optic()
113 | 
114 | 115 | 116 | 117 | `N`: The index of the list element to focus on.
`Options`: Common optic options.
118 | 119 | returns: An opaque optic record. 120 | 121 | Focus on the nth element of a list. As with `lists:nth/2`, indexing 122 | begins at 1. 123 | 124 | Example: 125 | 126 | ``` 127 | > optic:get([optic_lists:nth(1)], [1,2,3]). 128 | {ok,[1]} 129 | ``` 130 | 131 | 132 | 133 | ### tail/0 ### 134 | 135 |

136 | tail() -> optic:optic()
137 | 
138 |
139 | 140 | __See also:__ [tail/1](#tail-1). 141 | 142 | 143 | 144 | ### tail/1 ### 145 | 146 |

147 | tail(Options) -> optic:optic()
148 | 
149 | 150 | 151 | 152 | `Options`: Common optic options.
153 | 154 | returns: An opaque optic record. 155 | 156 | Focus on the tail of a list. A list must have at least one element 157 | to have a tail. 158 | 159 | Example: 160 | 161 | ``` 162 | > optic:get([optic_lists:tail()], [1,2,3]). 163 | {ok,[2,3]} 164 | ``` 165 | 166 | -------------------------------------------------------------------------------- /doc/optic_maps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_maps 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_maps

13 | 14 | A set of optics specific to maps. 15 | 16 | 17 |

Description

18 | A set of optics specific to maps. 19 |

Function Index

20 | 21 | 22 | 23 | 25 | 26 | 28 | 29 | 31 | 32 | 34 | 35 | 37 |
all/0
all/1
association/1
association/2 24 | Focus on the association for a map key.
associations/0
associations/1 27 | Focus on all associations of a map.
key/1
key/2 30 | Focus on the value of a map key.
keys/0
keys/1 33 | Focus on all keys of a map.
values/0
values/1 36 | Focus on all values of a map.
38 | 39 |

Function Details

40 | 41 |

all/0

42 |
43 |

all() -> optic:optic()

44 |
45 |

See also: values/1.

46 | 47 |

all/1

48 |
49 |

all(Options) -> optic:optic() 50 |

51 |
52 |

See also: values/1.

53 | 54 |

association/1

55 |
56 |

association(Key) -> optic:optic() 57 |

58 |
59 |

See also: association/2.

60 | 61 |

association/2

62 |
63 |

association(Key, Options) -> optic:optic() 64 |

65 |

Key: The key to focus on.
66 | Options: Common optic options.
67 |

68 |

returns: An opaque optic record.

69 |

70 | Focus on the association for a map key. An association is the tuple 71 | of a map key and value. If the key is modified, the optic is no 72 | longer well behaved.

73 | 74 |

Example:

75 | 76 |
  > optic:get([optic_maps:association(first)], #{first => 1, second => 2}).
 77 |   {ok,[{first,1}]}

78 | 79 |

associations/0

80 |
81 |

associations() -> optic:optic()

82 |
83 |

See also: associations/1.

84 | 85 |

associations/1

86 |
87 |

associations(Options) -> optic:optic() 88 |

89 |

Options: Common optic options.
90 |

91 |

returns: An opaque optic record.

92 |

93 | Focus on all associations of a map. An association is a tuple of 94 | the key and value for each entry.

95 | 96 |

Example:

97 | 98 |
  > optic:get([optic_maps:associations()], #{first => 1, second => 2}).
 99 |   {ok,[{first,1},{second,2}]}

100 | 101 |

key/1

102 |
103 |

key(Key) -> optic:optic() 104 |

105 |
106 |

See also: key/2.

107 | 108 |

key/2

109 |
110 |

key(Key, Options) -> optic:optic() 111 |

112 |

Key: The key to focus on.
113 | Options: Common optic options.
114 |

115 |

returns: An opaque optic record.

116 |

117 | Focus on the value of a map key.

118 | 119 |

Example:

120 | 121 |
  > optic:get([optic_maps:key(first)], #{first => 1, second => 2}).
122 |   {ok,[1]}

123 | 124 |

keys/0

125 |
126 |

keys() -> optic:optic()

127 |
128 |

See also: keys/1.

129 | 130 |

keys/1

131 |
132 |

keys(Options) -> optic:optic() 133 |

134 |

Options: Common optic options.
135 |

136 |

returns: An opaque optic record.

137 |

138 | Focus on all keys of a map.

139 | 140 |

Example:

141 | 142 |
  > optic:get([optic_maps:keys()], #{first => 1, second => 2}).
143 |   {ok,[first,second]}

144 | 145 |

values/0

146 |
147 |

values() -> optic:optic()

148 |
149 |

See also: values/1.

150 | 151 |

values/1

152 |
153 |

values(Options) -> optic:optic() 154 |

155 |

Options: Common optic options.
156 |

157 |

returns: An opaque optic record.

158 |

159 | Focus on all values of a map.

160 | 161 |

Example:

162 | 163 |
  > optic:get([optic_maps:values()], #{first => 1, second => 2}).
164 |   {ok,[1,2]}

165 |
166 | 167 | 168 |

Generated by EDoc

169 | 170 | 171 | -------------------------------------------------------------------------------- /doc/optic_maps.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_maps # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to maps. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1
association/1
association/2 16 | Focus on the association for a map key.
associations/0
associations/1 17 | Focus on all associations of a map.
key/1
key/2 18 | Focus on the value of a map key.
keys/0
keys/1 19 | Focus on all keys of a map.
values/0
values/1 20 | Focus on all values of a map.
21 | 22 | 23 | 24 | 25 | ## Function Details ## 26 | 27 | 28 | 29 | ### all/0 ### 30 | 31 |

 32 | all() -> optic:optic()
 33 | 
34 |
35 | 36 | __See also:__ [values/1](#values-1). 37 | 38 | 39 | 40 | ### all/1 ### 41 | 42 |

 43 | all(Options) -> optic:optic()
 44 | 
45 | 46 | 47 | 48 | __See also:__ [values/1](#values-1). 49 | 50 | 51 | 52 | ### association/1 ### 53 | 54 |

 55 | association(Key) -> optic:optic()
 56 | 
57 | 58 | 59 | 60 | __See also:__ [association/2](#association-2). 61 | 62 | 63 | 64 | ### association/2 ### 65 | 66 |

 67 | association(Key, Options) -> optic:optic()
 68 | 
69 | 70 | 71 | 72 | `Key`: The key to focus on.
`Options`: Common optic options.
73 | 74 | returns: An opaque optic record. 75 | 76 | Focus on the association for a map key. An association is the tuple 77 | of a map key and value. If the key is modified, the optic is no 78 | longer well behaved. 79 | 80 | Example: 81 | 82 | ``` 83 | > optic:get([optic_maps:association(first)], #{first => 1, second => 2}). 84 | {ok,[{first,1}]} 85 | ``` 86 | 87 | 88 | 89 | ### associations/0 ### 90 | 91 |

 92 | associations() -> optic:optic()
 93 | 
94 |
95 | 96 | __See also:__ [associations/1](#associations-1). 97 | 98 | 99 | 100 | ### associations/1 ### 101 | 102 |

103 | associations(Options) -> optic:optic()
104 | 
105 | 106 | 107 | 108 | `Options`: Common optic options.
109 | 110 | returns: An opaque optic record. 111 | 112 | Focus on all associations of a map. An association is a tuple of 113 | the key and value for each entry. 114 | 115 | Example: 116 | 117 | ``` 118 | > optic:get([optic_maps:associations()], #{first => 1, second => 2}). 119 | {ok,[{first,1},{second,2}]} 120 | ``` 121 | 122 | 123 | 124 | ### key/1 ### 125 | 126 |

127 | key(Key) -> optic:optic()
128 | 
129 | 130 | 131 | 132 | __See also:__ [key/2](#key-2). 133 | 134 | 135 | 136 | ### key/2 ### 137 | 138 |

139 | key(Key, Options) -> optic:optic()
140 | 
141 | 142 | 143 | 144 | `Key`: The key to focus on.
`Options`: Common optic options.
145 | 146 | returns: An opaque optic record. 147 | 148 | Focus on the value of a map key. 149 | 150 | Example: 151 | 152 | ``` 153 | > optic:get([optic_maps:key(first)], #{first => 1, second => 2}). 154 | {ok,[1]} 155 | ``` 156 | 157 | 158 | 159 | ### keys/0 ### 160 | 161 |

162 | keys() -> optic:optic()
163 | 
164 |
165 | 166 | __See also:__ [keys/1](#keys-1). 167 | 168 | 169 | 170 | ### keys/1 ### 171 | 172 |

173 | keys(Options) -> optic:optic()
174 | 
175 | 176 | 177 | 178 | `Options`: Common optic options.
179 | 180 | returns: An opaque optic record. 181 | 182 | Focus on all keys of a map. 183 | 184 | Example: 185 | 186 | ``` 187 | > optic:get([optic_maps:keys()], #{first => 1, second => 2}). 188 | {ok,[first,second]} 189 | ``` 190 | 191 | 192 | 193 | ### values/0 ### 194 | 195 |

196 | values() -> optic:optic()
197 | 
198 |
199 | 200 | __See also:__ [values/1](#values-1). 201 | 202 | 203 | 204 | ### values/1 ### 205 | 206 |

207 | values(Options) -> optic:optic()
208 | 
209 | 210 | 211 | 212 | `Options`: Common optic options.
213 | 214 | returns: An opaque optic record. 215 | 216 | Focus on all values of a map. 217 | 218 | Example: 219 | 220 | ``` 221 | > optic:get([optic_maps:values()], #{first => 1, second => 2}). 222 | {ok,[1,2]} 223 | ``` 224 | 225 | -------------------------------------------------------------------------------- /doc/optic_orddict.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_orddict # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to orddicts. 9 | 10 | 11 | 12 | ## Description ## 13 | As orddicts are internally represented as a list of pairs, the 14 | type checks used here are not as reliable as those used for other 15 | optics. Please ensure via other means that these optics are only 16 | used with actual orddicts. 17 | 18 | ## Function Index ## 19 | 20 | 21 |
all/0
all/1
association/1
association/2 22 | Focus on the association for an orddict key.
associations/0
associations/1 23 | Focus on all associations of an orddict.
key/1
key/2 24 | Focus on the value of an orddict key.
keys/0
keys/1 25 | Focus on all keys of an orddict.
values/0
values/1 26 | Focus on all values of an orddict.
27 | 28 | 29 | 30 | 31 | ## Function Details ## 32 | 33 | 34 | 35 | ### all/0 ### 36 | 37 |

 38 | all() -> optic:optic()
 39 | 
40 |
41 | 42 | __See also:__ [values/1](#values-1). 43 | 44 | 45 | 46 | ### all/1 ### 47 | 48 |

 49 | all(Options) -> optic:optic()
 50 | 
51 | 52 | 53 | 54 | __See also:__ [values/1](#values-1). 55 | 56 | 57 | 58 | ### association/1 ### 59 | 60 |

 61 | association(Key) -> optic:optic()
 62 | 
63 | 64 | 65 | 66 | __See also:__ [association/2](#association-2). 67 | 68 | 69 | 70 | ### association/2 ### 71 | 72 |

 73 | association(Key, Options) -> optic:optic()
 74 | 
75 | 76 | 77 | 78 | `Key`: The key to focus on.
`Options`: Common optic options.
79 | 80 | returns: An opaque optic record. 81 | 82 | Focus on the association for an orddict key. An association is the 83 | tuple of a orddict key and value. If the key is modified, the optic is 84 | no longer well behaved. 85 | 86 | Example: 87 | 88 | ``` 89 | > optic:get([optic_orddict:association(first)], 90 | orddict:from_list([{first, 1}, {second, 2}])). 91 | {ok,[{first,1}]} 92 | ``` 93 | 94 | 95 | 96 | ### associations/0 ### 97 | 98 |

 99 | associations() -> optic:optic()
100 | 
101 |
102 | 103 | __See also:__ [associations/1](#associations-1). 104 | 105 | 106 | 107 | ### associations/1 ### 108 | 109 |

110 | associations(Options) -> optic:optic()
111 | 
112 | 113 | 114 | 115 | `Options`: Common optic options.
116 | 117 | returns: An opaque optic record. 118 | 119 | Focus on all associations of an orddict. An association is a tuple 120 | of the key and value for each entry. 121 | 122 | Example: 123 | 124 | ``` 125 | > optic:get([optic_orddict:associations()], 126 | orddict:from_list([{first, 1}, {second, 2}])). 127 | {ok,[{first,1},{second,2}]} 128 | ``` 129 | 130 | 131 | 132 | ### key/1 ### 133 | 134 |

135 | key(Key) -> optic:optic()
136 | 
137 | 138 | 139 | 140 | __See also:__ [key/2](#key-2). 141 | 142 | 143 | 144 | ### key/2 ### 145 | 146 |

147 | key(Key, Options) -> optic:optic()
148 | 
149 | 150 | 151 | 152 | `Key`: The key to focus on.
`Options`: Common optic options.
153 | 154 | returns: An opaque optic record. 155 | 156 | Focus on the value of an orddict key. 157 | 158 | Example: 159 | 160 | ``` 161 | > optic:get([optic_orddict:key(first)], 162 | orddict:from_list([{first, 1}, {second, 2}])). 163 | {ok,[1]} 164 | ``` 165 | 166 | 167 | 168 | ### keys/0 ### 169 | 170 |

171 | keys() -> optic:optic()
172 | 
173 |
174 | 175 | __See also:__ [keys/1](#keys-1). 176 | 177 | 178 | 179 | ### keys/1 ### 180 | 181 |

182 | keys(Options) -> optic:optic()
183 | 
184 | 185 | 186 | 187 | `Options`: Common optic options.
188 | 189 | returns: An opaque optic record. 190 | 191 | Focus on all keys of an orddict. 192 | 193 | Example: 194 | 195 | ``` 196 | > optic:get([optic_orddict:keys()], 197 | orddict:from_list([{first, 1}, {second, 2}])). 198 | {ok,[first,second]} 199 | ``` 200 | 201 | 202 | 203 | ### values/0 ### 204 | 205 |

206 | values() -> optic:optic()
207 | 
208 |
209 | 210 | __See also:__ [values/1](#values-1). 211 | 212 | 213 | 214 | ### values/1 ### 215 | 216 |

217 | values(Options) -> optic:optic()
218 | 
219 | 220 | 221 | 222 | `Options`: Common optic options.
223 | 224 | returns: An opaque optic record. 225 | 226 | Focus on all values of an orddict. 227 | 228 | Example: 229 | 230 | ``` 231 | > optic:get([optic_orddict:values()], 232 | orddict:from_list([{first, 1}, {second, 2}])). 233 | {ok,[1,2]} 234 | ``` 235 | 236 | -------------------------------------------------------------------------------- /doc/optic_ordsets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_ordsets 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_ordsets

13 | 14 | A set of optics specific to ordsets. 15 | 16 | 17 |

Description

18 | A set of optics specific to ordsets.

19 | 20 | As ordsets are internally represented as a plain list, the type 21 | checks used here are not as reliable as those used for other 22 | optics. Please ensure via other means that these optics are only 23 | used with actual ordsets. 24 |

Function Index

25 | 26 | 28 |
all/0
all/1 27 | Focus on all elements of an ordset.
29 | 30 |

Function Details

31 | 32 |

all/0

33 |
34 |

all() -> optic:optic()

35 |
36 |

See also: all/1.

37 | 38 |

all/1

39 |
40 |

all(Options) -> optic:optic() 41 |

42 |

Options: Common optic options.
43 |

44 |

returns: An opaque optic record.

45 |

46 | Focus on all elements of an ordset.

47 | 48 |

Example:

49 | 50 |
  > optic:get([optic_ordsets:all()], ordsets:from_list([1,2,3])).
51 |   {ok,[1,2,3]}

52 |
53 | 54 | 55 |

Generated by EDoc

56 | 57 | 58 | -------------------------------------------------------------------------------- /doc/optic_ordsets.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_ordsets # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to ordsets. 9 | 10 | 11 | 12 | ## Description ## 13 | As ordsets are internally represented as a plain list, the type 14 | checks used here are not as reliable as those used for other 15 | optics. Please ensure via other means that these optics are only 16 | used with actual ordsets. 17 | 18 | ## Function Index ## 19 | 20 | 21 |
all/0
all/1 22 | Focus on all elements of an ordset.
23 | 24 | 25 | 26 | 27 | ## Function Details ## 28 | 29 | 30 | 31 | ### all/0 ### 32 | 33 |

34 | all() -> optic:optic()
35 | 
36 |
37 | 38 | __See also:__ [all/1](#all-1). 39 | 40 | 41 | 42 | ### all/1 ### 43 | 44 |

45 | all(Options) -> optic:optic()
46 | 
47 | 48 | 49 | 50 | `Options`: Common optic options.
51 | 52 | returns: An opaque optic record. 53 | 54 | Focus on all elements of an ordset. 55 | 56 | Example: 57 | 58 | ``` 59 | > optic:get([optic_ordsets:all()], ordsets:from_list([1,2,3])). 60 | {ok,[1,2,3]} 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /doc/optic_path.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_path 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_path

13 | 14 | Utility functions for constructing optics from lists of selectors. 15 | 16 | 17 |

Description

18 | Utility functions for constructing optics from lists of selectors. 19 |

Data Types

20 | 21 |

path()

22 |

path() = string() | binary() | non_neg_integer() | '*'

23 |

A single path component.

24 | 25 |

paths()

26 |

paths() = [path()]

27 |

A list of path components.

28 | 29 |

Function Index

30 | 32 |
new/1 31 | Construct a list of optics from a path.
33 | 34 |

Function Details

35 | 36 |

new/1

37 |
38 |

new(Paths) -> optic:optics() 39 |

40 |

Paths: A list of path components to convert.
41 |

42 |

returns: A list of opaque optic records.

43 |

44 | Construct a list of optics from a path. The type of the path 45 | component determines the optic used:

46 | 47 | 53 | 54 |

This heavily depends on the optic_generic module, see the optics 55 | there for the full list of containers supported.

56 | 57 |

Example:

58 | 59 |
  > optic:get(optic_path(["first"]), ${"first" => 1, "second" => 2}).
60 |   {ok,[1]}

61 |
62 | 63 | 64 |

Generated by EDoc

65 | 66 | 67 | -------------------------------------------------------------------------------- /doc/optic_path.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_path # 4 | * [Description](#description) 5 | * [Data Types](#types) 6 | * [Function Index](#index) 7 | * [Function Details](#functions) 8 | 9 | Utility functions for constructing optics from lists of selectors. 10 | 11 | 12 | 13 | ## Data Types ## 14 | 15 | 16 | 17 | 18 | ### path() ### 19 | 20 | 21 |

22 | path() = string() | binary() | non_neg_integer() | *
23 | 
24 | 25 | A single path component. 26 | 27 | 28 | 29 | ### paths() ### 30 | 31 | 32 |

33 | paths() = [path()]
34 | 
35 | 36 | A list of path components. 37 | 38 | 39 | 40 | ## Function Index ## 41 | 42 | 43 |
new/1 44 | Construct a list of optics from a path.
45 | 46 | 47 | 48 | 49 | ## Function Details ## 50 | 51 | 52 | 53 | ### new/1 ### 54 | 55 |

56 | new(Paths) -> optic:optics()
57 | 
58 | 59 | 60 | 61 | `Paths`: A list of path components to convert.
62 | 63 | returns: A list of opaque optic records. 64 | 65 | Construct a list of optics from a path. The type of the path 66 | component determines the optic used: 67 | 68 | * string: A key for a map-like structure. 69 | 70 | * binary: A key for a map-like structure. 71 | 72 | * integer: An index into a list-like structure. 73 | 74 | * '*': All elements of a list. 75 | 76 | 77 | This heavily depends on the `optic_generic` module, see the optics 78 | there for the full list of containers supported. 79 | 80 | Example: 81 | 82 | ``` 83 | > optic:get(optic_path(["first"]), ${"first" => 1, "second" => 2}). 84 | {ok,[1]} 85 | ``` 86 | 87 | -------------------------------------------------------------------------------- /doc/optic_proplists.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_proplists 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_proplists

13 | 14 | A set of optics specific to proplists. 15 | 16 | 17 |

Description

18 | A set of optics specific to proplists. 19 |

Function Index

20 | 21 | 22 | 23 | 25 | 26 | 28 | 29 | 31 | 32 | 34 | 35 | 37 |
all/0
all/1
key/1
key/2 24 | Focus on the value of a property list key.
keys/0
keys/1 27 | Focus on all keys of a list of properties.
properties/0
properties/1 30 | Focus on all properties of a list of properties.
property/1
property/2 33 | Focus on a property in a property list by key.
values/0
values/1 36 | Focus on all values of a list of properties.
38 | 39 |

Function Details

40 | 41 |

all/0

42 |
43 |

all() -> optic:optic()

44 |
45 |

See also: values/1.

46 | 47 |

all/1

48 |
49 |

all(Options) -> optic:optic() 50 |

51 |
52 |

See also: values/1.

53 | 54 |

key/1

55 |
56 |

key(Key) -> optic:optic() 57 |

58 |
59 |

See also: key/2.

60 | 61 |

key/2

62 |
63 |

key(Key, Options) -> optic:optic() 64 |

65 |

Key: The key to focus on.
66 | Options: Common optic options.
67 |

68 |

returns: An opaque optic record.

69 |

70 | Focus on the value of a property list key. As keys may be 71 | duplicated, this may be multiple values. If the value is not given, 72 | it defaults to the atom true.

73 | 74 |

Example:

75 | 76 |
  > optic:get([optic_proplists:key(first)], [{first, 1}, {second, 2}]).
 77 |   {ok,[1]}

78 | 79 |

keys/0

80 |
81 |

keys() -> optic:optic()

82 |
83 |

See also: keys/1.

84 | 85 |

keys/1

86 |
87 |

keys(Options) -> optic:optic() 88 |

89 |

Options: Common optic options.
90 |

91 |

returns: An opaque optic record.

92 |

93 | Focus on all keys of a list of properties. Duplicate keys are 94 | preserved.

95 | 96 |

Example:

97 | 98 |
  > optic:get([optic_proplists:keys()], [{first, 1}, {second, 2}]).
 99 |   {ok,[first,second]}

100 | 101 |

properties/0

102 |
103 |

properties() -> optic:optic()

104 |
105 |

See also: properties/1.

106 | 107 |

properties/1

108 |
109 |

properties(Options) -> optic:optic() 110 |

111 |

Options: Common optic options.
112 |

113 |

returns: An opaque optic record.

114 |

115 | Focus on all properties of a list of properties. A propety is a 116 | tuple of a key and value. If a value was not given, it defaults to 117 | the atom true.

118 | 119 |

Example:

120 | 121 |
  > optic:get([optic_proplists:properties()], [{first, 1}, {second, 2}]).
122 |   {ok,[{first,1},{second,2}]}

123 | 124 |

property/1

125 |
126 |

property(Key) -> optic:optic() 127 |

128 |
129 |

See also: property/2.

130 | 131 |

property/2

132 |
133 |

property(Key, Options) -> optic:optic() 134 |

135 |

Key: The key to focus on.
136 | Options: Common optic options.
137 |

138 |

returns: An opaque optic record.

139 |

140 | Focus on a property in a property list by key. As keys may be 141 | duplicated, this may be multiple properties. If the value is not 142 | given, it defaults to the atom true. If the key is modified, the 143 | optic is no longer well behaved.

144 | 145 |

Example:

146 | 147 |
  > optic:get([optic_proplists:property(first)], [{first, 1}, {second, 2}]).
148 |   {ok,[{first,1}]}

149 | 150 |

values/0

151 |
152 |

values() -> optic:optic()

153 |
154 |

See also: values/1.

155 | 156 |

values/1

157 |
158 |

values(Options) -> optic:optic() 159 |

160 |

Options: Common optic options.
161 |

162 |

returns: An opaque optic record.

163 |

164 | Focus on all values of a list of properties.

165 | 166 |

Example:

167 | 168 |
  > optic:get([optic_proplists:values()], [{first, 1}, {second, 2}]).
169 |   {ok,[1,2]}

170 |
171 | 172 | 173 |

Generated by EDoc

174 | 175 | 176 | -------------------------------------------------------------------------------- /doc/optic_proplists.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_proplists # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to proplists. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1
key/1
key/2 16 | Focus on the value of a property list key.
keys/0
keys/1 17 | Focus on all keys of a list of properties.
properties/0
properties/1 18 | Focus on all properties of a list of properties.
property/1
property/2 19 | Focus on a property in a property list by key.
values/0
values/1 20 | Focus on all values of a list of properties.
21 | 22 | 23 | 24 | 25 | ## Function Details ## 26 | 27 | 28 | 29 | ### all/0 ### 30 | 31 |

 32 | all() -> optic:optic()
 33 | 
34 |
35 | 36 | __See also:__ [values/1](#values-1). 37 | 38 | 39 | 40 | ### all/1 ### 41 | 42 |

 43 | all(Options) -> optic:optic()
 44 | 
45 | 46 | 47 | 48 | __See also:__ [values/1](#values-1). 49 | 50 | 51 | 52 | ### key/1 ### 53 | 54 |

 55 | key(Key) -> optic:optic()
 56 | 
57 | 58 | 59 | 60 | __See also:__ [key/2](#key-2). 61 | 62 | 63 | 64 | ### key/2 ### 65 | 66 |

 67 | key(Key, Options) -> optic:optic()
 68 | 
69 | 70 | 71 | 72 | `Key`: The key to focus on.
`Options`: Common optic options.
73 | 74 | returns: An opaque optic record. 75 | 76 | Focus on the value of a property list key. As keys may be 77 | duplicated, this may be multiple values. If the value is not given, 78 | it defaults to the atom `true`. 79 | 80 | Example: 81 | 82 | ``` 83 | > optic:get([optic_proplists:key(first)], [{first, 1}, {second, 2}]). 84 | {ok,[1]} 85 | ``` 86 | 87 | 88 | 89 | ### keys/0 ### 90 | 91 |

 92 | keys() -> optic:optic()
 93 | 
94 |
95 | 96 | __See also:__ [keys/1](#keys-1). 97 | 98 | 99 | 100 | ### keys/1 ### 101 | 102 |

103 | keys(Options) -> optic:optic()
104 | 
105 | 106 | 107 | 108 | `Options`: Common optic options.
109 | 110 | returns: An opaque optic record. 111 | 112 | Focus on all keys of a list of properties. Duplicate keys are 113 | preserved. 114 | 115 | Example: 116 | 117 | ``` 118 | > optic:get([optic_proplists:keys()], [{first, 1}, {second, 2}]). 119 | {ok,[first,second]} 120 | ``` 121 | 122 | 123 | 124 | ### properties/0 ### 125 | 126 |

127 | properties() -> optic:optic()
128 | 
129 |
130 | 131 | __See also:__ [properties/1](#properties-1). 132 | 133 | 134 | 135 | ### properties/1 ### 136 | 137 |

138 | properties(Options) -> optic:optic()
139 | 
140 | 141 | 142 | 143 | `Options`: Common optic options.
144 | 145 | returns: An opaque optic record. 146 | 147 | Focus on all properties of a list of properties. A propety is a 148 | tuple of a key and value. If a value was not given, it defaults to 149 | the atom `true`. 150 | 151 | Example: 152 | 153 | ``` 154 | > optic:get([optic_proplists:properties()], [{first, 1}, {second, 2}]). 155 | {ok,[{first,1},{second,2}]} 156 | ``` 157 | 158 | 159 | 160 | ### property/1 ### 161 | 162 |

163 | property(Key) -> optic:optic()
164 | 
165 | 166 | 167 | 168 | __See also:__ [property/2](#property-2). 169 | 170 | 171 | 172 | ### property/2 ### 173 | 174 |

175 | property(Key, Options) -> optic:optic()
176 | 
177 | 178 | 179 | 180 | `Key`: The key to focus on.
`Options`: Common optic options.
181 | 182 | returns: An opaque optic record. 183 | 184 | Focus on a property in a property list by key. As keys may be 185 | duplicated, this may be multiple properties. If the value is not 186 | given, it defaults to the atom `true`. If the key is modified, the 187 | optic is no longer well behaved. 188 | 189 | Example: 190 | 191 | ``` 192 | > optic:get([optic_proplists:property(first)], [{first, 1}, {second, 2}]). 193 | {ok,[{first,1}]} 194 | ``` 195 | 196 | 197 | 198 | ### values/0 ### 199 | 200 |

201 | values() -> optic:optic()
202 | 
203 |
204 | 205 | __See also:__ [values/1](#values-1). 206 | 207 | 208 | 209 | ### values/1 ### 210 | 211 |

212 | values(Options) -> optic:optic()
213 | 
214 | 215 | 216 | 217 | `Options`: Common optic options.
218 | 219 | returns: An opaque optic record. 220 | 221 | Focus on all values of a list of properties. 222 | 223 | Example: 224 | 225 | ``` 226 | > optic:get([optic_proplists:values()], [{first, 1}, {second, 2}]). 227 | {ok,[1,2]} 228 | ``` 229 | 230 | -------------------------------------------------------------------------------- /doc/optic_sets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_sets 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_sets

13 | 14 | A set of optics specific to sets. 15 | 16 | 17 |

Description

18 | A set of optics specific to sets. 19 |

Function Index

20 | 21 | 23 |
all/0
all/1 22 | Focus on all elements of a set.
24 | 25 |

Function Details

26 | 27 |

all/0

28 |
29 |

all() -> optic:optic()

30 |
31 |

See also: all/1.

32 | 33 |

all/1

34 |
35 |

all(Options) -> optic:optic() 36 |

37 |

Options: Common optic options.
38 |

39 |

returns: An opaque optic record.

40 |

41 | Focus on all elements of a set.

42 | 43 |

Example:

44 | 45 |
  > optic:get([optic_sets:all()], sets:from_list([1,2,3])).
46 |   {ok,[1,2,3]}

47 |
48 | 49 | 50 |

Generated by EDoc

51 | 52 | 53 | -------------------------------------------------------------------------------- /doc/optic_sets.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_sets # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to sets. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1 16 | Focus on all elements of a set.
17 | 18 | 19 | 20 | 21 | ## Function Details ## 22 | 23 | 24 | 25 | ### all/0 ### 26 | 27 |

28 | all() -> optic:optic()
29 | 
30 |
31 | 32 | __See also:__ [all/1](#all-1). 33 | 34 | 35 | 36 | ### all/1 ### 37 | 38 |

39 | all(Options) -> optic:optic()
40 | 
41 | 42 | 43 | 44 | `Options`: Common optic options.
45 | 46 | returns: An opaque optic record. 47 | 48 | Focus on all elements of a set. 49 | 50 | Example: 51 | 52 | ``` 53 | > optic:get([optic_sets:all()], sets:from_list([1,2,3])). 54 | {ok,[1,2,3]} 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /doc/optic_tuples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Module optic_tuples 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Module optic_tuples

13 | 14 | A set of optics specific to tuples. 15 | 16 | 17 |

Description

18 | A set of optics specific to tuples. 19 |

Function Index

20 | 21 | 23 | 24 | 26 | 27 | 29 |
all/0
all/1 22 | Focus on all elements of a tuple.
element/1
element/2 25 | Focus on the nth element of a tuple.
field/3
field/4 28 | Focus on a record field.
30 | 31 |

Function Details

32 | 33 |

all/0

34 |
35 |

all() -> optic:optic()

36 |
37 |

See also: all/1.

38 | 39 |

all/1

40 |
41 |

all(Options) -> optic:optic() 42 |

43 |

Options: Common optic options.
44 |

45 |

returns: An opaque optic record.

46 |

47 | Focus on all elements of a tuple.

48 | 49 |

Example:

50 | 51 |
  > optic:get([optic_tuples:all()], {1,2,3}).
 52 |   {ok,[1,2,3]}

53 | 54 |

element/1

55 |
56 |

element(N) -> optic:optic() 57 |

58 |
59 |

See also: element/2.

60 | 61 |

element/2

62 |
63 |

element(N, Options) -> optic:optic() 64 |

65 |

N: The index of the tuple element to focus on.
66 | Options: Common optic options.
67 |

68 |

returns: An opaque optic record.

69 |

70 | Focus on the nth element of a tuple. As with erlang:element/2, 71 | indexing begins at 1.

72 | 73 |

Example:

74 | 75 |
  > optic:get([optic_tuples:element(1)], {1,2,3}).
 76 |   {ok,[1]}

77 | 78 |

field/3

79 |
80 |

field(Tag, Size, N) -> optic:optic() 81 |

82 |
83 |

See also: field/4.

84 | 85 |

field/4

86 |
87 |

field(Tag, Size, N, Options) -> optic:optic() 88 |

89 |

Tag: The expected record tag.
90 | Size: The expected record size.
91 | N: The index of the field in the record tuple.
92 | Options: Common optic options.
93 |

94 |

returns: An opaque optic record.

95 |

96 | Focus on a record field. As records are a compiler construct, this 97 | depends on the ?OPTIC_FIELD macro in include/optic_tuples.hrl 98 | to construct the required arguments from the record definition.

99 | 100 |

Given the record definition:

101 | 102 |
  -include_lib("optic/include/optic_tuples.hrl").
103 |   -record(example, {first}).
104 | 105 |

Example:

106 | 107 |
  > optic:get([optic_tuples:field(?OPTIC_FIELD(example, first))],
108 |               #example{first=1}).
109 |   {ok,[1]}

110 |
111 | 112 | 113 |

Generated by EDoc

114 | 115 | 116 | -------------------------------------------------------------------------------- /doc/optic_tuples.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Module optic_tuples # 4 | * [Description](#description) 5 | * [Function Index](#index) 6 | * [Function Details](#functions) 7 | 8 | A set of optics specific to tuples. 9 | 10 | 11 | 12 | ## Function Index ## 13 | 14 | 15 |
all/0
all/1 16 | Focus on all elements of a tuple.
element/1
element/2 17 | Focus on the nth element of a tuple.
field/3
field/4 18 | Focus on a record field.
19 | 20 | 21 | 22 | 23 | ## Function Details ## 24 | 25 | 26 | 27 | ### all/0 ### 28 | 29 |

 30 | all() -> optic:optic()
 31 | 
32 |
33 | 34 | __See also:__ [all/1](#all-1). 35 | 36 | 37 | 38 | ### all/1 ### 39 | 40 |

 41 | all(Options) -> optic:optic()
 42 | 
43 | 44 | 45 | 46 | `Options`: Common optic options.
47 | 48 | returns: An opaque optic record. 49 | 50 | Focus on all elements of a tuple. 51 | 52 | Example: 53 | 54 | ``` 55 | > optic:get([optic_tuples:all()], {1,2,3}). 56 | {ok,[1,2,3]} 57 | ``` 58 | 59 | 60 | 61 | ### element/1 ### 62 | 63 |

 64 | element(N) -> optic:optic()
 65 | 
66 | 67 | 68 | 69 | __See also:__ [element/2](#element-2). 70 | 71 | 72 | 73 | ### element/2 ### 74 | 75 |

 76 | element(N, Options) -> optic:optic()
 77 | 
78 | 79 | 80 | 81 | `N`: The index of the tuple element to focus on.
`Options`: Common optic options.
82 | 83 | returns: An opaque optic record. 84 | 85 | Focus on the nth element of a tuple. As with `erlang:element/2`, 86 | indexing begins at 1. 87 | 88 | Example: 89 | 90 | ``` 91 | > optic:get([optic_tuples:element(1)], {1,2,3}). 92 | {ok,[1]} 93 | ``` 94 | 95 | 96 | 97 | ### field/3 ### 98 | 99 |

100 | field(Tag, Size, N) -> optic:optic()
101 | 
102 | 103 | 104 | 105 | __See also:__ [field/4](#field-4). 106 | 107 | 108 | 109 | ### field/4 ### 110 | 111 |

112 | field(Tag, Size, N, Options) -> optic:optic()
113 | 
114 | 115 | 116 | 117 | `Tag`: The expected record tag.
`Size`: The expected record size.
`N`: The index of the field in the record tuple.
`Options`: Common optic options.
118 | 119 | returns: An opaque optic record. 120 | 121 | Focus on a record field. As records are a compiler construct, this 122 | depends on the `?OPTIC_FIELD` macro in `include/optic_tuples.hrl` 123 | to construct the required arguments from the record definition. 124 | 125 | Given the record definition: 126 | 127 | ``` 128 | -include_lib("optic/include/optic_tuples.hrl"). 129 | -record(example, {first}). 130 | ``` 131 | 132 | Example: 133 | 134 | ``` 135 | > optic:get([optic_tuples:field(?OPTIC_FIELD(example, first))], 136 | #example{first=1}). 137 | {ok,[1]} 138 | ``` 139 | 140 | -------------------------------------------------------------------------------- /doc/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* standard EDoc style sheet */ 2 | body { 3 | font-family: Verdana, Arial, Helvetica, sans-serif; 4 | margin-left: .25in; 5 | margin-right: .2in; 6 | margin-top: 0.2in; 7 | margin-bottom: 0.2in; 8 | color: #000000; 9 | background-color: #ffffff; 10 | } 11 | h1,h2 { 12 | margin-left: -0.2in; 13 | } 14 | div.navbar { 15 | background-color: #add8e6; 16 | padding: 0.2em; 17 | } 18 | h2.indextitle { 19 | padding: 0.4em; 20 | background-color: #add8e6; 21 | } 22 | h3.function,h3.typedecl { 23 | background-color: #add8e6; 24 | padding-left: 1em; 25 | } 26 | div.spec { 27 | margin-left: 2em; 28 | background-color: #eeeeee; 29 | } 30 | a.module { 31 | text-decoration:none 32 | } 33 | a.module:hover { 34 | background-color: #eeeeee; 35 | } 36 | ul.definitions { 37 | list-style-type: none; 38 | } 39 | ul.index { 40 | list-style-type: none; 41 | background-color: #eeeeee; 42 | } 43 | 44 | /* 45 | * Minor style tweaks 46 | */ 47 | ul { 48 | list-style-type: square; 49 | } 50 | table { 51 | border-collapse: collapse; 52 | } 53 | td { 54 | padding: 3 55 | } 56 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3" 3 | 4 | services: 5 | 6 | test: 7 | build: 8 | context: . 9 | container_name: partial 10 | command: test-unit 11 | -------------------------------------------------------------------------------- /include/optic_tuples.hrl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Macros for the optic_tuples module. 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | 7 | % This macro creates the first three parameters required by 8 | % optic_tuple:field/3 for selecting the field of a record. It requires 9 | % the record to be defined in the current module. 10 | -define(OPTIC_FIELD(Record, Field), (Record), record_info(size, (Record)), (#Record.Field)). 11 | -------------------------------------------------------------------------------- /rebar.config: -------------------------------------------------------------------------------- 1 | {minimum_otp_vsn, "18.0"}. 2 | 3 | {erl_opts, [debug_info, 4 | {warn_format, 1}, 5 | warn_export_all, 6 | warn_export_vars, 7 | warn_obsolete_guard, 8 | warn_unused_import] 9 | }. 10 | 11 | {plugins, [rebar3_hex]}. 12 | 13 | {dialyzer, [{plt_prefix, "optic"}, 14 | {warnings, [unmatched_returns, 15 | error_handling, 16 | race_conditions, 17 | underspecs]}] 18 | }. 19 | 20 | {xref_warnings, true}. 21 | 22 | {profiles, [{native, [{erl_opts, [{native, o3}, 23 | {d, 'NATIVE'}]}] 24 | }, 25 | {test, [{erl_opts, [{d, 'TEST'}]}, 26 | {deps, [proper]}, 27 | {plugins, [geas_rebar3, 28 | rebar3_lint, 29 | rebar3_proper]}, 30 | {dialyzer, [{plt_prefix, "optic_test"}]}] 31 | }, 32 | {markdown, [{deps, [edown]}, 33 | {edoc_opts, [{preprocess, true}, 34 | {doclet, edown_doclet}, 35 | {top_level_readme, {"./README.md", 36 | "http://github.com/jkrukoff/optic"}}]}] 37 | }] 38 | }. 39 | -------------------------------------------------------------------------------- /rebar.lock: -------------------------------------------------------------------------------- 1 | []. 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | docker-compose 2 | html2text 3 | yamllint 4 | -------------------------------------------------------------------------------- /src/optic.app.src: -------------------------------------------------------------------------------- 1 | {application, optic, 2 | [{pkg_name, "optic"}, 3 | {description, "A library for reading and updating deeply nested data."}, 4 | {vsn, "3.1.0"}, 5 | {applications, [kernel, 6 | stdlib]}, 7 | {modules, [optic]}, 8 | {registered, []}, 9 | {env, []}, 10 | {licenses, ["Apache 2.0"]}, 11 | {links, [{"GitHub", "https://github.com/jkrukoff/optic"}]}, 12 | {extra, [{maintainers, ["John Krukoff"]}]}]}. 13 | -------------------------------------------------------------------------------- /src/optic_array.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% A set of optics specific to arrays. 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(optic_array). 7 | 8 | %% API 9 | -export([all/0, 10 | all/1, 11 | nth/1, 12 | nth/2]). 13 | 14 | %%%=================================================================== 15 | %%% API 16 | %%%=================================================================== 17 | 18 | %% @see all/1 19 | -spec all() -> optic:optic(). 20 | all() -> 21 | all(#{}). 22 | 23 | %% @doc 24 | %% Focus on all values of an array. 25 | %% 26 | %% Example: 27 | %% 28 | %% ``` 29 | %% > optic:get([optic_array:all()], array:from_list([1,2,3])). 30 | %% {ok,[1,2,3]} 31 | %% ''' 32 | %% @end 33 | %% @param Options Common optic options. 34 | %% @returns An opaque optic record. 35 | -spec all(Options) -> optic:optic() when 36 | Options :: optic:variations(). 37 | all(Options) -> 38 | Fold = 39 | fun (Fun, Acc, Array) -> 40 | case is_array(Array) of 41 | true -> 42 | {ok, array:foldl(fun (_Index, Elem, InnerAcc) -> 43 | Fun(Elem, InnerAcc) 44 | end, Acc, Array)}; 45 | false -> 46 | {error, undefined} 47 | end 48 | end, 49 | MapFold = 50 | fun (Fun, Acc, Array) -> 51 | case is_array(Array) of 52 | true -> 53 | {ok, array:foldl(fun (Index, Elem, {InnerArray, InnerAcc}) -> 54 | {NewElem, NewAcc} = Fun(Elem, InnerAcc), 55 | {array:set(Index, NewElem, InnerArray), NewAcc} 56 | end, 57 | {Array, Acc}, 58 | Array)}; 59 | false -> 60 | {error, undefined} 61 | end 62 | end, 63 | New = 64 | fun (_Data, Template) -> 65 | array:new([{default, Template}]) 66 | end, 67 | Optic = optic:new(MapFold, Fold), 68 | optic:variations(Optic, Options, New). 69 | 70 | %% @see nth/2 71 | -spec nth(N) -> optic:optic() when 72 | N :: pos_integer(). 73 | nth(N) -> 74 | nth(N, #{}). 75 | 76 | %% @doc 77 | %% Focus on the nth value of an array. Like lists, but unlike the 78 | %% standard array operations, indexing begins at 1. 79 | %% 80 | %% Example: 81 | %% 82 | %% ``` 83 | %% > optic:get([optic_array:nth(1)], array:from_list([1,2,3])). 84 | %% {ok,[1]} 85 | %% ''' 86 | %% @end 87 | %% @param N The index of the array value to focus on. 88 | %% @param Options Common optic options. 89 | %% @returns An opaque optic record. 90 | -spec nth(N, Options) -> optic:optic() when 91 | N :: pos_integer(), 92 | Options :: optic:variations(). 93 | nth(N, Options) when N >= 1 -> 94 | Index = N - 1, 95 | Fold = 96 | fun (Fun, Acc, Array) -> 97 | case is_array(Array) andalso valid_index(Index, Array) of 98 | true -> 99 | Elem = array:get(Index, Array), 100 | {ok, Fun(Elem, Acc)}; 101 | false -> 102 | {error, undefined} 103 | end 104 | end, 105 | MapFold = 106 | fun (Fun, Acc, Array) -> 107 | case is_array(Array) andalso valid_index(Index, Array) of 108 | true -> 109 | Elem = array:get(Index, Array), 110 | {NewElem, NewAcc} = Fun(Elem, Acc), 111 | {ok, {array:set(Index, NewElem, Array), NewAcc}}; 112 | false -> 113 | {error, undefined} 114 | end 115 | end, 116 | New = 117 | fun (Data, Template) -> 118 | case is_array(Data) of 119 | true -> 120 | array:resize(N, Data); 121 | false -> 122 | array:new(N, [{default, Template}]) 123 | end 124 | end, 125 | Optic = optic:new(MapFold, Fold), 126 | optic:variations(Optic, Options, New). 127 | 128 | %%%=================================================================== 129 | %%% Internal Functions 130 | %%%=================================================================== 131 | 132 | is_array(Unknown) -> 133 | try array:size(Unknown) of 134 | _ -> 135 | true 136 | catch 137 | error:badarg -> 138 | false 139 | end. 140 | 141 | valid_index(Index, Array) when Index >= 0 -> 142 | case array:is_fix(Array) of 143 | true -> 144 | Index < array:size(Array); 145 | false -> 146 | true 147 | end. 148 | -------------------------------------------------------------------------------- /src/optic_gb_sets.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% A set of optics specific to gb_sets. 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(optic_gb_sets). 7 | 8 | %% API 9 | -export([all/0, 10 | all/1]). 11 | 12 | %%%=================================================================== 13 | %%% API 14 | %%%=================================================================== 15 | 16 | %% @see all/1 17 | -spec all() -> optic:optic(). 18 | all() -> 19 | all(#{}). 20 | 21 | %% @doc 22 | %% Focus on all elements of a gb_set. 23 | %% 24 | %% Example: 25 | %% 26 | %% ``` 27 | %% > optic:get([optic_gb_sets:all()], gb_sets:from_list([1,2,3])). 28 | %% {ok,[1,2,3]} 29 | %% ''' 30 | %% @end 31 | %% @param Options Common optic options. 32 | %% @returns An opaque optic record. 33 | -spec all(Options) -> optic:optic() when 34 | Options :: optic:variations(). 35 | all(Options) -> 36 | Fold = 37 | fun (Fun, Acc, Set) -> 38 | case is_gb_set(Set) of 39 | true -> 40 | {ok, gb_sets:fold(Fun, Acc, Set)}; 41 | false -> 42 | {error, undefined} 43 | end 44 | end, 45 | MapFold = 46 | fun (Fun, Acc, Set) -> 47 | case is_gb_set(Set) of 48 | true -> 49 | {ok, gb_sets:fold(fun (Elem, {InnerSet, InnerAcc}) -> 50 | {NewElem, NewAcc} = Fun(Elem, InnerAcc), 51 | {gb_sets:add_element(NewElem, InnerSet), NewAcc} 52 | end, 53 | {gb_sets:new(), Acc}, 54 | Set)}; 55 | false -> 56 | {error, undefined} 57 | end 58 | end, 59 | New = 60 | fun (_Data, _Template) -> 61 | gb_sets:new() 62 | end, 63 | Optic = optic:new(MapFold, Fold), 64 | optic:variations(Optic, Options, New). 65 | 66 | %%%=================================================================== 67 | %%% Internal Functions 68 | %%%=================================================================== 69 | 70 | is_gb_set(Unknown) -> 71 | try gb_sets:size(Unknown) of 72 | _ -> 73 | true 74 | catch 75 | error:function_clause -> 76 | false 77 | end. 78 | -------------------------------------------------------------------------------- /src/optic_generic.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% A set of generic optics that can be applied to multiple container 4 | %%% types. 5 | %%% 6 | %%% Intended both as a convenience and to support optic creation from 7 | %%% parsed paths in optic_path. 8 | %%% 9 | %%% Because of the ambiguous types they support, these optics do not 10 | %%% support the standard optic options. Instead, they always skip 11 | %%% unexpected types and never create missing values. 12 | %%% @end 13 | %%%------------------------------------------------------------------- 14 | -module(optic_generic). 15 | 16 | %% API 17 | -export([key/1, 18 | index/1]). 19 | 20 | %%%=================================================================== 21 | %%% API 22 | %%%=================================================================== 23 | 24 | %% @doc 25 | %% Focus on the value of many different key/value like mappings. 26 | %% Understands how to focus on maps, property lists, dicts, orddicts 27 | %% and gb_trees. Does not support the usual optic options. 28 | %% 29 | %% Example: 30 | %% 31 | %% ``` 32 | %% > optic:get([optic_generic:key(first)], #{first => 1}). 33 | %% {ok,[1]} 34 | %% ''' 35 | %% @end 36 | %% @param Key The key to focus on. 37 | %% @returns An opaque optic record. 38 | -spec key(Key) -> optic:optic() when 39 | Key :: term(). 40 | key(Key) -> 41 | Fold = 42 | fun (Fun, Acc, Map) when is_map(Map) -> 43 | case Map of 44 | #{Key:=Value} -> 45 | {ok, Fun(Value, Acc)}; 46 | _ -> 47 | {ok, Acc} 48 | end; 49 | (Fun, Acc, List) when is_list(List) -> 50 | % This might be a proplist or an orddict. 51 | Values = proplists:get_all_values(Key, List), 52 | {ok, lists:foldl(Fun, Acc, Values)}; 53 | (Fun, Acc, Unknown) -> 54 | case {is_dict(Unknown), is_gb_tree(Unknown)} of 55 | {true, _} -> 56 | % It's bad if is_dict & is_gb_tree ever both return 57 | % true, but I can't justify throwing an error when 58 | % this is already doing such fuzzy guessing of types. 59 | Dict = Unknown, 60 | case dict:find(Key, Dict) of 61 | {ok, Value} -> 62 | {ok, Fun(Value, Acc)}; 63 | error -> 64 | {ok, Acc} 65 | end; 66 | {false, true} -> 67 | Tree = Unknown, 68 | case gb_trees:lookup(Key, Tree) of 69 | {value, Value} -> 70 | {ok, Fun(Value, Acc)}; 71 | none -> 72 | {ok, Acc} 73 | end; 74 | {false, false} -> 75 | {ok, Acc} 76 | end 77 | end, 78 | MapFold = 79 | fun (Fun, Acc, Map) when is_map(Map) -> 80 | case Map of 81 | #{Key:=Value} -> 82 | {NewValue, NewAcc} = Fun(Value, Acc), 83 | {ok, {Map#{Key:=NewValue}, NewAcc}}; 84 | _ -> 85 | {ok, {Map, Acc}} 86 | end; 87 | (Fun, Acc, List) when is_list(List) -> 88 | % This might be a proplist or an orddict. 89 | {ok, lists:mapfoldl(fun (Elem, InnerAcc) -> 90 | case proplists:is_defined(Key, [Elem]) of 91 | true -> 92 | Value = proplists:get_value(Key, [Elem]), 93 | {NewValue, NewAcc} = Fun(Value, InnerAcc), 94 | {{Key, NewValue}, NewAcc}; 95 | false -> 96 | {Elem, InnerAcc} 97 | end 98 | end, 99 | Acc, 100 | List)}; 101 | (Fun, Acc, Unknown) -> 102 | case {is_dict(Unknown), is_gb_tree(Unknown)} of 103 | {true, _} -> 104 | % It's bad if is_dict & is_gb_tree ever both return 105 | % true, but I can't justify throwing an error when 106 | % this is already doing such fuzzy guessing of types. 107 | Dict = Unknown, 108 | case dict:find(Key, Dict) of 109 | {ok, Value} -> 110 | {NewValue, NewAcc} = Fun(Value, Acc), 111 | {ok, {dict:store(Key, NewValue, Dict), NewAcc}}; 112 | error -> 113 | {ok, {Dict, Acc}} 114 | end; 115 | {false, true} -> 116 | Tree = Unknown, 117 | case gb_trees:lookup(Key, Tree) of 118 | {value, Value} -> 119 | {NewValue, NewAcc} = Fun(Value, Acc), 120 | {ok, {gb_trees:update(Key, NewValue, Tree), NewAcc}}; 121 | none -> 122 | {ok, {Tree, Acc}} 123 | end; 124 | {false, false} -> 125 | {ok, {Unknown, Acc}} 126 | end 127 | end, 128 | optic:new(MapFold, Fold). 129 | 130 | %% @doc 131 | %% Focus on an element of a list like container. Indexing begins at 1. 132 | %% Understands how to focus on lists and tuples. Does not support the 133 | %% usual optic options. 134 | %% 135 | %% Example: 136 | %% 137 | %% ``` 138 | %% > optic:get([optic_generic:index(3)], [1, 2, 3]). 139 | %% {ok,[3]} 140 | %% ''' 141 | %% @end 142 | %% @param Index The one based index of the element to focus on. 143 | %% @returns An opaque optic record. 144 | -spec index(Index) -> optic:optic() when 145 | Index :: non_neg_integer(). 146 | index(Index) -> 147 | Fold = 148 | fun (Fun, Acc, List) when Index =< length(List) -> 149 | Elem = lists:nth(Index, List), 150 | {ok, Fun(Elem, Acc)}; 151 | (Fun, Acc, Tuple) when Index =< tuple_size(Tuple) -> 152 | Elem = erlang:element(Index, Tuple), 153 | {ok, Fun(Elem, Acc)}; 154 | (_Fun, Acc, _Data) -> 155 | {ok, Acc} 156 | end, 157 | MapFold = 158 | fun (Fun, Acc, List) when Index =< length(List) -> 159 | {Before, [Head | Tail]} = lists:split(Index - 1, List), 160 | {NewHead, NewAcc} = Fun(Head, Acc), 161 | {ok, {Before ++ [NewHead] ++ Tail, NewAcc}}; 162 | (Fun, Acc, Tuple) when Index =< tuple_size(Tuple) -> 163 | Elem = erlang:element(Index, Tuple), 164 | {NewElem, NewAcc} = Fun(Elem, Acc), 165 | {ok, {erlang:setelement(Index, Tuple, NewElem), NewAcc}}; 166 | (_Fun, Acc, Unknown) -> 167 | {ok, {Unknown, Acc}} 168 | end, 169 | optic:new(MapFold, Fold). 170 | 171 | %%%=================================================================== 172 | %%% Internal Functions 173 | %%%=================================================================== 174 | 175 | is_dict(Unknown) -> 176 | try dict:size(Unknown) of 177 | _ -> 178 | true 179 | catch 180 | error:function_clause -> 181 | false 182 | end. 183 | 184 | is_gb_tree(Unknown) -> 185 | try gb_trees:size(Unknown) of 186 | _ -> 187 | true 188 | catch 189 | error:function_clause -> 190 | false 191 | end. 192 | -------------------------------------------------------------------------------- /src/optic_lists.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% A set of optics specific to lists. 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(optic_lists). 7 | 8 | %% API 9 | -export([all/0, 10 | all/1, 11 | head/0, 12 | head/1, 13 | tail/0, 14 | tail/1, 15 | nth/1, 16 | nth/2]). 17 | 18 | %%%=================================================================== 19 | %%% API 20 | %%%=================================================================== 21 | 22 | %% @see all/1 23 | -spec all() -> optic:optic(). 24 | all() -> 25 | all(#{}). 26 | 27 | %% @doc 28 | %% Focus on all elements of a list. 29 | %% 30 | %% Example: 31 | %% 32 | %% ``` 33 | %% > optic:get([optic_lists:all()], [1,2,3]). 34 | %% {ok,[1,2,3]} 35 | %% ''' 36 | %% @end 37 | %% @param Options Common optic options. 38 | %% @returns An opaque optic record. 39 | -spec all(Options) -> optic:optic() when 40 | Options :: optic:variations(). 41 | all(Options) -> 42 | Fold = 43 | fun (Fun, Acc, List) when is_list(List) -> 44 | {ok, lists:foldl(Fun, Acc, List)}; 45 | (_, _, _) -> 46 | {error, undefined} 47 | end, 48 | MapFold = 49 | fun (Fun, Acc, List) when is_list(List) -> 50 | {ok, lists:mapfoldl(Fun, Acc, List)}; 51 | (_, _, _) -> 52 | {error, undefined} 53 | end, 54 | New = 55 | fun (_Data, _Template) -> 56 | [] 57 | end, 58 | Optic = optic:new(MapFold, Fold), 59 | optic:variations(Optic, Options, New). 60 | 61 | %% @see head/1 62 | -spec head() -> optic:optic(). 63 | head() -> 64 | head(#{}). 65 | 66 | %% @doc 67 | %% Focus on the head of a list. The list must have at least one 68 | %% element to have a head. 69 | %% 70 | %% Example: 71 | %% 72 | %% ``` 73 | %% > optic:get([optic_lists:head()], [1,2,3]). 74 | %% {ok,[1]} 75 | %% ''' 76 | %% @end 77 | %% @param Options Common optic options. 78 | %% @returns An opaque optic record. 79 | -spec head(Options) -> optic:optic() when 80 | Options :: optic:variations(). 81 | head(Options) -> 82 | Fold = 83 | fun (Fun, Acc, [Head | _]) -> 84 | {ok, Fun(Head, Acc)}; 85 | (_, _, _) -> 86 | {error, undefined} 87 | end, 88 | MapFold = 89 | fun (Fun, Acc, [Head | Tail]) -> 90 | {NewHead, NewAcc} = Fun(Head, Acc), 91 | {ok, {[NewHead | Tail], NewAcc}}; 92 | (_, _, _) -> 93 | {error, undefined} 94 | end, 95 | New = 96 | fun (_Data, Template) -> 97 | [Template] 98 | end, 99 | Optic = optic:new(MapFold, Fold), 100 | optic:variations(Optic, Options, New). 101 | 102 | %% @see tail/1 103 | -spec tail() -> optic:optic(). 104 | tail() -> 105 | tail(#{}). 106 | 107 | %% @doc 108 | %% Focus on the tail of a list. A list must have at least one element 109 | %% to have a tail. 110 | %% 111 | %% Example: 112 | %% 113 | %% ``` 114 | %% > optic:get([optic_lists:tail()], [1,2,3]). 115 | %% {ok,[2,3]} 116 | %% ''' 117 | %% @end 118 | %% @param Options Common optic options. 119 | %% @returns An opaque optic record. 120 | -spec tail(Options) -> optic:optic() when 121 | Options :: optic:variations(). 122 | tail(Options) -> 123 | Fold = 124 | fun (Fun, Acc, [_ | Tail]) -> 125 | {ok, lists:foldl(Fun, Acc, Tail)}; 126 | (_, _, _) -> 127 | {error, undefined} 128 | end, 129 | MapFold = 130 | fun (Fun, Acc, [Head | Tail]) -> 131 | {NewTail, NewAcc} = lists:mapfoldl(Fun, Acc, Tail), 132 | {ok, {[Head | NewTail], NewAcc}}; 133 | (_, _, _) -> 134 | {error, undefined} 135 | end, 136 | New = 137 | fun (_Data, Template) -> 138 | [Template] 139 | end, 140 | Optic = optic:new(MapFold, Fold), 141 | optic:variations(Optic, Options, New). 142 | 143 | %% @see nth/2 144 | -spec nth(N) -> optic:optic() when 145 | N :: pos_integer(). 146 | nth(N) -> 147 | nth(N, #{}). 148 | 149 | %% @doc 150 | %% Focus on the nth element of a list. As with `lists:nth/2', indexing 151 | %% begins at 1. 152 | %% 153 | %% Example: 154 | %% 155 | %% ``` 156 | %% > optic:get([optic_lists:nth(1)], [1,2,3]). 157 | %% {ok,[1]} 158 | %% ''' 159 | %% @end 160 | %% @param N The index of the list element to focus on. 161 | %% @param Options Common optic options. 162 | %% @returns An opaque optic record. 163 | -spec nth(N, Options) -> optic:optic() when 164 | N :: pos_integer(), 165 | Options :: optic:variations(). 166 | nth(N, Options) -> 167 | Fold = 168 | fun (Fun, Acc, List) when N =< length(List) -> 169 | Nth = lists:nth(N, List), 170 | {ok, Fun(Nth, Acc)}; 171 | (_, _, _) -> 172 | {error, undefined} 173 | end, 174 | MapFold = 175 | fun (Fun, Acc, List) when N =< length(List) -> 176 | {Before, [Head | Tail]} = lists:split(N - 1, List), 177 | {NewHead, NewAcc} = Fun(Head, Acc), 178 | {ok, {Before ++ [NewHead] ++ Tail, NewAcc}}; 179 | (_, _, _) -> 180 | {error, undefined} 181 | end, 182 | New = 183 | fun (Data, Template) when is_list(Data) -> 184 | Data ++ lists:duplicate(N - length(Data), Template); 185 | (_Data, Template) -> 186 | lists:duplicate(N, Template) 187 | end, 188 | Optic = optic:new(MapFold, Fold), 189 | optic:variations(Optic, Options, New). 190 | -------------------------------------------------------------------------------- /src/optic_ordsets.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% A set of optics specific to ordsets. 4 | %%% 5 | %%% As ordsets are internally represented as a plain list, the type 6 | %%% checks used here are not as reliable as those used for other 7 | %%% optics. Please ensure via other means that these optics are only 8 | %%% used with actual ordsets. 9 | %%% @end 10 | %%%------------------------------------------------------------------- 11 | -module(optic_ordsets). 12 | 13 | %% API 14 | -export([all/0, 15 | all/1]). 16 | 17 | %%%=================================================================== 18 | %%% API 19 | %%%=================================================================== 20 | 21 | %% @see all/1 22 | -spec all() -> optic:optic(). 23 | all() -> 24 | all(#{}). 25 | 26 | %% @doc 27 | %% Focus on all elements of an ordset. 28 | %% 29 | %% Example: 30 | %% 31 | %% ``` 32 | %% > optic:get([optic_ordsets:all()], ordsets:from_list([1,2,3])). 33 | %% {ok,[1,2,3]} 34 | %% ''' 35 | %% @end 36 | %% @param Options Common optic options. 37 | %% @returns An opaque optic record. 38 | -spec all(Options) -> optic:optic() when 39 | Options :: optic:variations(). 40 | all(Options) -> 41 | Fold = 42 | fun (Fun, Acc, Set) -> 43 | case is_ordset(Set) of 44 | true -> 45 | {ok, ordsets:fold(Fun, Acc, Set)}; 46 | false -> 47 | {error, undefined} 48 | end 49 | end, 50 | MapFold = 51 | fun (Fun, Acc, Set) -> 52 | case is_ordset(Set) of 53 | true -> 54 | {ok, ordsets:fold(fun (Elem, {InnerSet, InnerAcc}) -> 55 | {NewElem, NewAcc} = Fun(Elem, InnerAcc), 56 | {ordsets:add_element(NewElem, InnerSet), NewAcc} 57 | end, 58 | {ordsets:new(), Acc}, 59 | Set)}; 60 | false -> 61 | {error, undefined} 62 | end 63 | end, 64 | New = 65 | fun (_Data, _Template) -> 66 | ordsets:new() 67 | end, 68 | Optic = optic:new(MapFold, Fold), 69 | optic:variations(Optic, Options, New). 70 | 71 | %%%=================================================================== 72 | %%% Internal Functions 73 | %%%=================================================================== 74 | 75 | is_ordset(Unknown) when is_list(Unknown) -> 76 | true; 77 | is_ordset(_Unknown) -> 78 | false. 79 | -------------------------------------------------------------------------------- /src/optic_path.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Utility functions for constructing optics from lists of selectors. 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(optic_path). 7 | 8 | -type path() :: string() | binary() | non_neg_integer() | '*'. 9 | %% A single path component. 10 | -type paths() :: [path()]. 11 | %% A list of path components. 12 | 13 | %% API 14 | -export([new/1]). 15 | 16 | -export_type([path/0, 17 | paths/0]). 18 | 19 | %%%=================================================================== 20 | %%% API 21 | %%%=================================================================== 22 | 23 | %% @doc 24 | %% Construct a list of optics from a path. The type of the path 25 | %% component determines the optic used: 26 | %% 27 | %% 33 | %% 34 | %% This heavily depends on the `optic_generic' module, see the optics 35 | %% there for the full list of containers supported. 36 | %% 37 | %% Example: 38 | %% 39 | %% ``` 40 | %% > optic:get(optic_path(["first"]), ${"first" => 1, "second" => 2}). 41 | %% {ok,[1]} 42 | %% ''' 43 | %% @end 44 | %% @param Paths A list of path components to convert. 45 | %% @returns A list of opaque optic records. 46 | -spec new(Paths) -> optic:optics() when 47 | Paths :: paths(). 48 | new([]) -> 49 | []; 50 | new([Path | Paths]) when is_list(Path); is_binary(Path) -> 51 | [optic_generic:key(Path) | new(Paths)]; 52 | new([Path | Paths]) when is_integer(Path), Path > 0 -> 53 | [optic_generic:index(Path) | new(Paths)]; 54 | new(['*' | Paths]) -> 55 | [optic_lists:all() | new(Paths)]. 56 | -------------------------------------------------------------------------------- /src/optic_sets.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% A set of optics specific to sets. 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(optic_sets). 7 | 8 | %% API 9 | -export([all/0, 10 | all/1]). 11 | 12 | %%%=================================================================== 13 | %%% API 14 | %%%=================================================================== 15 | 16 | %% @see all/1 17 | -spec all() -> optic:optic(). 18 | all() -> 19 | all(#{}). 20 | 21 | %% @doc 22 | %% Focus on all elements of a set. 23 | %% 24 | %% Example: 25 | %% 26 | %% ``` 27 | %% > optic:get([optic_sets:all()], sets:from_list([1,2,3])). 28 | %% {ok,[1,2,3]} 29 | %% ''' 30 | %% @end 31 | %% @param Options Common optic options. 32 | %% @returns An opaque optic record. 33 | -spec all(Options) -> optic:optic() when 34 | Options :: optic:variations(). 35 | all(Options) -> 36 | Fold = 37 | fun (Fun, Acc, Set) -> 38 | case is_set(Set) of 39 | true -> 40 | {ok, sets:fold(Fun, Acc, Set)}; 41 | false -> 42 | {error, undefined} 43 | end 44 | end, 45 | MapFold = 46 | fun (Fun, Acc, Set) -> 47 | case is_set(Set) of 48 | true -> 49 | {ok, sets:fold(fun (Elem, {InnerSet, InnerAcc}) -> 50 | {NewElem, NewAcc} = Fun(Elem, InnerAcc), 51 | {sets:add_element(NewElem, InnerSet), NewAcc} 52 | end, 53 | {sets:new(), Acc}, 54 | Set)}; 55 | false -> 56 | {error, undefined} 57 | end 58 | end, 59 | New = 60 | fun (_Data, _Template) -> 61 | sets:new() 62 | end, 63 | Optic = optic:new(MapFold, Fold), 64 | optic:variations(Optic, Options, New). 65 | 66 | %%%=================================================================== 67 | %%% Internal Functions 68 | %%%=================================================================== 69 | 70 | is_set(Unknown) -> 71 | try sets:size(Unknown) of 72 | _ -> 73 | true 74 | catch 75 | error:{badrecord, set} -> 76 | false 77 | end. 78 | -------------------------------------------------------------------------------- /src/optic_tuples.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% A set of optics specific to tuples. 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(optic_tuples). 7 | 8 | %% API 9 | -export([all/0, 10 | all/1, 11 | element/1, 12 | element/2, 13 | field/3, 14 | field/4]). 15 | 16 | %%%=================================================================== 17 | %%% API 18 | %%%=================================================================== 19 | 20 | %% @see all/1 21 | -spec all() -> optic:optic(). 22 | all() -> 23 | all(#{}). 24 | 25 | %% @doc 26 | %% Focus on all elements of a tuple. 27 | %% 28 | %% Example: 29 | %% 30 | %% ``` 31 | %% > optic:get([optic_tuples:all()], {1,2,3}). 32 | %% {ok,[1,2,3]} 33 | %% ''' 34 | %% @end 35 | %% @param Options Common optic options. 36 | %% @returns An opaque optic record. 37 | -spec all(Options) -> optic:optic() when 38 | Options :: optic:variations(). 39 | all(Options) -> 40 | Fold = 41 | fun (Fun, Acc, Tuple) when is_tuple(Tuple) -> 42 | {ok, lists:foldl(Fun, Acc, tuple_to_list(Tuple))}; 43 | (_, _, _) -> 44 | {error, undefined} 45 | end, 46 | MapFold = 47 | fun (Fun, Acc, Tuple) when is_tuple(Tuple) -> 48 | {NewList, NewAcc} = lists:mapfoldl(Fun, Acc, tuple_to_list(Tuple)), 49 | {ok, {list_to_tuple(NewList), NewAcc}}; 50 | (_, _, _) -> 51 | {error, undefined} 52 | end, 53 | New = 54 | fun (_Data, _Template) -> 55 | {} 56 | end, 57 | Optic = optic:new(MapFold, Fold), 58 | optic:variations(Optic, Options, New). 59 | 60 | %% @see element/2 61 | -spec element(N) -> optic:optic() when 62 | N :: pos_integer(). 63 | element(N) -> 64 | optic_tuples:element(N, #{}). 65 | 66 | %% @doc 67 | %% Focus on the nth element of a tuple. As with `erlang:element/2', 68 | %% indexing begins at 1. 69 | %% 70 | %% Example: 71 | %% 72 | %% ``` 73 | %% > optic:get([optic_tuples:element(1)], {1,2,3}). 74 | %% {ok,[1]} 75 | %% ''' 76 | %% @end 77 | %% @param N The index of the tuple element to focus on. 78 | %% @param Options Common optic options. 79 | %% @returns An opaque optic record. 80 | -spec element(N, Options) -> optic:optic() when 81 | N :: pos_integer(), 82 | Options :: optic:variations(). 83 | element(N, Options) -> 84 | Fold = 85 | fun (Fun, Acc, Tuple) when N =< tuple_size(Tuple) -> 86 | Nth = erlang:element(N, Tuple), 87 | {ok, Fun(Nth, Acc)}; 88 | (_, _, _) -> 89 | {error, undefined} 90 | end, 91 | MapFold = 92 | fun (Fun, Acc, Tuple) when N =< tuple_size(Tuple) -> 93 | Nth = erlang:element(N, Tuple), 94 | {NewNth, NewAcc} = Fun(Nth, Acc), 95 | {ok, {erlang:setelement(N, Tuple, NewNth), NewAcc}}; 96 | (_, _, _) -> 97 | {error, undefined} 98 | end, 99 | New = 100 | fun (Tuple, Template) when is_tuple(Tuple) -> 101 | list_to_tuple(tuple_to_list(Tuple) ++ 102 | lists:duplicate(N - tuple_size(Tuple), Template)); 103 | (_Data, Template) -> 104 | list_to_tuple(lists:duplicate(N, Template)) 105 | end, 106 | Optic = optic:new(MapFold, Fold), 107 | optic:variations(Optic, Options, New). 108 | 109 | %% @see field/4 110 | -spec field(Tag, Size, N) -> optic:optic() when 111 | Tag :: atom(), 112 | Size :: pos_integer(), 113 | N :: pos_integer(). 114 | field(Tag, Size, N) -> 115 | field(Tag, Size, N, #{}). 116 | 117 | %% @doc 118 | %% Focus on a record field. As records are a compiler construct, this 119 | %% depends on the `?OPTIC_FIELD' macro in `include/optic_tuples.hrl' 120 | %% to construct the required arguments from the record definition. 121 | %% 122 | %% Given the record definition: 123 | %% 124 | %% ``` 125 | %% -include_lib("optic/include/optic_tuples.hrl"). 126 | %% -record(example, {first}). 127 | %% ''' 128 | %% 129 | %% Example: 130 | %% 131 | %% ``` 132 | %% > optic:get([optic_tuples:field(?OPTIC_FIELD(example, first))], 133 | %% #example{first=1}). 134 | %% {ok,[1]} 135 | %% ''' 136 | %% @end 137 | %% @param Tag The expected record tag. 138 | %% @param Size The expected record size. 139 | %% @param N The index of the field in the record tuple. 140 | %% @param Options Common optic options. 141 | %% @returns An opaque optic record. 142 | -spec field(Tag, Size, N, Options) -> optic:optic() when 143 | Tag :: atom(), 144 | Size :: pos_integer(), 145 | N :: pos_integer(), 146 | Options :: optic:variations(). 147 | field(Tag, Size, N, Options) -> 148 | Fold = 149 | fun (Fun, Acc, Tuple) when erlang:element(1, Tuple) == Tag, 150 | Size == tuple_size(Tuple), 151 | N > 1, 152 | N =< tuple_size(Tuple) -> 153 | Nth = erlang:element(N, Tuple), 154 | {ok, Fun(Nth, Acc)}; 155 | (_, _, _) -> 156 | {error, undefined} 157 | end, 158 | MapFold = 159 | fun (Fun, Acc, Tuple) when erlang:element(1, Tuple) == Tag, 160 | Size == tuple_size(Tuple), 161 | N > 1, 162 | N =< tuple_size(Tuple) -> 163 | Nth = erlang:element(N, Tuple), 164 | {NewNth, NewAcc} = Fun(Nth, Acc), 165 | {ok, {erlang:setelement(N, Tuple, NewNth), NewAcc}}; 166 | (_, _, _) -> 167 | {error, undefined} 168 | end, 169 | New = 170 | fun (_Data, Template) -> 171 | list_to_tuple([Tag] ++ lists:duplicate(Size - 1, Template)) 172 | end, 173 | Optic = optic:new(MapFold, Fold), 174 | optic:variations(Optic, Options, New). 175 | -------------------------------------------------------------------------------- /test/test_optic_array.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_array.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_array). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | optic:get([optic_array:all([strict])], 17 | array:from_list([1, 2, 3]))), 18 | ?_assertEqual({error, undefined}, 19 | optic:get([optic_array:all([strict])], 20 | atom))]. 21 | 22 | all_put_test_() -> 23 | [?_assertEqual({ok, array:from_list([4, 4, 4])}, 24 | optic:put([optic_array:all([strict])], 25 | 4, 26 | array:from_list([1, 2, 3]))), 27 | ?_assertEqual({error, undefined}, 28 | optic:put([optic_array:all([strict])], 29 | 4, 30 | atom))]. 31 | 32 | all_create_test() -> 33 | ?assertEqual({ok, array:new([{default, test}])}, 34 | optic:put([optic_array:all([strict, {create, test}])], 35 | 4, 36 | atom)). 37 | 38 | nth_get_test_() -> 39 | [?_assertEqual({ok, [1]}, 40 | optic:get([optic_array:nth(1, [strict])], 41 | array:from_list([1, 2, 3]))), 42 | ?_assertEqual({error, undefined}, 43 | optic:get([optic_array:nth(1, [strict])], 44 | atom))]. 45 | 46 | nth_put_test_() -> 47 | [?_assertEqual({ok, array:from_list([4, 2, 3])}, 48 | optic:put([optic_array:nth(1, [strict])], 49 | 4, 50 | array:from_list([1, 2, 3]))), 51 | ?_assertEqual({error, undefined}, 52 | optic:put([optic_array:nth(1, [strict])], 53 | 4, 54 | atom))]. 55 | 56 | nth_create_test_() -> 57 | [?_assertEqual({ok, [test, 4]}, 58 | maybe_to_list( 59 | optic:put([optic_array:nth(2, [strict, {create, test}])], 60 | 4, 61 | atom))), 62 | ?_assertEqual({ok, [1, undefined, 4]}, 63 | maybe_to_list( 64 | optic:put([optic_array:nth(3, [strict, create])], 65 | 4, 66 | array:from_list([1]))))]. 67 | 68 | %%%=================================================================== 69 | %%% Internal Functions 70 | %%%=================================================================== 71 | 72 | maybe_to_list({ok, Result}) -> 73 | {ok, array:to_list(Result)}. 74 | -------------------------------------------------------------------------------- /test/test_optic_dict.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_dict.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_dict). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | sort_get( 17 | optic:get([optic_dict:all([strict])], 18 | dict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 19 | ?_assertEqual({error, undefined}, 20 | optic:get([optic_dict:all([strict])], atom))]. 21 | 22 | all_put_test_() -> 23 | [?_assertEqual({ok, dict:from_list([{one, 4}, {two, 4}, {three, 4}])}, 24 | optic:put([optic_dict:all([strict])], 25 | 4, 26 | dict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 27 | ?_assertEqual({error, undefined}, 28 | optic:put([optic_dict:all([strict])], 4, atom))]. 29 | 30 | all_create_test() -> 31 | ?assertEqual({ok, dict:new()}, 32 | optic:put([optic_dict:all([strict, create])], 4, atom)). 33 | 34 | keys_get_test_() -> 35 | [?_assertEqual({ok, [one, three, two]}, 36 | sort_get( 37 | optic:get([optic_dict:keys([strict])], 38 | dict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 39 | ?_assertEqual({error, undefined}, 40 | optic:get([optic_dict:keys([strict])], atom))]. 41 | 42 | keys_put_test_() -> 43 | [?_assertEqual({ok, dict:from_list([{four, 1}])}, 44 | optic:put([optic_dict:keys([strict])], 45 | four, 46 | dict:from_list([{one, 1}]))), 47 | ?_assertEqual({error, undefined}, 48 | optic:put([optic_dict:keys([strict])], four, atom))]. 49 | 50 | keys_create_test() -> 51 | ?assertEqual({ok, dict:new()}, 52 | optic:put([optic_dict:keys([strict, create])], four, atom)). 53 | 54 | values_get_test_() -> 55 | [?_assertEqual({ok, [1, 2, 3]}, 56 | sort_get( 57 | optic:get([optic_dict:values([strict])], 58 | dict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 59 | ?_assertEqual({error, undefined}, 60 | optic:get([optic_dict:values([strict])], atom))]. 61 | 62 | values_put_test_() -> 63 | [?_assertEqual({ok, dict:from_list([{one, 4}, {two, 4}, {three, 4}])}, 64 | optic:put([optic_dict:values([strict])], 65 | 4, 66 | dict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 67 | ?_assertEqual({error, undefined}, 68 | optic:put([optic_dict:values([strict])], 4, atom))]. 69 | 70 | values_create_test() -> 71 | ?assertEqual({ok, dict:new()}, 72 | optic:put([optic_dict:values([strict, create])], 4, atom)). 73 | 74 | associations_get_test_() -> 75 | [?_assertEqual({ok, [{one, 1}, {three, 3}, {two, 2}]}, 76 | sort_get( 77 | optic:get([optic_dict:associations([strict])], 78 | dict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 79 | ?_assertEqual({error, undefined}, 80 | optic:get([optic_dict:associations([strict])], atom))]. 81 | 82 | associations_put_test_() -> 83 | [?_assertEqual({ok, dict:from_list([{four, 4}])}, 84 | optic:put([optic_dict:associations([strict])], 85 | {four, 4}, 86 | dict:from_list([{one, 1}]))), 87 | ?_assertEqual({error, undefined}, 88 | optic:put([optic_dict:associations([strict])], 89 | {four, 4}, 90 | atom))]. 91 | 92 | associations_create_test() -> 93 | ?assertEqual({ok, dict:new()}, 94 | optic:put([optic_dict:associations([strict, create])], 95 | {four, 4}, 96 | atom)). 97 | 98 | key_get_test_() -> 99 | [?_assertEqual({ok, [1]}, 100 | sort_get( 101 | optic:get([optic_dict:key(one, [strict])], 102 | dict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 103 | ?_assertEqual({error, undefined}, 104 | optic:get([optic_dict:key(one, [strict])], atom))]. 105 | 106 | key_put_test_() -> 107 | [?_assertEqual({ok, dict:from_list([{one, 4}, {two, 2}, {three, 3}])}, 108 | optic:put([optic_dict:key(one, [strict])], 109 | 4, 110 | dict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 111 | ?_assertEqual({error, undefined}, 112 | optic:put([optic_dict:key(one, [strict])], 4, atom))]. 113 | 114 | key_create_test_() -> 115 | [?_assertEqual({ok, dict:from_list([{one, 1}, {four, 4}])}, 116 | optic:put([optic_dict:key(four, [strict, create])], 117 | 4, 118 | dict:from_list([{one, 1}]))), 119 | ?_assertEqual({ok, dict:from_list([{four, 4}])}, 120 | optic:put([optic_dict:key(four, [strict, create])], 121 | 4, 122 | atom))]. 123 | 124 | association_get_test_() -> 125 | [?_assertEqual({ok, [{one, 1}]}, 126 | sort_get( 127 | optic:get([optic_dict:association(one, [strict])], 128 | dict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 129 | ?_assertEqual({error, undefined}, 130 | optic:get([optic_dict:association(one, [strict])], atom))]. 131 | 132 | association_put_test_() -> 133 | [?_assertEqual({ok, dict:from_list([{two, 2}, {three, 3}, {four, 4}])}, 134 | optic:put([optic_dict:association(one, [strict])], 135 | {four, 4}, 136 | dict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 137 | ?_assertEqual({ok, dict:from_list([{two, 2}, {three, 3}, {four, 4}])}, 138 | optic:put([optic_dict:association(one, [strict])], 139 | {four, 4}, 140 | dict:from_list([{one, 1}, {two, 2}, {three, 3}, {four, clobbered}]))), 141 | ?_assertEqual({error, undefined}, 142 | optic:put([optic_dict:association(one, [strict])], 143 | 4, 144 | atom))]. 145 | 146 | association_create_test_() -> 147 | [?_assertEqual({ok, dict:from_list([{one, 1}, {four, 4}])}, 148 | optic:put([optic_dict:association(four, [strict, create])], 149 | {four, 4}, 150 | dict:from_list([{one, 1}]))), 151 | ?_assertEqual({ok, dict:from_list([{four, 4}])}, 152 | optic:put([optic_dict:association(four, [strict, create])], 153 | {four, 4}, 154 | atom))]. 155 | 156 | %%%=================================================================== 157 | %%% Internal Functions 158 | %%%=================================================================== 159 | 160 | sort_get({ok, Result}) -> 161 | {ok, lists:sort(Result)}. 162 | -------------------------------------------------------------------------------- /test/test_optic_gb_sets.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_gb_sets.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_gb_sets). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | sort_get( 17 | optic:get([optic_gb_sets:all([strict])], 18 | gb_sets:from_list([1, 2, 3])))), 19 | ?_assertEqual({error, undefined}, 20 | optic:get([optic_gb_sets:all([strict])], atom))]. 21 | 22 | all_map_test() -> 23 | ?assertEqual({ok, [2, 4, 6]}, 24 | sort_put( 25 | optic:map([optic_gb_sets:all([strict])], 26 | fun (Elem) -> Elem * 2 end, 27 | gb_sets:from_list([1, 2, 3])))). 28 | 29 | all_put_test_() -> 30 | [?_assertEqual({ok, [4]}, 31 | sort_put( 32 | optic:put([optic_gb_sets:all([strict])], 33 | 4, 34 | gb_sets:from_list([1, 2, 3])))), 35 | ?_assertEqual({error, undefined}, 36 | optic:put([optic_gb_sets:all([strict])], 4, atom))]. 37 | 38 | all_create_test() -> 39 | ?assertEqual({ok, gb_sets:new()}, 40 | optic:put([optic_gb_sets:all([strict, create])], 41 | 4, 42 | atom)). 43 | 44 | %%%=================================================================== 45 | %%% Internal Functions 46 | %%%=================================================================== 47 | 48 | sort_get({ok, Result}) -> 49 | {ok, lists:sort(Result)}. 50 | 51 | sort_put({ok, Result}) -> 52 | {ok, lists:sort(gb_sets:to_list(Result))}. 53 | -------------------------------------------------------------------------------- /test/test_optic_gb_trees.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_gb_trees.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_gb_trees). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | sort_get( 17 | optic:get([optic_gb_trees:all([strict])], 18 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 19 | ?_assertEqual({error, undefined}, 20 | optic:get([optic_gb_trees:all([strict])], atom))]. 21 | 22 | all_put_test_() -> 23 | [?_assertEqual({ok, [{one, 4}, {three, 4}, {two, 4}]}, 24 | sort_put( 25 | optic:put([optic_gb_trees:all([strict])], 26 | 4, 27 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 28 | ?_assertEqual({error, undefined}, 29 | optic:put([optic_gb_trees:all([strict])], 4, atom))]. 30 | 31 | all_create_test() -> 32 | ?assertEqual({ok, []}, 33 | sort_put( 34 | optic:put([optic_gb_trees:all([strict, create])], 4, atom))). 35 | 36 | keys_get_test_() -> 37 | [?_assertEqual({ok, [one, three, two]}, 38 | sort_get( 39 | optic:get([optic_gb_trees:keys([strict])], 40 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 41 | ?_assertEqual({error, undefined}, 42 | optic:get([optic_gb_trees:keys([strict])], atom))]. 43 | 44 | keys_put_test_() -> 45 | [?_assertEqual({ok, [{four, 1}]}, 46 | sort_put( 47 | optic:put([optic_gb_trees:keys([strict])], 48 | four, 49 | from_list([{one, 1}])))), 50 | ?_assertEqual({error, undefined}, 51 | optic:put([optic_gb_trees:keys([strict])], four, atom))]. 52 | 53 | keys_create_test() -> 54 | ?assertEqual({ok, []}, 55 | sort_put( 56 | optic:put([optic_gb_trees:keys([strict, create])], four, atom))). 57 | 58 | values_get_test_() -> 59 | [?_assertEqual({ok, [1, 2, 3]}, 60 | sort_get( 61 | optic:get([optic_gb_trees:values([strict])], 62 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 63 | ?_assertEqual({error, undefined}, 64 | optic:get([optic_gb_trees:values([strict])], atom))]. 65 | 66 | values_put_test_() -> 67 | [?_assertEqual({ok, [{one, 4}, {three, 4}, {two, 4}]}, 68 | sort_put( 69 | optic:put([optic_gb_trees:values([strict])], 70 | 4, 71 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 72 | ?_assertEqual({error, undefined}, 73 | optic:put([optic_gb_trees:values([strict])], 4, atom))]. 74 | 75 | values_create_test() -> 76 | ?assertEqual({ok, []}, 77 | sort_put( 78 | optic:put([optic_gb_trees:values([strict, create])], 4, atom))). 79 | 80 | associations_get_test_() -> 81 | [?_assertEqual({ok, [{one, 1}, {three, 3}, {two, 2}]}, 82 | sort_get( 83 | optic:get([optic_gb_trees:associations([strict])], 84 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 85 | ?_assertEqual({error, undefined}, 86 | optic:get([optic_gb_trees:associations([strict])], atom))]. 87 | 88 | associations_put_test_() -> 89 | [?_assertEqual({ok, [{four, 4}]}, 90 | sort_put( 91 | optic:put([optic_gb_trees:associations([strict])], 92 | {four, 4}, 93 | from_list([{one, 1}])))), 94 | ?_assertEqual({error, undefined}, 95 | optic:put([optic_gb_trees:associations([strict])], 96 | {four, 4}, 97 | atom))]. 98 | 99 | associations_create_test() -> 100 | ?assertEqual({ok, []}, 101 | sort_put( 102 | optic:put([optic_gb_trees:associations([strict, create])], 103 | {four, 4}, 104 | atom))). 105 | 106 | key_get_test_() -> 107 | [?_assertEqual({ok, [1]}, 108 | sort_get( 109 | optic:get([optic_gb_trees:key(one, [strict])], 110 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 111 | ?_assertEqual({error, undefined}, 112 | optic:get([optic_gb_trees:key(one, [strict])], atom))]. 113 | 114 | key_put_test_() -> 115 | [?_assertEqual({ok, [{one, 4}, {three, 3}, {two, 2}]}, 116 | sort_put( 117 | optic:put([optic_gb_trees:key(one, [strict])], 118 | 4, 119 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 120 | ?_assertEqual({error, undefined}, 121 | optic:put([optic_gb_trees:key(one, [strict])], 4, atom))]. 122 | 123 | key_create_test_() -> 124 | [?_assertEqual({ok, [{four, 4}, {one, 1}]}, 125 | sort_put( 126 | optic:put([optic_gb_trees:key(four, [strict, create])], 127 | 4, 128 | from_list([{one, 1}])))), 129 | ?_assertEqual({ok, [{four, 4}]}, 130 | sort_put( 131 | optic:put([optic_gb_trees:key(four, [strict, create])], 132 | 4, 133 | atom)))]. 134 | 135 | association_get_test_() -> 136 | [?_assertEqual({ok, [{one, 1}]}, 137 | sort_get( 138 | optic:get([optic_gb_trees:association(one, [strict])], 139 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 140 | ?_assertEqual({error, undefined}, 141 | optic:get([optic_gb_trees:association(one, [strict])], atom))]. 142 | 143 | association_put_test_() -> 144 | [?_assertEqual({ok, [{four, 4}, {three, 3}, {two, 2}]}, 145 | sort_put( 146 | optic:put([optic_gb_trees:association(one, [strict])], 147 | {four, 4}, 148 | from_list([{one, 1}, {two, 2}, {three, 3}])))), 149 | ?_assertEqual({ok, [{four, 4}, {three, 3}, {two, 2}]}, 150 | sort_put( 151 | optic:put([optic_gb_trees:association(one, [strict])], 152 | {four, 4}, 153 | from_list([{one, 1}, {two, 2}, {three, 3}, {four, clobbered}])))), 154 | ?_assertEqual({error, undefined}, 155 | optic:put([optic_gb_trees:association(one, [strict])], 156 | 4, 157 | atom))]. 158 | 159 | association_create_test_() -> 160 | [?_assertEqual({ok, [{four, 4}, {one, 1}]}, 161 | sort_put( 162 | optic:put([optic_gb_trees:association(four, [strict, create])], 163 | {four, 4}, 164 | from_list([{one, 1}])))), 165 | ?_assertEqual({ok, [{four, 4}]}, 166 | sort_put( 167 | optic:put([optic_gb_trees:association(four, [strict, create])], 168 | {four, 4}, 169 | atom)))]. 170 | 171 | %%%=================================================================== 172 | %%% Internal Functions 173 | %%%=================================================================== 174 | 175 | from_list(List) -> 176 | Dict = orddict:from_list(List), 177 | gb_trees:from_orddict(Dict). 178 | 179 | sort_get({ok, Result}) -> 180 | {ok, lists:sort(Result)}. 181 | 182 | sort_put({ok, Result}) -> 183 | {ok, gb_trees:to_list(Result)}. 184 | -------------------------------------------------------------------------------- /test/test_optic_generic.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_generic.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_generic). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | key_get_test_() -> 15 | [?_assertEqual({ok, [value]}, 16 | optic:get([optic_generic:key(key)], #{key=>value})), 17 | ?_assertEqual({ok, [value]}, 18 | optic:get([optic_generic:key(key)], [{key, value}])), 19 | ?_assertEqual({ok, [value]}, 20 | optic:get([optic_generic:key(key)], orddict:from_list([{key, value}]))), 21 | ?_assertEqual({ok, [value]}, 22 | optic:get([optic_generic:key(key)], dict:from_list([{key, value}]))), 23 | ?_assertEqual({ok, [value]}, 24 | optic:get([optic_generic:key(key)], gb_trees:from_orddict([{key, value}]))), 25 | ?_assertEqual({ok, []}, 26 | optic:get([optic_generic:key(key)], atom))]. 27 | 28 | key_put_test_() -> 29 | [?_assertEqual({ok, #{key=>new}}, 30 | optic:put([optic_generic:key(key)], new, #{key=>value})), 31 | ?_assertEqual({ok, [{key, new}]}, 32 | optic:put([optic_generic:key(key)], new, [{key, value}])), 33 | ?_assertEqual({ok, [{key, new}]}, 34 | optic:put([optic_generic:key(key)], new, orddict:from_list([{key, value}]))), 35 | ?_assertEqual({ok, dict:from_list([{key, new}])}, 36 | optic:put([optic_generic:key(key)], new, dict:from_list([{key, value}]))), 37 | ?_assertEqual({ok, gb_trees:from_orddict([{key, new}])}, 38 | optic:put([optic_generic:key(key)], new, gb_trees:from_orddict([{key, value}]))), 39 | ?_assertEqual({ok, atom}, 40 | optic:put([optic_generic:key(key)], new, atom))]. 41 | 42 | index_get_test_() -> 43 | [?_assertEqual({ok, [3]}, 44 | optic:get([optic_generic:index(3)], [1, 2, 3])), 45 | ?_assertEqual({ok, [3]}, 46 | optic:get([optic_generic:index(3)], {1, 2, 3})), 47 | ?_assertEqual({ok, []}, 48 | optic:get([optic_generic:index(3)], #{}))]. 49 | 50 | index_put_test_() -> 51 | [?_assertEqual({ok, [1, 2, 4]}, 52 | optic:put([optic_generic:index(3)], 4, [1, 2, 3])), 53 | ?_assertEqual({ok, {1, 2, 4}}, 54 | optic:put([optic_generic:index(3)], 4, {1, 2, 3})), 55 | ?_assertEqual({ok, #{}}, 56 | optic:put([optic_generic:index(3)], 4, #{}))]. 57 | -------------------------------------------------------------------------------- /test/test_optic_lists.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_lists.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_lists). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | optic:get([optic_lists:all([strict])], [1, 2, 3])), 17 | ?_assertEqual({ok, [3]}, 18 | optic:get([optic_lists:all([strict, 19 | {filter, 20 | fun (Elem) -> Elem == 3 end}])], 21 | [1, 2, 3])), 22 | ?_assertEqual({ok, [3]}, 23 | optic:get([optic_lists:all([strict, 24 | {require, 25 | fun (Elem) -> Elem == 3 end}])], 26 | [3])), 27 | ?_assertEqual({error, required}, 28 | optic:get([optic_lists:all([create, 29 | {require, 30 | fun (Elem) -> Elem == 3 end}])], 31 | [1, 2, 3])), 32 | ?_assertEqual({ok, []}, 33 | optic:get([optic_lists:all()], atom)), 34 | ?_assertEqual({ok, []}, 35 | optic:get([optic_lists:all([{strict, false}])], atom)), 36 | ?_assertEqual({error, undefined}, 37 | optic:get([optic_lists:all([strict])], atom))]. 38 | 39 | all_put_test_() -> 40 | [?_assertEqual({ok, [4, 4, 4]}, 41 | optic:put([optic_lists:all([strict])], 4, [1, 2, 3])), 42 | ?_assertEqual({ok, [1, 2, 4]}, 43 | optic:put([optic_lists:all([strict, 44 | {filter, 45 | fun (Elem) -> Elem == 3 end}])], 46 | 4, 47 | [1, 2, 3])), 48 | ?_assertEqual({ok, [4]}, 49 | optic:put([optic_lists:all([strict, 50 | {require, 51 | fun (Elem) -> Elem == 3 end}])], 52 | 4, 53 | [3])), 54 | ?_assertEqual({error, required}, 55 | optic:put([optic_lists:all([create, 56 | {require, 57 | fun (Elem) -> Elem == 3 end}])], 58 | 4, 59 | [1, 2, 3])), 60 | ?_assertEqual({ok, atom}, 61 | optic:put([optic_lists:all()], 4, atom)), 62 | ?_assertEqual({ok, atom}, 63 | optic:put([optic_lists:all([{strict, false}])], 4, atom)), 64 | ?_assertEqual({error, undefined}, 65 | optic:put([optic_lists:all([strict])], 4, atom))]. 66 | 67 | all_create_test() -> 68 | ?assertEqual({ok, []}, 69 | optic:put([optic_lists:all([strict, create])], 4, atom)). 70 | 71 | head_get_test_() -> 72 | [?_assertEqual({ok, [1]}, 73 | optic:get([optic_lists:head([strict])], [1, 2, 3])), 74 | ?_assertEqual({error, undefined}, 75 | optic:get([optic_lists:head([strict])], atom))]. 76 | 77 | head_put_test_() -> 78 | [?_assertEqual({ok, [4, 2, 3]}, 79 | optic:put([optic_lists:head([strict])], 4, [1, 2, 3])), 80 | ?_assertEqual({error, undefined}, 81 | optic:put([optic_lists:head([strict])], 4, atom))]. 82 | 83 | head_create_test() -> 84 | ?assertEqual({ok, [4]}, 85 | optic:put([optic_lists:head([strict, create])], 4, atom)). 86 | 87 | tail_get_test_() -> 88 | [?_assertEqual({ok, [2, 3]}, 89 | optic:get([optic_lists:tail([strict])], [1, 2, 3])), 90 | ?_assertEqual({error, undefined}, 91 | optic:get([optic_lists:tail([strict])], atom))]. 92 | 93 | tail_put_test_() -> 94 | [?_assertEqual({ok, [1, 4, 4]}, 95 | optic:put([optic_lists:tail([strict])], 4, [1, 2, 3])), 96 | ?_assertEqual({error, undefined}, 97 | optic:put([optic_lists:tail([strict])], 4, atom))]. 98 | 99 | tail_create_test() -> 100 | ?assertEqual({ok, [undefined]}, 101 | optic:put([optic_lists:tail([strict, 102 | {create, undefined}])], 103 | 4, 104 | atom)). 105 | 106 | nth_get_test_() -> 107 | [?_assertEqual({ok, [1]}, 108 | optic:get([optic_lists:nth(1, [strict])], [1, 2, 3])), 109 | ?_assertEqual({error, undefined}, 110 | optic:get([optic_lists:nth(1, [strict])], atom))]. 111 | 112 | nth_put_test_() -> 113 | [?_assertEqual({ok, [4, 2, 3]}, 114 | optic:put([optic_lists:nth(1, [strict])], 4, [1, 2, 3])), 115 | ?_assertEqual({error, undefined}, 116 | optic:put([optic_lists:nth(1, [strict])], 4, atom))]. 117 | 118 | nth_create_test_() -> 119 | [?_assertEqual({ok, [undefined, 4]}, 120 | optic:put([optic_lists:nth(2, [strict, 121 | {create, undefined}])], 122 | 4, 123 | atom)), 124 | ?_assertEqual({ok, [1, undefined, 4]}, 125 | optic:put([optic_lists:nth(3, [strict, 126 | {create, undefined}])], 127 | 4, 128 | [1]))]. 129 | -------------------------------------------------------------------------------- /test/test_optic_maps.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_maps.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_maps). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | sort_get(optic:get([optic_maps:all([strict])], 17 | #{one=>1, two=>2, three=>3}))), 18 | ?_assertEqual({error, undefined}, 19 | optic:get([optic_maps:all([strict])], atom))]. 20 | 21 | all_put_test_() -> 22 | [?_assertEqual({ok, #{one=>4, two=>4, three=>4}}, 23 | optic:put([optic_maps:all([strict])], 24 | 4, 25 | #{one=>1, two=>2, three=>3})), 26 | ?_assertEqual({error, undefined}, 27 | optic:put([optic_maps:all([strict])], 4, atom))]. 28 | 29 | all_create_test() -> 30 | ?assertEqual({ok, #{}}, 31 | optic:put([optic_maps:all([strict, create])], 4, atom)). 32 | 33 | keys_get_test_() -> 34 | [?_assertEqual({ok, [one, three, two]}, 35 | sort_get(optic:get([optic_maps:keys([strict])], 36 | #{one=>1, two=>2, three=>3}))), 37 | ?_assertEqual({error, undefined}, 38 | optic:get([optic_maps:keys([strict])], atom))]. 39 | 40 | keys_put_test_() -> 41 | [?_assertEqual({ok, #{four=>1}}, 42 | optic:put([optic_maps:keys([strict])], 43 | four, 44 | #{one=>1})), 45 | ?_assertEqual({error, undefined}, 46 | optic:put([optic_maps:keys([strict])], four, atom))]. 47 | 48 | keys_create_test() -> 49 | ?assertEqual({ok, #{}}, 50 | optic:put([optic_maps:keys([strict, create])], four, atom)). 51 | 52 | values_get_test_() -> 53 | [?_assertEqual({ok, [1, 2, 3]}, 54 | sort_get(optic:get([optic_maps:values([strict])], 55 | #{one=>1, two=>2, three=>3}))), 56 | ?_assertEqual({error, undefined}, 57 | optic:get([optic_maps:values([strict])], atom))]. 58 | 59 | values_put_test_() -> 60 | [?_assertEqual({ok, #{one=>4, two=>4, three=>4}}, 61 | optic:put([optic_maps:values([strict])], 62 | 4, 63 | #{one=>1, two=>2, three=>3})), 64 | ?_assertEqual({error, undefined}, 65 | optic:put([optic_maps:values([strict])], 4, atom))]. 66 | 67 | values_create_test() -> 68 | ?assertEqual({ok, #{}}, 69 | optic:put([optic_maps:values([strict, create])], 4, atom)). 70 | 71 | associations_get_test_() -> 72 | [?_assertEqual({ok, [{one, 1}, {three, 3}, {two, 2}]}, 73 | sort_get(optic:get([optic_maps:associations([strict])], 74 | #{one=>1, two=>2, three=>3}))), 75 | ?_assertEqual({error, undefined}, 76 | optic:get([optic_maps:associations([strict])], atom))]. 77 | 78 | associations_put_test_() -> 79 | [?_assertEqual({ok, #{four=>4}}, 80 | optic:put([optic_maps:associations([strict])], 81 | {four, 4}, 82 | #{one=>1})), 83 | ?_assertEqual({error, undefined}, 84 | optic:put([optic_maps:associations([strict])], 85 | {four, 4}, 86 | atom))]. 87 | 88 | associations_create_test() -> 89 | ?assertEqual({ok, #{}}, 90 | optic:put([optic_maps:associations([strict, create])], 91 | {four, 4}, 92 | atom)). 93 | 94 | key_get_test_() -> 95 | [?_assertEqual({ok, [1]}, 96 | sort_get(optic:get([optic_maps:key(one, [strict])], 97 | #{one=>1, two=>2, three=>3}))), 98 | ?_assertEqual({error, undefined}, 99 | optic:get([optic_maps:key(one, [strict])], atom))]. 100 | 101 | key_put_test_() -> 102 | [?_assertEqual({ok, #{one=>4, two=>2, three=>3}}, 103 | optic:put([optic_maps:key(one, [strict])], 104 | 4, 105 | #{one=>1, two=>2, three=>3})), 106 | ?_assertEqual({error, undefined}, 107 | optic:put([optic_maps:key(one, [strict])], 4, atom))]. 108 | 109 | key_create_test_() -> 110 | [?_assertEqual({ok, #{one=>1, four=>4}}, 111 | optic:put([optic_maps:key(four, [strict, create])], 112 | 4, 113 | #{one=>1})), 114 | ?_assertEqual({ok, #{four=>4}}, 115 | optic:put([optic_maps:key(four, [strict, create])], 116 | 4, 117 | atom))]. 118 | 119 | association_get_test_() -> 120 | [?_assertEqual({ok, [{one, 1}]}, 121 | sort_get(optic:get([optic_maps:association(one, [strict])], 122 | #{one=>1, two=>2, three=>3}))), 123 | ?_assertEqual({error, undefined}, 124 | optic:get([optic_maps:association(one, [strict])], atom))]. 125 | 126 | association_put_test_() -> 127 | [?_assertEqual({ok, #{two=>2, three=>3, four=>4}}, 128 | optic:put([optic_maps:association(one, [strict])], 129 | {four, 4}, 130 | #{one=>1, two=>2, three=>3})), 131 | ?_assertEqual({ok, #{two=>2, three=>3, four=>4}}, 132 | optic:put([optic_maps:association(one, [strict])], 133 | {four, 4}, 134 | #{one=>1, two=>2, three=>3, four=>clobbered})), 135 | ?_assertEqual({error, undefined}, 136 | optic:put([optic_maps:association(one, [strict])], 137 | 4, 138 | atom))]. 139 | 140 | association_create_test_() -> 141 | [?_assertEqual({ok, #{one=>1, four=>4}}, 142 | optic:put([optic_maps:association(four, [strict, create])], 143 | {four, 4}, 144 | #{one=>1})), 145 | ?_assertEqual({ok, #{four=>4}}, 146 | optic:put([optic_maps:association(four, [strict, create])], 147 | {four, 4}, 148 | atom))]. 149 | 150 | %%%=================================================================== 151 | %%% Internal Functions 152 | %%%=================================================================== 153 | 154 | sort_get({ok, Result}) -> 155 | {ok, lists:sort(Result)}. 156 | -------------------------------------------------------------------------------- /test/test_optic_orddict.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_orddict.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_orddict). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | sort_get(optic:get([optic_orddict:all([strict])], 17 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 18 | ?_assertEqual({error, undefined}, 19 | optic:get([optic_orddict:all([strict])], atom))]. 20 | 21 | all_put_test_() -> 22 | [?_assertEqual({ok, orddict:from_list([{one, 4}, {two, 4}, {three, 4}])}, 23 | optic:put([optic_orddict:all([strict])], 24 | 4, 25 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 26 | ?_assertEqual({error, undefined}, 27 | optic:put([optic_orddict:all([strict])], 4, atom))]. 28 | 29 | all_create_test() -> 30 | ?assertEqual({ok, orddict:new()}, 31 | optic:put([optic_orddict:all([strict, create])], 4, atom)). 32 | 33 | keys_get_test_() -> 34 | [?_assertEqual({ok, [one, three, two]}, 35 | sort_get(optic:get([optic_orddict:keys([strict])], 36 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 37 | ?_assertEqual({error, undefined}, 38 | optic:get([optic_orddict:keys([strict])], atom))]. 39 | 40 | keys_put_test_() -> 41 | [?_assertEqual({ok, orddict:from_list([{four, 1}])}, 42 | optic:put([optic_orddict:keys([strict])], 43 | four, 44 | orddict:from_list([{one, 1}]))), 45 | ?_assertEqual({error, undefined}, 46 | optic:put([optic_orddict:keys([strict])], four, atom))]. 47 | 48 | keys_create_test() -> 49 | ?assertEqual({ok, orddict:new()}, 50 | optic:put([optic_orddict:keys([strict, create])], four, atom)). 51 | 52 | values_get_test_() -> 53 | [?_assertEqual({ok, [1, 2, 3]}, 54 | sort_get(optic:get([optic_orddict:values([strict])], 55 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 56 | ?_assertEqual({error, undefined}, 57 | optic:get([optic_orddict:values([strict])], atom))]. 58 | 59 | values_put_test_() -> 60 | [?_assertEqual({ok, orddict:from_list([{one, 4}, {two, 4}, {three, 4}])}, 61 | optic:put([optic_orddict:values([strict])], 62 | 4, 63 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 64 | ?_assertEqual({error, undefined}, 65 | optic:put([optic_orddict:values([strict])], 4, atom))]. 66 | 67 | values_create_test() -> 68 | ?assertEqual({ok, orddict:new()}, 69 | optic:put([optic_orddict:values([strict, create])], 4, atom)). 70 | 71 | associations_get_test_() -> 72 | [?_assertEqual({ok, [{one, 1}, {three, 3}, {two, 2}]}, 73 | sort_get(optic:get([optic_orddict:associations([strict])], 74 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 75 | ?_assertEqual({error, undefined}, 76 | optic:get([optic_orddict:associations([strict])], atom))]. 77 | 78 | associations_put_test_() -> 79 | [?_assertEqual({ok, orddict:from_list([{four, 4}])}, 80 | optic:put([optic_orddict:associations([strict])], 81 | {four, 4}, 82 | orddict:from_list([{one, 1}]))), 83 | ?_assertEqual({error, undefined}, 84 | optic:put([optic_orddict:associations([strict])], 85 | {four, 4}, 86 | atom))]. 87 | 88 | associations_create_test() -> 89 | ?assertEqual({ok, orddict:new()}, 90 | optic:put([optic_orddict:associations([strict, create])], 91 | {four, 4}, 92 | atom)). 93 | 94 | key_get_test_() -> 95 | [?_assertEqual({ok, [1]}, 96 | sort_get(optic:get([optic_orddict:key(one, [strict])], 97 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 98 | ?_assertEqual({error, undefined}, 99 | optic:get([optic_orddict:key(one, [strict])], atom))]. 100 | 101 | key_put_test_() -> 102 | [?_assertEqual({ok, orddict:from_list([{one, 4}, {two, 2}, {three, 3}])}, 103 | optic:put([optic_orddict:key(one, [strict])], 104 | 4, 105 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 106 | ?_assertEqual({error, undefined}, 107 | optic:put([optic_orddict:key(one, [strict])], 4, atom))]. 108 | 109 | key_create_test_() -> 110 | [?_assertEqual({ok, orddict:from_list([{one, 1}, {four, 4}])}, 111 | optic:put([optic_orddict:key(four, [strict, create])], 112 | 4, 113 | orddict:from_list([{one, 1}]))), 114 | ?_assertEqual({ok, orddict:from_list([{four, 4}])}, 115 | optic:put([optic_orddict:key(four, [strict, create])], 116 | 4, 117 | atom))]. 118 | 119 | association_get_test_() -> 120 | [?_assertEqual({ok, [{one, 1}]}, 121 | sort_get(optic:get([optic_orddict:association(one, [strict])], 122 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}])))), 123 | ?_assertEqual({error, undefined}, 124 | optic:get([optic_orddict:association(one, [strict])], atom))]. 125 | 126 | association_put_test_() -> 127 | [?_assertEqual({ok, orddict:from_list([{two, 2}, {three, 3}, {four, 4}])}, 128 | optic:put([optic_orddict:association(one, [strict])], 129 | {four, 4}, 130 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}]))), 131 | ?_assertEqual({ok, orddict:from_list([{two, 2}, {three, 3}, {four, 4}])}, 132 | optic:put([optic_orddict:association(one, [strict])], 133 | {four, 4}, 134 | orddict:from_list([{one, 1}, {two, 2}, {three, 3}, {four, clobbered}]))), 135 | ?_assertEqual({error, undefined}, 136 | optic:put([optic_orddict:association(one, [strict])], 137 | 4, 138 | atom))]. 139 | 140 | association_create_test_() -> 141 | [?_assertEqual({ok, orddict:from_list([{one, 1}, {four, 4}])}, 142 | optic:put([optic_orddict:association(four, [strict, create])], 143 | {four, 4}, 144 | orddict:from_list([{one, 1}]))), 145 | ?_assertEqual({ok, orddict:from_list([{four, 4}])}, 146 | optic:put([optic_orddict:association(four, [strict, create])], 147 | {four, 4}, 148 | atom))]. 149 | 150 | %%%=================================================================== 151 | %%% Internal Functions 152 | %%%=================================================================== 153 | 154 | sort_get({ok, Result}) -> 155 | {ok, lists:sort(Result)}. 156 | -------------------------------------------------------------------------------- /test/test_optic_ordsets.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_ordsets.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_ordsets). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | sort_get( 17 | optic:get([optic_ordsets:all([strict])], 18 | ordsets:from_list([1, 2, 3])))), 19 | ?_assertEqual({error, undefined}, 20 | optic:get([optic_ordsets:all([strict])], atom))]. 21 | 22 | all_map_test() -> 23 | ?assertEqual({ok, [2, 4, 6]}, 24 | sort_put( 25 | optic:map([optic_ordsets:all([strict])], 26 | fun (Elem) -> Elem * 2 end, 27 | ordsets:from_list([1, 2, 3])))). 28 | 29 | all_put_test_() -> 30 | [?_assertEqual({ok, [4]}, 31 | sort_put( 32 | optic:put([optic_ordsets:all([strict])], 33 | 4, 34 | ordsets:from_list([1, 2, 3])))), 35 | ?_assertEqual({error, undefined}, 36 | optic:put([optic_ordsets:all([strict])], 4, atom))]. 37 | 38 | all_create_test() -> 39 | ?assertEqual({ok, ordsets:new()}, 40 | optic:put([optic_ordsets:all([strict, create])], 41 | 4, 42 | atom)). 43 | 44 | %%%=================================================================== 45 | %%% Internal Functions 46 | %%%=================================================================== 47 | 48 | sort_get({ok, Result}) -> 49 | {ok, lists:sort(Result)}. 50 | 51 | sort_put({ok, Result}) -> 52 | {ok, lists:sort(ordsets:to_list(Result))}. 53 | -------------------------------------------------------------------------------- /test/test_optic_path.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_path.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_path). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | new_test_() -> 15 | [?_assertEqual({ok, [value]}, 16 | optic:get(optic_path:new(["key"]), #{"key"=>value})), 17 | ?_assertEqual({ok, [value]}, 18 | optic:get(optic_path:new(["key"]), [{"key", value}])), 19 | ?_assertEqual({ok, [value]}, 20 | optic:get(optic_path:new([<<"key">>]), 21 | #{<<"key">>=>value})), 22 | ?_assertEqual({ok, [value]}, 23 | optic:get(optic_path:new([1]), [value])), 24 | ?_assertEqual({ok, [1, 2, 3]}, 25 | optic:get(optic_path:new(['*']), [1, 2, 3])), 26 | ?_assertEqual({ok, [value]}, 27 | optic:get(optic_path:new(["key", 1, "nested"]), 28 | #{"key"=>[#{"nested"=>value}]}))]. 29 | -------------------------------------------------------------------------------- /test/test_optic_proplists.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_proplists.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_proplists). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 1, 2, 3]}, 16 | optic:get([optic_proplists:all([strict])], 17 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 18 | ?_assertEqual({error, undefined}, 19 | optic:get([optic_proplists:all([strict])], atom))]. 20 | 21 | all_put_test_() -> 22 | [?_assertEqual({ok, [{one, 4}, {one, 4}, {two, 4}, {three, 4}]}, 23 | optic:put([optic_proplists:all([strict])], 24 | 4, 25 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 26 | ?_assertEqual({error, undefined}, 27 | optic:put([optic_proplists:all([strict])], 4, atom))]. 28 | 29 | all_create_test() -> 30 | ?assertEqual({ok, []}, 31 | optic:put([optic_proplists:all([strict, create])], 4, atom)). 32 | 33 | keys_get_test_() -> 34 | [?_assertEqual({ok, [one, one, two, three]}, 35 | optic:get([optic_proplists:keys([strict])], 36 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 37 | ?_assertEqual({error, undefined}, 38 | optic:get([optic_proplists:keys([strict])], atom))]. 39 | 40 | keys_put_test_() -> 41 | [?_assertEqual({ok, [{four, 1}, {four, 1}, {four, 2}, {four, 3}]}, 42 | optic:put([optic_proplists:keys([strict])], 43 | four, 44 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 45 | ?_assertEqual({error, undefined}, 46 | optic:put([optic_proplists:keys([strict])], four, atom))]. 47 | 48 | keys_create_test() -> 49 | ?assertEqual({ok, []}, 50 | optic:put([optic_proplists:keys([strict, create])], 51 | four, 52 | atom)). 53 | 54 | values_get_test_() -> 55 | [?_assertEqual({ok, [1, 1, 2, 3]}, 56 | optic:get([optic_proplists:values([strict])], 57 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 58 | ?_assertEqual({error, undefined}, 59 | optic:get([optic_proplists:values([strict])], atom))]. 60 | 61 | values_put_test_() -> 62 | [?_assertEqual({ok, [{one, 4}, {one, 4}, {two, 4}, {three, 4}]}, 63 | optic:put([optic_proplists:values([strict])], 64 | 4, 65 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 66 | ?_assertEqual({error, undefined}, 67 | optic:put([optic_proplists:values([strict])], 4, atom))]. 68 | 69 | values_create_test() -> 70 | ?assertEqual({ok, []}, 71 | optic:put([optic_proplists:values([strict, create])], 72 | 4, 73 | atom)). 74 | 75 | properties_get_test_() -> 76 | [?_assertEqual({ok, [{one, 1}, {one, 1}, {two, 2}, {three, 3}]}, 77 | optic:get([optic_proplists:properties([strict])], 78 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 79 | ?_assertEqual({error, undefined}, 80 | optic:get([optic_proplists:properties([strict])], atom))]. 81 | 82 | properties_put_test_() -> 83 | [?_assertEqual({ok, [{four, 4}, {four, 4}, {four, 4}, {four, 4}]}, 84 | optic:put([optic_proplists:properties([strict])], 85 | {four, 4}, 86 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 87 | ?_assertEqual({error, undefined}, 88 | optic:put([optic_proplists:properties([strict])], 89 | four, 90 | atom))]. 91 | 92 | properties_create_test() -> 93 | ?assertEqual({ok, []}, 94 | optic:put([optic_proplists:properties([strict, create])], 95 | four, 96 | atom)). 97 | 98 | key_get_test_() -> 99 | [?_assertEqual({ok, [1, 1.5]}, 100 | optic:get([optic_proplists:key(one, [strict])], 101 | [{one, 1}, {one, 1.5}, {two, 2}, {three, 3}])), 102 | ?_assertEqual({error, undefined}, 103 | optic:get([optic_proplists:key(one, [strict])], atom))]. 104 | 105 | key_put_test_() -> 106 | [?_assertEqual({ok, [{one, 4}, {one, 4}, {two, 2}, {three, 3}]}, 107 | optic:put([optic_proplists:key(one, [strict])], 108 | 4, 109 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 110 | ?_assertEqual({error, undefined}, 111 | optic:put([optic_proplists:key(one, [strict])], 4, atom))]. 112 | 113 | key_create_test_() -> 114 | [?_assertEqual({ok, [{four, 4}, {one, 1}]}, 115 | optic:put([optic_proplists:key(four, [strict, create])], 116 | 4, 117 | [{one, 1}])), 118 | ?_assertEqual({ok, [{four, 4}]}, 119 | optic:put([optic_proplists:key(four, [strict, create])], 120 | 4, 121 | atom))]. 122 | 123 | property_get_test_() -> 124 | [?_assertEqual({ok, [{one, 1}, {one, 1.5}]}, 125 | optic:get([optic_proplists:property(one, [strict])], 126 | [{one, 1}, {one, 1.5}, {two, 2}, {three, 3}])), 127 | ?_assertEqual({error, undefined}, 128 | optic:get([optic_proplists:property(one, [strict])], 129 | atom))]. 130 | 131 | property_put_test_() -> 132 | [?_assertEqual({ok, [{four, 4}, {four, 4}, {two, 2}, {three, 3}]}, 133 | optic:put([optic_proplists:property(one, [strict])], 134 | {four, 4}, 135 | [{one, 1}, {one, 1}, {two, 2}, {three, 3}])), 136 | ?_assertEqual({error, undefined}, 137 | optic:put([optic_proplists:property(one, [strict])], 138 | 4, 139 | atom))]. 140 | 141 | property_create_test_() -> 142 | [?_assertEqual({ok, [{four, 4}, {one, 1}]}, 143 | optic:put([optic_proplists:property(four, [strict, create])], 144 | {four, 4}, 145 | [{one, 1}])), 146 | ?_assertEqual({ok, [{four, 4}]}, 147 | optic:put([optic_proplists:property(four, [strict, create])], 148 | {four, 4}, 149 | atom))]. 150 | -------------------------------------------------------------------------------- /test/test_optic_sets.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_sets.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_sets). 7 | 8 | -include_lib("eunit/include/eunit.hrl"). 9 | 10 | %%%=================================================================== 11 | %%% Tests 12 | %%%=================================================================== 13 | 14 | all_get_test_() -> 15 | [?_assertEqual({ok, [1, 2, 3]}, 16 | sort_get( 17 | optic:get([optic_sets:all([strict])], 18 | sets:from_list([1, 2, 3])))), 19 | ?_assertEqual({error, undefined}, 20 | optic:get([optic_sets:all([strict])], atom))]. 21 | 22 | all_map_test() -> 23 | ?assertEqual({ok, [2, 4, 6]}, 24 | sort_put( 25 | optic:map([optic_sets:all([strict])], 26 | fun (Elem) -> Elem * 2 end, 27 | sets:from_list([1, 2, 3])))). 28 | 29 | all_put_test_() -> 30 | [?_assertEqual({ok, [4]}, 31 | sort_put( 32 | optic:put([optic_sets:all([strict])], 33 | 4, 34 | sets:from_list([1, 2, 3])))), 35 | ?_assertEqual({error, undefined}, 36 | optic:put([optic_sets:all([strict])], 4, atom))]. 37 | 38 | all_create_test() -> 39 | ?assertEqual({ok, sets:new()}, 40 | optic:put([optic_sets:all([strict, create])], 41 | 4, 42 | atom)). 43 | 44 | %%%=================================================================== 45 | %%% Internal Functions 46 | %%%=================================================================== 47 | 48 | sort_get({ok, Result}) -> 49 | {ok, lists:sort(Result)}. 50 | 51 | sort_put({ok, Result}) -> 52 | {ok, lists:sort(sets:to_list(Result))}. 53 | -------------------------------------------------------------------------------- /test/test_optic_tuples.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %%% @doc 3 | %%% Tests for src/optic_tuples.erl 4 | %%% @end 5 | %%%------------------------------------------------------------------- 6 | -module(test_optic_tuples). 7 | 8 | -include("include/optic_tuples.hrl"). 9 | -include_lib("eunit/include/eunit.hrl"). 10 | 11 | -record(test_optic_tuples, {one=1, two=2, three=3}). 12 | 13 | %%%=================================================================== 14 | %%% Tests 15 | %%%=================================================================== 16 | 17 | all_get_test_() -> 18 | [?_assertEqual({ok, [1, 2, 3]}, 19 | optic:get([optic_tuples:all([strict])], {1, 2, 3})), 20 | ?_assertEqual({error, undefined}, 21 | optic:get([optic_tuples:all([strict])], atom))]. 22 | 23 | all_put_test_() -> 24 | [?_assertEqual({ok, {4, 4, 4}}, 25 | optic:put([optic_tuples:all([strict])], 4, {1, 2, 3})), 26 | ?_assertEqual({error, undefined}, 27 | optic:put([optic_tuples:all([strict])], 4, atom))]. 28 | 29 | all_create_test() -> 30 | ?assertEqual({ok, {}}, 31 | optic:put([optic_tuples:all([strict, create])], 4, atom)). 32 | 33 | element_get_test_() -> 34 | [?_assertEqual({ok, [1]}, 35 | optic:get([optic_tuples:element(1, [strict])], {1, 2, 3})), 36 | ?_assertEqual({error, undefined}, 37 | optic:get([optic_tuples:element(1, [strict])], atom))]. 38 | 39 | element_put_test_() -> 40 | [?_assertEqual({ok, {4, 2, 3}}, 41 | optic:put([optic_tuples:element(1, [strict])], 42 | 4, 43 | {1, 2, 3})), 44 | ?_assertEqual({error, undefined}, 45 | optic:put([optic_tuples:element(1, [strict])], 46 | 4, 47 | atom))]. 48 | 49 | element_create_test_() -> 50 | [?_assertEqual({ok, {undefined, 4}}, 51 | optic:put([optic_tuples:element(2, [strict, 52 | {create, undefined}])], 53 | 4, 54 | atom)), 55 | ?_assertEqual({ok, {1, undefined, 4}}, 56 | optic:put([optic_tuples:element(3, [strict, 57 | {create, undefined}])], 58 | 4, 59 | {1}))]. 60 | 61 | field_get_test_() -> 62 | [?_assertEqual({ok, [1]}, 63 | optic:get([optic_tuples:field( 64 | test_optic_tuples, 65 | record_info(size, test_optic_tuples), 66 | #test_optic_tuples.one, 67 | [strict])], 68 | #test_optic_tuples{})), 69 | ?_assertEqual({ok, [1]}, 70 | optic:get([optic_tuples:field( 71 | ?OPTIC_FIELD(test_optic_tuples, one))], 72 | #test_optic_tuples{})), 73 | ?_assertEqual({error, undefined}, 74 | optic:get([optic_tuples:field( 75 | test_optic_tuples, 76 | record_info(size, test_optic_tuples), 77 | #test_optic_tuples.one, 78 | [strict])], 79 | {test_optic_tuples}))]. 80 | 81 | field_put_test_() -> 82 | [?_assertEqual({ok, {test_optic_tuples, 4, 2, 3}}, 83 | optic:put([optic_tuples:field( 84 | test_optic_tuples, 85 | record_info(size, test_optic_tuples), 86 | #test_optic_tuples.one, 87 | [strict])], 88 | 4, 89 | #test_optic_tuples{})), 90 | ?_assertEqual({ok, {test_optic_tuples, 4, 2, 3}}, 91 | optic:put([optic_tuples:field( 92 | ?OPTIC_FIELD(test_optic_tuples, one))], 93 | 4, 94 | #test_optic_tuples{})), 95 | ?_assertEqual({error, undefined}, 96 | optic:put([optic_tuples:field( 97 | test_optic_tuples, 98 | record_info(size, test_optic_tuples), 99 | #test_optic_tuples.one, 100 | [strict])], 101 | 4, 102 | {test_optic_tuples}))]. 103 | 104 | field_create_test() -> 105 | ?assertEqual({ok, {test_optic_tuples, 4, undefined, undefined}}, 106 | optic:put([optic_tuples:field( 107 | test_optic_tuples, 108 | record_info(size, test_optic_tuples), 109 | #test_optic_tuples.one, 110 | [strict, {create, undefined}])], 111 | 4, 112 | {test_optic_tuples})). 113 | --------------------------------------------------------------------------------