BadArityError with & function capture operator

Hi Folks,

I tried to understand the next piece of code:

@function_table zip(["and",       "or",       "nand",    "nor",    "not"],
                                [&p_and/2, &p_or/2, &nand/2, &nor/2, &not/1])
                       
 @target_data [[false, false, false, true],
               [ false, false, true,  false],
               [ false, true,  false, false],
               [ false, true,  true,  true],
               [ true,  false, false, false],
               [ true,  false, true,  true],
               [ true,  true,  false, true],
               [ true,  true,  true,  false]]

  def random_function() do
      @function_table |> Enum.into(%{}) |> Map.values |> random
  end

  def random_terminal() do
      Enum.random(
           [fn(in1, _, _) -> in1 end,
            fn(_, in2, _) -> in2 end,
            fn(_, _, in3) -> in3 end])
  end

  def random_code(depth) do

    rand_uniform = :rand.uniform(2)

    if (depth == 0) or rand_uniform == 1 do
       rant = random_terminal()
       puts "Random_code:   Depth: #{depth}   rand-uniform = #{rand_uniform}   Random_terminal -> #{Macro.to_string(rant)}"
       rant
    else
      f = random_function()
      puts "Random_code:   Depth: #{depth}   Arity: #{:erlang.fun_info(f)[:arity]}   f = random_function: #{Macro.to_string(f)}"
      puts "\nStart using  f.(repeatly  ... )"
       f.(repeatedly(fn() -> random_code(depth - 1) end, :erlang.fun_info(f)[:arity]))
      end
  end

And I got the following testoutput:

=================

Random_code:   Depth: 2   Arity: 2   f = random_function: &Gpi.Util.p_and/2

Start using  f.(repeatly  ... )

Random_code:   Depth: 1   rand-uniform = 1   Random_terminal -> #Function<7.123612048/3 in Gpi1Test.random_terminal/0>
Random_code:   Depth: 1   rand-uniform = 1   Random_terminal -> #Function<9.123612048/3 in Gpi1Test.random_terminal/0>

  1) test random code aanmaken populatie (Gpi1Test)
     test/gpi_test.exs:268
     ** (BadArityError) &Gpi.Util.p_and/2 with arity 2 called with 1 argument ([#Function<7.123612048/3 in Gpi1Test.random_terminal/0>, #Function<9.123612048/3 in Gpi1Test.random_terminal/0>])
     code: random_code(2)
     stacktrace:
       test/gpi_test.exs:79: Gpi1Test.random_code/1
       test/gpi_test.exs:270: (test)
=============

I got something like f.( [a,b] ) while I expected f.(a,b)

Can anyone explain what is wrong?

Thanks in advance,

Thiel

Can anyone explain what is wrong?

Can you show what repeatedly/1 does in

f.(repeatedly(fn() -> random_code(depth - 1) end, :erlang.fun_info(f)[:arity]))

?

In this case, you might try using Kernel.apply/2 instead:

apply(f, repeatedly(fn() -> random_code(depth - 1) end, :erlang.fun_info(f)[:arity]))

Hi voughtdg,

Many thanks for your reaction!!

I changed the code into:

  Kernel.apply(f,(repeatedly(fn() -> random_code(depth - 1) end, :erlang.fun_info(f)[:arity])))

according to your suggestion and it worked! See the testoutput:

Hi ,

I use the next macro in my code:

´´´

defmacro repeatedly(f, n) do

      quote do

        unquote(f) |> Stream.repeatedly |> Enum.take(unquote(n))

      end

    end

´´´

See my answer to Voughtdq.

Many thanks for your reaction.

Thiel

I think repeatedly/2 can be a function instead of a macro. And it returns a list [a,b] since you are calling Enum.take/2 in the end.

Hi,

Thanks for your response.

I will give it a try with:

‘’’

def repeatedly2(f,n) do

Stream.repeatedly(f,n) |> Enum.take(n)

end

‘’’

I’ll let you know.

I don’t think it would work either:

And it returns a list [a,b] since you are calling Enum.take/2 in the end.

Hi,

You are right, it did not work.

  I am satisfied with the Kernel.apply solution. It generates a  population of logical functions for the genetic algorithm code.

  The problem left is the NOT function. I got an argument error for the :erlang.not(#Function<..... in Gpi1Test.random_terminal/0>)

I have to found why.

Many thanks,

Thiel