Skip to content

Commit ec47187

Browse files
author
Aleksei Matiushkin
committed
Better type handling
1 parent 7db5da8 commit ec47187

File tree

2 files changed

+14
-26
lines changed

2 files changed

+14
-26
lines changed

lib/iteraptor.ex

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ defmodule Iteraptor do
120120
Map.put(acc, key, v)
121121
end
122122

123-
with {_, flattened} <- reduce(input, %{}, reducer, opts), do: flattened
123+
reduce(input, %{}, reducer, opts)
124124
end
125125

126126
@doc """
@@ -214,7 +214,7 @@ defmodule Iteraptor do
214214
- `yield`: `[:all | :none | :maps | :lists]` what to yield; _default:_ `:all`
215215
for yielding _values only_
216216
- `keys`: `[:reverse]` reverse keys list to ease pattern matching; _default:_ `nil`
217-
- `structs`: `[:values | :keep]` how to handle structs; _default:_ `nil`
217+
- `structs`: `[:values | :keep]` how to handle structs; _default:_ `:values`
218218
for treating them as `map`s. When `:values`, the nested structs
219219
are considered leaves and returned to the iterator instead of being iterated
220220
through; when `:keep` it returns a struct back after iteration
@@ -278,9 +278,7 @@ defmodule Iteraptor do
278278
{type, _, into} = type(input)
279279
{result, _} = traverse(input, fun, opts, {[], into})
280280

281-
if opts[:structs] == :keep && is_map(result) and type != Map,
282-
do: struct(type, result),
283-
else: result
281+
maybe_struct(opts[:structs], result, type)
284282
end
285283

286284
@doc """
@@ -307,7 +305,7 @@ defmodule Iteraptor do
307305
["a", "a_b", "a_b_c"]
308306
"""
309307

310-
@spec reduce(Access.t(), Access.t(), traverse_fun(), options()) :: {Access.t(), any()}
308+
@spec reduce(Access.t(), Access.t(), traverse_fun(), options()) :: Access.t()
311309

312310
def reduce(input, acc \\ nil, fun, opts \\ []) do
313311
unless is_function(fun, 2), do: raise("Function or arity fun/2 is required")
@@ -317,9 +315,7 @@ defmodule Iteraptor do
317315
fun_wrapper = fn kv, acc -> {kv, fun.(kv, acc)} end
318316
{_, result} = traverse(input, fun_wrapper, opts, {[], acc})
319317

320-
if opts[:structs] == :keep && is_map(result) and type != Map,
321-
do: struct(type, result),
322-
else: result
318+
maybe_struct(opts[:structs], result, type)
323319
end
324320

325321
@doc """
@@ -356,12 +352,7 @@ defmodule Iteraptor do
356352
acc = if is_nil(acc), do: into, else: acc
357353
{map_result, result} = traverse(input, fun, opts, {[], acc})
358354

359-
result =
360-
if opts[:structs] == :keep && is_map(result) and type != Map,
361-
do: struct(type, result),
362-
else: result
363-
364-
{map_result, result}
355+
{map_result, maybe_struct(opts[:structs], result, type)}
365356
end
366357

367358
@doc """
@@ -383,7 +374,7 @@ defmodule Iteraptor do
383374
%{a: %{e: %{c: 42}, d: %{c: 42}}, c: 42}
384375
"""
385376

386-
@spec filter(Access.t(), traverse_fun(), options()) :: {Access.t(), any()}
377+
@spec filter(Access.t(), traverse_fun(), options()) :: Access.t()
387378

388379
def filter(input, fun, opts \\ []) do
389380
unless is_function(fun, 1), do: raise("Function or arity fun/1 is required")
@@ -395,9 +386,7 @@ defmodule Iteraptor do
395386

396387
{_, result} = traverse(input, fun_wrapper, opts, {[], acc})
397388

398-
if opts[:structs] == :keep && is_map(result) and type != Map,
399-
do: struct(type, result),
400-
else: result
389+
maybe_struct(opts[:structs], result, type)
401390
end
402391

403392
@doc """
@@ -444,6 +433,10 @@ defmodule Iteraptor do
444433
)
445434
end
446435

436+
@spec maybe_struct(:keep | :values, result :: any(), type :: module()) :: Access.t()
437+
defp maybe_struct(:keep, %{} = result, type) when type != Map, do: struct(type, result)
438+
defp maybe_struct(_, result, _), do: result
439+
447440
@spec do_stringify(any(), boolean()) :: any() | binary()
448441
defp do_stringify(k, false), do: k
449442
defp do_stringify(k, _) when is_atom(k), do: Atom.to_string(k)
@@ -514,12 +507,7 @@ defmodule Iteraptor do
514507
end
515508
end)
516509

517-
result = Enum.into(value, into)
518-
519-
result =
520-
if opts[:structs] == :keep && is_map(result) and type != Map,
521-
do: struct(type, result),
522-
else: result
510+
result = maybe_struct(opts[:structs], Enum.into(value, into), type)
523511

524512
{squeeze(result, opts), acc}
525513
end

test/iteraptor_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ defmodule Iteraptor.Test do
8080
test "keyword / each prints keys in the reversed order" do
8181
result =
8282
capture_log(fn ->
83-
@keyword |> Iteraptor.each(fn {k, v} -> Logger.debug(inspect({k, v})) end, keys: :reverse)
83+
@keyword |> Iteraptor.map(fn {k, v} -> Logger.debug(inspect({k, v})) end, keys: :reverse)
8484
end)
8585

8686
assert result =~ "{[:a1], 42}"

0 commit comments

Comments
 (0)