Enum.reduce_while vs Enum.reduce in Elixir

Publish date: 2024-05-18

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 

ncG1vNJzZmirpJawrLvVnqmfpJ%2Bse6S7zGiorp2jqbawutJobmlvaGmAc32OnqWupV2nsqXBwp5ksKCZobJuwtJmnKetnWK%2FprDUnJxmoZ5isq2116Kp