こちらの内容の課題
fx = fn x -> rem(x, 2) == 0 end
の部分がパラメータ化できてない
現時点の結論だめでした…
あえて、失敗例を載せます
defmodule HogeTest do
use ExUnit.Case
doctest Hoge
params = [
[true, 1, "s"],
[true, nil, true],
[true, 1, false]
]
for param <- params do
@param param
test "Hoge.all?/1 param #{inspect(@param)}" do
assert Hoge.all?(@param) == Enum.all?(@param)
end
end
params = [
[[2, 4, 6], fn x -> rem(x, 2) == 0 end],
[[2, 4, 5], fn x -> rem(x, 2) == 0 end]
]
for [param, fx] <- params do
@param param
@fx fx
test "Hoge.all?/2 param #{inspect(@param)}" do
assert Hoge.all?(@param, @fx) == Enum.all?(@param, @fx)
end
end
end
** (ArgumentError) cannot inject attribute @fx into function/macro because cannot escape #Function<2.123583373 in file:test/hoge_test.exs>. The supported values are: lists, tuples, maps, atoms, numbers, bitstrings, PIDs and remote functions in the format &Mod.fun/arity
(elixir 1.13.4) lib/kernel.ex:3509: Kernel.do_at/5
(elixir 1.13.4) expanding macro: Kernel.@/1
test/hoge_test.exs:28: HogeTest."test Hoge.all?/2 param [2, 4, 6]"/1
(ex_unit 1.13.4) expanding macro: ExUnit.Assertions.assert/1
test/hoge_test.exs:28: HogeTest."test Hoge.all?/2 param [2, 4, 6]"/1
エラーメッセージの通り、だめっぽい
だが…
無理やり動かす方法を考えた
defmodule HogeTest do
use ExUnit.Case
doctest Hoge
params = [
[true, 1, "s"],
[true, nil, true],
[true, 1, false]
]
for param <- params do
@param param
test "Hoge.all?/1 param #{inspect(@param)}" do
assert Hoge.all?(@param) == Enum.all?(@param)
end
end
params = [
[[2, 4, 6], "fn x -> rem(x, 2) == 0 end"],
[[2, 4, 5], "fn x -> rem(x, 2) == 0 end"]
]
for param <- params do
@param param
test "Hoge.all?/2 param #{inspect(@param)}" do
[list, fx_string] = @param
fx = Code.eval_string(fx_string) |> elem(0)
assert Hoge.all?(list, fx) == Enum.all?(list, fx)
end
end
end
つまり、文字列として渡す
その後にCode.eval_stringで文字列から関数を作成する