Enum.reduce_while vs Enum.reduce in Elixir

I am a beginner at Elixir. Here are my queries. I have written two functions below.

a) The first one uses Enum.reduce_while

b) the second function uses Enum.reduce

I am observing the following:
a) In the first function the count goes from 0, 1, 2, 3 and gets reset (Basically for each row, the count gets reset). This I could observe by viewing the output of IO.puts My expectation was that the "count" should keep incrementing.

b) However in the 2nd function the count keeps incrementing (which is expected). The only difference is that the first one is reduce_while, whereas the second one is just reduce.

Questions:

a) Why there is a difference in the way accumulators are treated between Enum.reduce_while vs Enum.reduce?

b) What am I missing?

def is_power_pattern_present_in_grid(grid, pattern, max_row, max_col) when length(pattern) <= max_row * max_col do count = 0 result = 0 {chk, chk1} = Enum.reduce_while(0..(max_row - 1), {result, count}, fn row, {result, count} -> Enum.reduce_while(0..(max_col - 1), {result, count}, fn col, {result, count} -> IO.puts("looping throughat #{inspect(row)}, #{inspect(col)},#{inspect(count)}") count = count + 1 result = 0 {:cont, {result, count}} end) {:cont, {result, count}} end)
end
def is_power1_pattern_present_in_grid(grid, pattern, max_row, max_col) when length(pattern) <= max_row * max_col do count = 0 result = 0 {chk, chk1} = Enum.reduce(0..(max_row - 1), {result, count}, fn row, {result, count} -> Enum.reduce(0..(max_col - 1), {result, count}, fn col, {result, count} -> IO.puts("looping throughat #{inspect(row)}, #{inspect(col)},#{inspect(count)}") count = count + 1 result = 0 {result, count} end) end)
end
4

1 Answer

The outer reduces are returning different things. The bottom reduce is returning the result of the inner reduce while the top one is throwing away the result and returning {0, 0}.

Hopefully it is a bit easier to see with different variable names:

def is_power_pattern_present_in_grid(grid, pattern, max_row, max_col) when length(pattern) <= max_row * max_col do initial_count = 0 initial_result = 0 {chk, chk1} = Enum.reduce_while(0..(max_row - 1), {initial_result, initial_count}, fn row, {outer_result, outer_count} -> Enum.reduce_while(0..(max_col - 1), {outer_result, outer_count}, fn col, {inner_result, inner_count} -> IO.puts("looping throughat #{inspect(row)}, #{inspect(col)},#{inspect(inner_count)}") inner_count = inner_count + 1 inner_result = 0 {:cont, {inner_result, inner_count}} end) {:cont, {outer_result, outer_count}} end)
end
def is_power1_pattern_present_in_grid(grid, pattern, max_row, max_col) when length(pattern) <= max_row * max_col do initial_count = 0 initial_result = 0 {chk, chk1} = Enum.reduce(0..(max_row - 1), {initial_result, initial_count}, fn row, {outer_result, outer_count} -> Enum.reduce(0..(max_col - 1), {outer_result, outer_count}, fn col, {inner_result, inner_count} -> IO.puts("looping throughat #{inspect(row)}, #{inspect(col)},#{inspect(inner_count)}") inner_count = inner_count + 1 inner_result = 0 {inner_result, inner_count} end) end)
end

This seems like what you may have intended:

def is_power_pattern_present_in_grid(grid, pattern, max_row, max_col) when length(pattern) <= max_row * max_col do initial_count = 0 initial_result = 0 {chk, chk1} = Enum.reduce_while(0..(max_row - 1), {initial_result, initial_count}, fn row, {outer_result, outer_count} -> {result, count} = Enum.reduce_while(0..(max_col - 1), {outer_result, outer_count}, fn col, {inner_result, inner_count} -> IO.puts("looping throughat #{inspect(row)}, #{inspect(col)},#{inspect(inner_count)}") inner_count = inner_count + 1 inner_result = 0 {:cont, {inner_result, inner_count}} end) {:cont, {result, count}} end)
end

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like