> It could be done for maps and filter, but I am not quite sure about find.

Well, technically `find` is `filter` in a nutshell, with some additional 
condition, so it’s either or none.

> we need to be careful to not promote traversals in maps (by using find) 
instead of doing a per key operation.

I’d say they are by no means interchangeable because nobody (hopefully) 
filters/finds by key, these functions are normally used as a last resort to 
lookup by value, and it’s next to impossible in many cases to reshape the 
input so that filtering might be done by key to avoid traversal. 

On Monday, July 1, 2024 at 8:41:24 AM UTC+2 José Valim wrote:

The general problem is, when used with the update operations, both find/1 
and filter/1 would have to build the original shape back, instead of simply 
returning a list (which is what the Enum functions do). It could be done 
for maps and filter, but I am not quite sure about find. Also, we need to 
be careful to not promote traversals in maps (by using find) instead of 
doing a per key operation.

On Mon, Jul 1, 2024 at 8:27 AM Philip Munksgaard <pmunk...@gmail.com> wrote:

Hi,

I'm a frequent user of the Access module, and I'm excited about the recent 
addition of Access.find/1 to support some use-cases I've had to work my way 
around in the past. However, now that I have it, the first thing I wanted 
to do actually applied to a map.

For context, I'm working with Ecto changesets in a Phoenix LiveView 
application. I'm working with a `Foo` schema that has an assoc containing a 
number of uploaded files. Whenever I edit a Foo, I want to be able to 
upload a new file, but only one at a time. I also want to be able to edit 
the attached descriptions to each of the files that are already uploaded. I 
have written some logic that only shows one live_file_input at a time, and 
I have written the following `save` function (following the pattern in the 
standard phx.gen.live templates):

```elixir
  defp save(socket, :edit, foo_params) do
    uploaded_entries_params = consume_uploaded_entries(socket, :file, 
&upload_consumer/2)

    foo_params =
      case uploaded_entries_params do
        [] ->
          foo_params

        [upload_params] ->
          update_in(
            foo_params,
            ["foo_files", Access.find(&is_nil(&1["file_id"])), "file"],
            &Map.merge(&1, upload_params)
          )
      end

    case Foos.update_foo(socket.assigns.foo, foo_params) do
      {:ok, foo} ->
        {:noreply, push_patch(socket, to: socket.assigns.patch)}

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign_form(socket, changeset)}
    end
  end
```

The interesting bit is the `update_in` call, which takes the params 
generated by my `upload_consumer` and merges it with the params coming from 
the form submission. Unfortunately, this doesn't work, since 
`foo_params["foo_files"]` is a map of the form: `%{"0" => %{ ... }, ...}`

I was a bit surprised to find that Access.find/1 doesn't work with maps, 
but then I remembered that the same is true for Access.filter/1. My (very) 
cursory look at the implementation suggests that both of those are using 
Enum-functions, which _do_ in fact support maps, so I am wondering why that 
is not the case for the Access-functions? Would there be any interest in 
adding support for maps in Access.find/1 and Access.filter/1?

Best regards
Philip

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an 
email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/d29a0d69-db72-4d2d-814e-5809c4f8da6f%40app.fastmail.com
.

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/873152dd-2c02-4604-88d7-88120d5d23e4n%40googlegroups.com.

Reply via email to