** (CompileError) core_components.ex:671: attributes must be defined before the first function clause at line 587

Hello, I would to define two icons CoreComponent with two differents arity if it’s possible ? but I get this error :

** (CompileError) core_components.ex:671: attributes must be defined before
the first function clause at line 587

My code : (core_components.ex)

  ....

  @doc """
  Renders a [Heroicon](https://heroicons.com).

  Heroicons come in three styles – outline, solid, and mini.
  By default, the outline style is used, but solid an mini may
  be applied by using the `-solid` and `-mini` suffix.

  You can customize the size and colors of the icons by setting
  width, height, and background color classes.

  Icons are extracted from your `assets/vendor/heroicons` directory and bundled
  within your compiled app.css by the plugin in your `assets/tailwind.config.js`.

  ## Examples

      <.icon name="hero-x-mark-solid" />
      <.icon name="hero-arrow-path" class="ml-1 w-3 h-3 animate-spin" />
  """
  attr :name, :string, required: true
  attr :class, :string, default: "h-8 w-8"
  
  def icon(%{name: "hero-" <> _} = assigns) do
    ~H"""
      <span class={[@name, @class]} />
    """
  end

  @doc """
  HeroIcons.LiveView  
  """
  attr :name, :string, required: true
  attr :class, :string, default: "h-8 w-8"
  attr :type, :string, default: "outline"
  
  def icon(%{name: _, class: _, type: _} = assigns) do
    ~H"""
      <Heroicons.LiveView.icon name={@name} class={@class} type={@type} />
    """
  end

  ...

Hey @sabo66 the def icon clauses you show are the same arity. Both take 1 argument. That makes them the same function.

1 Like

Ah yes ! I’m pretty new in Elixir

I saw these functions in a session crontroller:

  def create(conn, %{"_action" => "registered"} = params) do
    create(conn, params, "Successful registration !")
  end

  def create(conn, %{"_action" => "password_updated"} = params) do
    conn
    |> put_session(:user_return_to, ~p"/users/settings")
    |> create(params, "Password changed !")
  end

It’s not possible to define one CoreComponent (def icon in this case) with two differents pattern matching like theses functions above ?

This could lead to infinite loop, because You are calling yourself.

You need to reorder your function

def icon(%{name: name, class: class, type: type} = assigns) do
  # do something with type
end

def icon(%{name: "hero-" <> _} = assigns) do
  # usual stuff
end

No need for full name… maybe You can simplify

  def icon(%{name: _, class: _, type: _} = assigns) do
    ~H"""
      <.icon name={@name} class={@class} type={@type} />
    """
  end
3 Likes

Thank you it’s working :slight_smile: Writing Heroicons.LiveView in @doc make some alias ?

No it should not, but icon is inside core component, so You should have access to it

1 Like

Ok thank !