Missed closing paren in iex, but it still worked

So I’m following along with the Programming Phoenix 1.4 book and I’m at the part where you create the users table and start inserting users into the database (page 63), and I messed up my input in iex like below but it still worked:

iex(2)> Accounts.list_users() |> Enum.map(&(%User{ name: &1.name, username: &1.username}) |> Repo.insert()
...(2)> 
...(2)> )

Notice how I missed the closing ‘)’ around the Enum.map and instead closed it after the Repo.insert.

Yet it still worked and I got the following output:

debug] QUERY OK db=15.1ms decode=19.2ms queue=3.8ms idle=1767.4ms
INSERT INTO "users" ("name","username","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["Jose", "jose_valim", ~N[2021-02-12 01:58:43], ~N[2021-02-12 01:58:43]]
[debug] QUERY OK db=2.4ms queue=1.3ms idle=1893.6ms
INSERT INTO "users" ("name","username","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["Bruce", "redrapids", ~N[2021-02-12 01:58:43], ~N[2021-02-12 01:58:43]]
[debug] QUERY OK db=1.8ms queue=1.0ms idle=897.3ms
INSERT INTO "users" ("name","username","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["Chris", "chrismccord", ~N[2021-02-12 01:58:43], ~N[2021-02-12 01:58:43]]
[
  ok: %Accounts.User{
    __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
    id: 1,
    inserted_at: ~N[2021-02-12 01:58:43],
    name: "Jose",
    updated_at: ~N[2021-02-12 01:58:43],
    username: "jose_valim"
  },
  ok: %Accounts.User{
    __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
    id: 2,
    inserted_at: ~N[2021-02-12 01:58:43],
    name: "Bruce",
    updated_at: ~N[2021-02-12 01:58:43],
    username: "redrapids"
  },
  ok: %Accounts.User{
    __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
    id: 3,
    inserted_at: ~N[2021-02-12 01:58:43],
    name: "Chris",
    updated_at: ~N[2021-02-12 01:58:43],
    username: "chrismccord"
  }
]

Doesn’t it seem odd that it would still work?

Now that I’m looking at it harder I’m guessing it’s because it’s considering everything in Enum.map as an anonymous function and thought that was the end of my statement.

That is correct. It parsed this as:

Accounts.list_users() |> Enum.map(
  &(
    %User{ name: &1.name, username: &1.username}) |> Repo.insert()
  )
)

The whole of %User{ name: &1.name, username: &1.username}) |> Repo.insert() is the anonymous function, there are no missing parens.

1 Like