### Good Doc Example with Behavior and Examples Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.NarratorDoc.md This example shows a 'good' function documentation comment that details behavior, constraints, and includes an example, which is preferred over simply stating the function's action. ```elixir # good — document behavior, constraints, examples @doc """ Passwords must be at least 12 characters. Returns `{:error, :weak_password}` for common dictionary words. ## Examples iex> create_user(%{email: "a@b.c", password: "hunter2"}) {:error, :weak_password} """ ``` -------------------------------- ### Good Documentation Example (with constraints) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.BoilerplateDocParams.md This example demonstrates a 'good' @doc string where the ## Parameters section documents the constraints and requirements for the parameters, rather than just their names. ```elixir @doc """ Renders the index page. ## Parameters - params: Must include `"page"` (integer >= 1) and optionally `"per_page"` (default 20, max 100). """ ``` -------------------------------- ### Bad Documentation Example Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.BoilerplateDocParams.md This example shows a 'bad' @doc string where the ## Parameters section merely restates the function signature, adding no value. ```elixir @doc """ Renders the index page. ## Parameters - conn: The connection struct - params: A map of parameters """ def index(conn, params) ``` -------------------------------- ### Good Moduledoc Example Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.NarratorDoc.md This example illustrates a 'good' moduledoc that provides valuable context and details beyond the module name, such as implementation details and rate-limiting behavior. ```elixir # good — explain WHY, not WHAT @moduledoc """ Wraps Bcrypt and session token generation. Rate-limits login attempts per IP via a sliding window. """ ``` -------------------------------- ### Good Documentation Example (no parameters section) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.BoilerplateDocParams.md This example shows another 'good' @doc string where the ## Parameters section is omitted entirely, which is acceptable when no specific parameter constraints need to be documented. ```elixir @doc """ Renders the index page, paginated. """ ``` -------------------------------- ### Bad Doc Example Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.NarratorDoc.md This example demonstrates a 'bad' function documentation comment that simply states what the function does, a pattern flagged by the NarratorDoc check. ```elixir # bad @doc """ This function creates a new user. """ def create_user(attrs) ``` -------------------------------- ### Bad Moduledoc Example Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.NarratorDoc.md This example shows a 'bad' moduledoc that restates the module's purpose, which the NarratorDoc check aims to identify. ```elixir # bad @moduledoc """ This module provides functionality for handling user authentication. """ defmodule MyApp.Auth do ``` -------------------------------- ### Identify Identity Map (Bad Example) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.IdentityMap.md These examples show the 'bad' pattern of using `Enum.map` as an identity map. This pattern is redundant and should be refactored. ```elixir list |> Enum.map(fn x -> x end) ``` ```elixir Enum.map(list, fn item -> item end) ``` -------------------------------- ### GenServer as a dumb key-value wrapper Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.GenserverAsKvStore.md This code demonstrates a GenServer implementing basic get and put operations, which is flagged by the check. Use Agent or ETS for better performance and built-in functionality. ```elixir defmodule MyCache do use GenServer def handle_call({:get, key}, _from, state) do {:reply, Map.get(state, key), state} end def handle_call({:put, key, value}, _from, state) do {:reply, :ok, Map.put(state, key, value)} end end ``` -------------------------------- ### ExSlop NarratorComment Check Examples Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.NarratorComment.md Illustrates comments flagged by the NarratorComment check and provides examples of how to refactor them into more concise and informative comments, or to remove them when the code is self-explanatory. ```elixir # bad # Here we fetch the user from the database user = Repo.get!(User, id) # Now we validate the input changeset = User.changeset(user, attrs) # Let's create a new changeset changeset = change(user) ``` ```elixir # good — no comment needed, the code is clear # good — explains WHY # Bypass validation for admin imports (they're pre-validated upstream) Repo.insert!(changeset, skip_validations: true) ``` -------------------------------- ### Remove Identity Map (Good Example) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.IdentityMap.md This example shows the 'good' pattern after refactoring. The identity map is simply removed, leaving the original list. ```elixir list ``` -------------------------------- ### Redundant Enum.join Separator Example Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.RedundantEnumJoinSeparator.md Demonstrates the incorrect usage of `Enum.join` with an empty string separator and the correct, simplified version. This check helps refactor code to be more concise. ```elixir Enum.join(parts, "") ``` ```elixir parts |> Enum.join("") ``` ```elixir Enum.join(parts) ``` -------------------------------- ### Example of Good Practice: Documented or Private Functions Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.DocFalseOnPublicFunction.md This code shows the preferred approach: either document public functions or make them private. This snippet serves as a contrast to the anti-pattern flagged by the check. ```elixir defmodule MyAppWeb.UserController do def index(conn, _params), do: ... def show(conn, %{"id" => id}), do: ... end ``` -------------------------------- ### Acceptable Single Use Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.UnaliasedModuleUse.md This example shows a function where a module is used only once. The UnaliasedModuleUse check does not flag this, as an alias is not necessary for readability when a module is referenced just one time. ```elixir def run(source_file) do Credo.Code.prewalk(source_file, &walk/2, ctx) end ``` -------------------------------- ### Example of Bad Practice: Multiple @doc false Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.DocFalseOnPublicFunction.md This code demonstrates the anti-pattern where every public function in a module is annotated with `@doc false`. This check aims to flag such occurrences. ```elixir defmodule MyAppWeb.UserController do @doc false def index(conn, _params), do: ... @doc false def show(conn, %{"id" => id}), do: ... @doc false def create(conn, %{"user" => params}), do: ... end ``` -------------------------------- ### Obvious Comment Example Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.ObviousComment.md Illustrates comments that are flagged as obvious and those that are not. Obvious comments restate code actions, while good comments explain the 'how' or 'why'. ```elixir # bad # Fetch the user user = Repo.get(User, id) # Create the changeset changeset = User.changeset(user, attrs) # Return the result {:ok, changeset} ``` ```elixir # good — no comment needed, the code is clear ``` ```elixir # good — explains HOW or WHY (not flagged despite starting with "Fetch") # Fetch the connection from the pool, blocking up to 5s conn = ConnectionPool.checkout!(pool, timeout: 5_000) ``` -------------------------------- ### Flagged AI Slop (Multiple Uses) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.UnaliasedModuleUse.md This example demonstrates code that would be flagged by the UnaliasedModuleUse check due to repeated use of `Credo.Code` within a single function. Enable this check to identify such patterns. ```elixir def run(source_file) do Credo.Code.prewalk(source_file, &walk/2, ctx) Credo.Code.remove_metadata(pattern) Credo.Code.remove_metadata(body) end ``` -------------------------------- ### Refactor Redundant `with` Statement (Good) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.WithIdentityDo.md This example demonstrates the 'good' pattern after refactoring a redundant `with` statement. The direct expression is used instead of the `with` construct when the `do` block only returns the matched value. ```elixir do_something() ``` -------------------------------- ### Refactor Redundant `with` Statement (Bad) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.WithIdentityDo.md This example shows a 'bad' pattern where a `with` statement's `do` block returns the matched pattern, indicating redundancy. This check is disabled by default and can be enabled via `.credo.exs`. ```elixir with {:ok, result} <- do_something() do {:ok, result} end ``` -------------------------------- ### Corrected Code with Alias Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.UnaliasedModuleUse.md This is the corrected version of the previous example, using an `alias` to shorten repeated module references within the function. This improves readability and avoids triggering the UnaliasedModuleUse check. ```elixir def run(source_file) do alias Credo.Code Code.prewalk(source_file, &walk/2, ctx) Code.remove_metadata(pattern) Code.remove_metadata(body) end ``` -------------------------------- ### Refactoring with Pipe Operator in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.StepComment.md This snippet shows the refactored version of the previous example, using the pipe operator to represent sequential steps. This is the preferred style. ```elixir def process(data) do data |> validate() |> transform() |> save() end ``` -------------------------------- ### Use Agent for key-value storage Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.GenserverAsKvStore.md This code shows the recommended way to implement a key-value store using Elixir's `Agent` module. It provides a more idiomatic and efficient solution. ```elixir defmodule MyCache do use Agent def start_link(initial) do Agent.start_link(fn -> initial end, name: __MODULE__) end def get(key), do: Agent.get(__MODULE__, &Map.get(&1, key)) def put(key, value), do: Agent.update(__MODULE__, &Map.put(&1, key, value)) end ``` -------------------------------- ### Register ExSlop Plugin in .credo.exs Source: https://hexdocs.pm/ex_slop/readme.md Configure your `.credo.exs` file to register ExSlop as a plugin. This enables a default set of high-signal checks. ```elixir # .credo.exs %{ configs: [ %{ name: "default", plugins: [{ExSlop, []}] } ] } ``` -------------------------------- ### Add ExSlop to mix.exs Source: https://hexdocs.pm/ex_slop/readme.md Include ExSlop as a development dependency in your `mix.exs` file. Ensure it's only loaded for development and test environments. ```elixir def deps do [ {:ex_slop, "~> 0.1", only: [:dev, :test], runtime: false} ] end ``` -------------------------------- ### Configure ExSlop Credo Plugin Source: https://hexdocs.pm/ex_slop/ExSlop.md Add ExSlop to your `.credo.exs` configuration to enable its checks. Alternatively, cherry-pick individual checks in `checks.enabled`. ```elixir %{ configs: [%{name: "default", plugins: [{ExSlop, []}]}] } ``` -------------------------------- ### Avoid Fragile Path Expansion in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.PathExpandPriv.md Use `Application.app_dir/2` for locating application resources to ensure compatibility across development, testing, and release environments. Avoid `Path.expand` with relative paths as it is fragile and breaks in releases. ```elixir Path.expand("../../priv/prompts/system.md", __DIR__) ``` ```elixir Application.app_dir(:my_app, "priv/prompts/system.md") ``` -------------------------------- ### Rescue Specific Exceptions Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.BlanketRescue.md This is the recommended approach for handling expected errors. It allows for targeted logging and error management without swallowing unexpected exceptions. ```elixir rescue e in [ArgumentError, RuntimeError] -> Logger.warning("Failed: #{Exception.message(e)}") {:error, :invalid_input} ``` -------------------------------- ### Refactoring Map Creation in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces a two-step process of mapping and then converting to a map with `Map.new`. ```elixir Enum.map(...) |> Enum.into(%{}) ``` ```elixir Map.new(...) ``` -------------------------------- ### Normalize Map Keys in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.DualKeyAccess.md Shows the correct way to handle map key access by normalizing the data once at the boundary and then using a single key type. This is the recommended pattern to avoid the DualKeyAccess warning. ```elixir Map.get(usage, :input_tokens, 0) ``` -------------------------------- ### Avoid try/rescue with safe alternatives in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.TryRescueWithSafeAlternative.md Use safe alternatives like `Integer.parse/1` instead of `String.to_integer/1` within a `try/rescue` block. This improves code clarity and avoids unnecessary exception handling. ```elixir try do String.to_integer(value) rescue _ -> nil end ``` ```elixir case Integer.parse(value) do {int, ""} -> int _ -> nil end ``` -------------------------------- ### Use ETS for key-value storage Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.GenserverAsKvStore.md This code demonstrates using Erlang Term Storage (ETS) for efficient key-value storage. ETS is a high-performance, in-memory data store suitable for this purpose. ```erlang :ets.new(:cache, [:named_table, :public]) :ets.insert(:cache, {key, value}) :ets.lookup(:cache, key) ``` -------------------------------- ### Avoid List.last/1 Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.ListLast.md Demonstrates inefficient use of `List.last/1` and a more efficient alternative when list construction is controlled. ```elixir # bad List.last(items) ``` ```elixir # better when you control construction [last | _] = Enum.reverse(items) ``` -------------------------------- ### Refactor Sort and Reverse Pattern Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.SortThenReverse.md This snippet shows the 'good' patterns that replace the identified sort and reverse operations. It demonstrates using `Enum.sort/2` with the `:desc` option or `Enum.sort_by/3` with the `:desc` option for a more concise and efficient solution. ```elixir Enum.sort(list, :desc) Enum.sort_by(list, &fun/1, :desc) ``` -------------------------------- ### Identify N+1 Queries in Enum.map Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.QueryInEnumMap.md This snippet demonstrates the anti-pattern of performing database queries inside `Enum.map`, leading to N+1 queries. Use `Repo.preload/3` for efficient data fetching instead. ```elixir users |> Enum.map(fn user -> posts = Repo.all(from p in Post, where: p.user_id == ^user.id) %{user | posts: posts} end) ``` ```elixir users |> Repo.preload(:posts) ``` -------------------------------- ### Cherry-pick ExSlop Checks Source: https://hexdocs.pm/ex_slop/readme.md Manually select specific ExSlop checks by appending them to the `extra` list in your `.credo.exs` configuration. This allows for fine-grained control over which patterns are flagged. ```elixir # .credo.exs {ExSlop.Check.Warning.BlanketRescue, []}, {ExSlop.Check.Warning.RescueWithoutReraise, []}, {ExSlop.Check.Warning.RepoAllThenFilter, []}, {ExSlop.Check.Warning.QueryInEnumMap, []}, {ExSlop.Check.Warning.GenserverAsKvStore, []}, {ExSlop.Check.Warning.PathExpandPriv, []}, {ExSlop.Check.Warning.DualKeyAccess, []}, {ExSlop.Check.Refactor.FilterNil, []}, {ExSlop.Check.Refactor.RejectNil, []}, {ExSlop.Check.Refactor.ReduceAsMap, []}, {ExSlop.Check.Refactor.MapIntoLiteral, []}, {ExSlop.Check.Refactor.IdentityPassthrough, []}, {ExSlop.Check.Refactor.IdentityMap, []}, {ExSlop.Check.Refactor.CaseTrueFalse, []}, {ExSlop.Check.Refactor.TryRescueWithSafeAlternative, []}, {ExSlop.Check.Refactor.WithIdentityElse, []}, {ExSlop.Check.Refactor.WithIdentityDo, []}, {ExSlop.Check.Refactor.SortThenReverse, []}, {ExSlop.Check.Refactor.StringConcatInReduce, []}, {ExSlop.Check.Refactor.ReduceMapPut, []}, {ExSlop.Check.Refactor.RedundantBooleanIf, []}, {ExSlop.Check.Refactor.FlatMapFilter, []}, {ExSlop.Check.Refactor.RedundantEnumJoinSeparator, []}, {ExSlop.Check.Refactor.UseMapJoin, []}, {ExSlop.Check.Refactor.PreferEnumSlice, []}, {ExSlop.Check.Refactor.GraphemesLength, []}, {ExSlop.Check.Refactor.ManualStringReverse, []}, {ExSlop.Check.Refactor.SortThenAt, []}, {ExSlop.Check.Refactor.SortForTopK, []}, {ExSlop.Check.Refactor.ListFold, []}, {ExSlop.Check.Refactor.ListLast, []}, {ExSlop.Check.Refactor.LengthInGuard, []}, {ExSlop.Check.Refactor.ExplicitSumReduce, []}, {ExSlop.Check.Readability.NarratorDoc, []}, {ExSlop.Check.Readability.DocFalseOnPublicFunction, []}, {ExSlop.Check.Readability.BoilerplateDocParams, []}, {ExSlop.Check.Readability.ObviousComment, [additional_keywords: []]}, {ExSlop.Check.Readability.StepComment, []}, {ExSlop.Check.Readability.NarratorComment, []}, {ExSlop.Check.Readability.UnaliasedModuleUse, []} ``` -------------------------------- ### Inefficient Sorting vs. Optimized Alternatives Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.SortForTopK.md Avoid sorting an entire collection when only the minimum or maximum element is required. Use `Enum.min/1` or `Enum.max/1` for better performance. ```elixir list |> Enum.sort() |> Enum.take(1) list |> Enum.sort() |> hd() ``` ```elixir Enum.min(list) Enum.max(list) ``` -------------------------------- ### Identity Passthrough with With and Else Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.IdentityPassthrough.md This pattern demonstrates an identity passthrough using a `with` statement combined with an `else` clause. The `with` block returns `{:ok, result}` if `do_something()` succeeds, and the `else` clause handles the error case by returning `{:error, reason}`, effectively just passing the result through. ```elixir with {:ok, result} <- do_something() do {:ok, result} else {:error, reason} -> {:error, reason} end ``` ```elixir do_something() ``` -------------------------------- ### String Reversal (Good) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.ManualStringReverse.md This is the recommended way to reverse a string in Elixir using the built-in `String.reverse/1` function. ```elixir String.reverse(string) ``` -------------------------------- ### Avoid `length/1` in Guards Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.LengthInGuard.md Use pattern matching instead of `length/1` in guards for better performance when checking for empty lists. This check is disabled by default and can be enabled in your `.credo.exs` configuration. ```elixir def empty?(list) when length(list) == 0, do: true ``` ```elixir def empty?([]), do: true ``` -------------------------------- ### Return Error Information from Rescue Blocks Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.RescueWithoutReraise.md Use this pattern to log an error and return specific error information, such as a tuple. This is useful when the error should be handled gracefully by the caller without halting execution. ```elixir rescue e in RuntimeError -> {:error, Exception.message(e)} ``` -------------------------------- ### Refactor Enum.drop/Enum.take to Enum.slice Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.PreferEnumSlice.md Use Enum.slice/3 when you need to drop a certain number of elements and then take a specific number of elements from a list. This is more readable than chaining Enum.drop/2 and Enum.take/2. ```elixir items |> Enum.drop(offset) |> Enum.take(limit) ``` ```elixir Enum.slice(items, offset, limit) ``` -------------------------------- ### Avoid Blanket Rescues Returning Nil Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.BlanketRescue.md This pattern swallows all exceptions by returning nil. Use specific exception handling or let the BEAM handle unexpected errors. ```elixir try do do_something() rescue _ -> nil end ``` -------------------------------- ### Avoid Loading All Records Then Filtering Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.RepoAllThenFilter.md This code demonstrates an inefficient pattern where all records are loaded into memory before filtering. Use Ecto query conditions to filter at the database level instead. ```elixir Repo.all(User) |> Enum.filter(& &1.active) ``` ```elixir User |> where(active: true) |> Repo.all() ``` -------------------------------- ### Avoid Dual Key Access in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.DualKeyAccess.md Demonstrates the incorrect way to access map keys using both atoms and strings, which can lead to an unknown data shape. This pattern is flagged by the DualKeyAccess check. ```elixir Map.get(usage, :input_tokens) || Map.get(usage, "input_tokens") || 0 get_in(data, [:path]) || get_in(data, ["path"]) payload[:kind] || payload["kind"] ``` -------------------------------- ### Inefficient String Length Calculation (Elixir) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.GraphemesLength.md Avoid building an intermediate list of graphemes just to count them. Use `String.length/1` for a more efficient approach. ```elixir string |> String.graphemes() |> length() ``` ```elixir length(String.graphemes(string)) ``` ```elixir String.length(string) ``` -------------------------------- ### Refactoring Exception Handling in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `try/rescue` blocks for safe integer parsing with the more direct `Integer.parse/1`. ```elixir try do String.to_integer(x) rescue _ -> nil end ``` ```elixir Integer.parse(x) ``` -------------------------------- ### Manual String Reversal (Bad) Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.ManualStringReverse.md This pattern manually reverses a string using graphemes, Enum.reverse, and Enum.join. Prefer `String.reverse/1` for simplicity and performance. ```elixir string |> String.graphemes() |> Enum.reverse() |> Enum.join() ``` -------------------------------- ### Recommended Credo Checks for AI Slop Source: https://hexdocs.pm/ex_slop/readme.md Lists recommended Credo built-in checks to identify common patterns in AI-generated code, such as inefficient list operations and redundant boolean logic. ```elixir # Catches length(list) == 0 (traverses entire list) → use list == [] or Enum.empty?/1 {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, ``` ```elixir # Catches acc ++ [item] (O(n²) append) → use [item | acc] then Enum.reverse {Credo.Check.Refactor.AppendSingleItem, []}, ``` ```elixir # Catches !!var (double negation) — LLMs use this to "cast to boolean" {Credo.Check.Refactor.DoubleBooleanNegation, []}, ``` ```elixir # Catches case x do true -> a; false -> b end → if/else {Credo.Check.Refactor.CondStatements, []}, ``` ```elixir # Catches Enum.map |> Enum.map → single Enum.map {Credo.Check.Refactor.MapMap, []}, ``` ```elixir # Catches Enum.filter |> Enum.filter → single Enum.filter {Credo.Check.Refactor.FilterFilter, []}, ``` ```elixir # Catches Enum.reject |> Enum.reject → single Enum.reject {Credo.Check.Refactor.RejectReject, []}, ``` ```elixir # Catches Enum.count(enum) > 0 → Enum.any?/1 {Credo.Check.Refactor.FilterCount, []}, ``` ```elixir # Catches negated conditions in unless → rewrite with positive condition {Credo.Check.Refactor.NegatedConditionsInUnless, []}, ``` ```elixir # Catches unless x do .. else .. end → if/else (clearer) {Credo.Check.Refactor.UnlessWithElse, []} ``` -------------------------------- ### Identity Passthrough with Case Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.IdentityPassthrough.md This pattern shows an identity passthrough using a `case` statement. It matches `{:ok, value}` and `{:error, reason}` only to return them directly, which is redundant. ```elixir case result do {:ok, value} -> {:ok, value} {:error, reason} -> {:error, reason} end ``` ```elixir result ``` -------------------------------- ### Refactor Enum.map |> Enum.into to Map.new Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.MapIntoLiteral.md Use this refactoring when you are mapping a list of key-value tuples into a map. `Map.new/2` is generally clearer than the `Enum.map` followed by `Enum.into` pattern. ```elixir list |> Enum.map(fn {k, v} -> {k, transform(v)} end) |> Enum.into(%{}) ``` ```elixir Map.new(list, fn {k, v} -> {k, transform(v)} end) ``` -------------------------------- ### Avoid Silent Failures in Rescue Blocks Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.RescueWithoutReraise.md Use this pattern to log an error and then re-raise it, ensuring callers are aware of the failure. This is the recommended approach when an error should halt execution or be handled further up the call stack. ```elixir rescue e -> Logger.error("Failed: #{inspect(e)}") reraise e, __STACKTRACE__ ``` -------------------------------- ### Refactoring Manual String Reverse to String.reverse in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces manual string reversal using graphemes and join with `String.reverse/1`. ```elixir String.graphemes(s) |> Enum.reverse() |> Enum.join() ``` ```elixir String.reverse(s) ``` -------------------------------- ### Refactor Enum.reduce to Enum.map Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.ReduceAsMap.md Avoid using `Enum.reduce` to build a reversed list or with O(n^2) list concatenation. Use `Enum.map/2` instead for a more efficient and idiomatic solution. ```elixir Enum.reduce(items, [], fn item, acc -> [transform(item) | acc] end) ``` ```elixir Enum.reduce(items, [], fn item, acc -> acc ++ [transform(item)] end) ``` ```elixir Enum.map(items, &transform/1) ``` -------------------------------- ### Inefficient String Concatenation in Enum.reduce/3 Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.StringConcatInReduce.md Avoid using the <> operator within Enum.reduce/3 to build strings, as this results in O(n^2) complexity. Use Enum.join/1 or Enum.map_join/2 for better performance. ```elixir Enum.reduce(list, "", fn item, acc -> acc <> item end) ``` ```elixir Enum.reduce(list, "", fn item, acc -> acc <> to_string(item) end) ``` -------------------------------- ### Using Pattern Matching for Empty Lists in Guards in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `length(xs) == 0` in function guards with pattern matching on `[]` for efficiency. ```elixir def f(xs) when length(xs) == 0 ``` ```elixir pattern match on `[]` / `[_ | _]` ``` -------------------------------- ### Refactoring Sort for Top K Elements in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces sorting a list and taking the top K elements with specialized top-k selection algorithms. ```elixir Enum.sort() |> Enum.take(1) ``` ```elixir Enum.min/1, Enum.max/1, or top-k selection ``` -------------------------------- ### Efficient String Concatenation Alternatives Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.StringConcatInReduce.md Use Enum.join/1 for concatenating a list of strings or Enum.map_join/2 when elements need transformation before joining. These methods offer better performance than string concatenation within Enum.reduce/3. ```elixir Enum.join(list) ``` ```elixir Enum.map_join(list, &to_string/1) ``` -------------------------------- ### Refactoring Map and Join to Map.join in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `Enum.map(...) |> Enum.join(...)` with the more efficient `Enum.map_join(...)`. ```elixir Enum.map(...) |> Enum.join(...) ``` ```elixir Enum.map_join(...) ``` -------------------------------- ### Refactoring Map Updates in Reduce to Map.new in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `Enum.reduce` with `Map.put` to build maps with `Map.new/2`. ```elixir Enum.reduce(%{}, fn x, acc -> Map.put(acc, k, v) end) ``` ```elixir Map.new/2 ``` -------------------------------- ### Refactor verbose reduce to build a map Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.ReduceMapPut.md Avoid using `Enum.reduce` with `Map.put` to build a map. This pattern is verbose and can be replaced with more idiomatic Elixir constructs. ```elixir Enum.reduce(batch, %{}, fn event, acc -> Map.put(acc, event.id, event) end) ``` ```elixir Map.new(batch, fn event -> {event.id, event} end) ``` ```elixir for event <- batch, into: %{}, do: {event.id, event} ``` -------------------------------- ### Refactoring Sort for First Element to Min/Max in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces sorting a list and taking the first element with `Enum.min/1` or `Enum.max/1`. ```elixir Enum.sort() |> Enum.at(0) ``` ```elixir Enum.min/1, Enum.max/1, or selection logic ``` -------------------------------- ### Detecting Step Comments in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Readability.StepComment.md This snippet demonstrates a function with step-like comments that indicate it's doing too much. This pattern is flagged by the `StepComment` check. ```elixir def process(data) do # Step 1: Validate the input validated = validate(data) # Step 2: Transform the data transformed = transform(validated) # Step 3: Save to database save(transformed) end ``` -------------------------------- ### Avoid Logging and Returning Generic Atoms in Rescue Blocks Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.RescueWithoutReraise.md This pattern is flagged by the check because it logs an error but then returns a generic atom, which can hide the actual failure from the caller. Avoid this approach in favor of re-raising or returning specific error information. ```elixir rescue e -> Logger.error("Failed: #{inspect(e)}") :error ``` -------------------------------- ### Refactoring Case Statements to If/Else in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `case` statements with boolean conditions to a more concise `if/else` structure. ```elixir case flag do true -> a; false -> b end ``` ```elixir if flag, do: a, else: b ``` -------------------------------- ### Inefficient List Sorting Pattern Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.SortThenAt.md Avoid sorting an entire list when only an element at a specific index is needed. Use `Enum.min` or `Enum.max` for finding minimum or maximum values. ```elixir # bad list |> Enum.sort() |> Enum.at(0) Enum.at(Enum.sort(list), 0) ``` ```elixir # good — for min/max cases Enum.min(list) Enum.max(list) ``` -------------------------------- ### Refactor Nil Rejection in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.RejectNil.md Use `Enum.reject(&is_nil/1)` instead of `Enum.reject(fn x -> x == nil end)` for more concise and idiomatic Elixir code. This check is disabled by default and can be enabled in your `.credo.exs` configuration file. ```elixir list |> Enum.reject(fn x -> x == nil end) ``` ```elixir list |> Enum.reject(fn x -> x === nil end) ``` ```elixir list |> Enum.reject(fn x -> is_nil(x) end) ``` ```elixir list |> Enum.reject(&is_nil/1) ``` -------------------------------- ### Refactor Nil Filtering in Elixir Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.FilterNil.md This snippet demonstrates the incorrect and correct ways to filter out nil values from a list in Elixir. Use `Enum.reject(&is_nil/1)` for a more idiomatic and efficient approach. ```elixir list |> Enum.filter(fn x -> x != nil end) ``` ```elixir list |> Enum.filter(fn x -> x !== nil end) ``` ```elixir list |> Enum.filter(fn x -> !is_nil(x) end) ``` ```elixir list |> Enum.reject(&is_nil/1) ``` -------------------------------- ### Preferring Enum.slice over Drop and Take in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `Enum.drop(n) |> Enum.take(k)` with the more direct `Enum.slice/3`. ```elixir Enum.drop(n) |> Enum.take(k) ``` ```elixir Enum.slice(enum, n, k) ``` -------------------------------- ### Prefer Enum.reduce/3 over List.foldl/3 Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.ListFold.md Use Enum.reduce/3 for folding lists in Elixir. This check is disabled by default and can be enabled in your .credo.exs configuration file. ```elixir List.foldl(items, 0, fn item, acc -> item + acc end) ``` ```elixir Enum.reduce(items, 0, fn item, acc -> item + acc end) ``` -------------------------------- ### Simplifying Identity Passthrough in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Removes redundant `case` statements that simply return the input value. ```elixir case r do {:ok, v} -> {:ok, v}; {:error, e} -> {:error, e} end ``` ```elixir r ``` -------------------------------- ### Refactor Enum.map/2 |> Enum.join/1 to Enum.map_join/3 Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.UseMapJoin.md Use Enum.map_join/3 to avoid creating an intermediate list when mapping and joining items. This check is disabled by default. ```elixir items |> Enum.map(&to_string/1) |> Enum.join(",") ``` ```elixir Enum.map_join(items, ",", &to_string/1) ``` -------------------------------- ### Refactor Enum.reduce/3 to Enum.sum/1 Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.ExplicitSumReduce.md Use Enum.sum/1 when Enum.reduce/3 is only used for summing values. This improves code clarity. This check is disabled by default. ```elixir Enum.reduce(nums, 0, fn num, acc -> num + acc end) ``` ```elixir Enum.sum(nums) ``` -------------------------------- ### Identify Sort and Reverse Pattern Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.SortThenReverse.md This snippet shows the 'bad' patterns that the SortThenReverse check identifies. It highlights the use of `Enum.sort/1` followed by `Enum.reverse/1`, or `Enum.sort_by/2` followed by `Enum.reverse/1`, which can be refactored. ```elixir list |> Enum.sort() |> Enum.reverse() Enum.reverse(Enum.sort(list)) list |> Enum.sort_by(&fun/1) |> Enum.reverse() ``` -------------------------------- ### Using Enum.sum over Explicit Reduce in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces explicit `Enum.reduce` for summing numbers with the more concise `Enum.sum/1`. ```elixir Enum.reduce(nums, 0, fn n, acc -> n + acc end) ``` ```elixir Enum.sum(nums) ``` -------------------------------- ### Refactor Case True/False to If/Else Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.CaseTrueFalse.md Use this check to refactor `case` statements that only match on `true` and `false`. This improves code readability by using `if`/`else` for boolean conditions. ```elixir case some_condition() do true -> :yes false -> :no end ``` ```elixir if some_condition(), do: :yes, else: :no ``` -------------------------------- ### Simplifying Redundant Boolean If Statements in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `if cond, do: true, else: false` with the condition itself. ```elixir if cond, do: true, else: false ``` ```elixir use the condition directly ``` -------------------------------- ### Simplifying Identity With Statements in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Removes redundant `with` statements that simply return the result of a function call. ```elixir with {:ok, v} <- f() do {:ok, v} end ``` ```elixir f() ``` -------------------------------- ### Refactoring String Concatenation in Reduce to Join in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces string concatenation within `Enum.reduce` with `Enum.join/1` or IO data for better performance. ```elixir Enum.reduce("", fn x, acc -> acc <> x end) ``` ```elixir Enum.join/1 or IO data ``` -------------------------------- ### Avoiding List.last after Traversal in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Suggests avoiding the need for `List.last/1` by restructuring logic to not require the last element after traversal. ```elixir List.last(list) ``` ```elixir avoid needing the last element after traversal ``` -------------------------------- ### Simplifying Redundant Enum.join Separator in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Removes the empty string separator from `Enum.join` when it's not needed. ```elixir Enum.join(parts, "") ``` ```elixir Enum.join(parts) ``` -------------------------------- ### Refactor FlatMap to Filter Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.FlatMapFilter.md Avoid using `Enum.flat_map` with conditional logic that returns singleton or empty lists, as this is less efficient than `Enum.filter`. This refactoring applies when the `flat_map` operation's sole purpose is to filter elements based on a condition. ```elixir Enum.flat_map(items, fn item -> if item.active, do: [item], else: [] end) ``` ```elixir Enum.filter(items, & &1.active) ``` -------------------------------- ### Avoid Generic Error Tuples in Rescues Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Warning.BlanketRescue.md Returning a generic error tuple like `{:error, "Something went wrong"}` loses valuable exception context. Prefer specific error types or detailed messages. ```elixir rescue _e -> {:error, "Something went wrong"} ``` -------------------------------- ### Refactor Redundant 'with' Identity Else Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.WithIdentityElse.md Use this refactoring when an 'else' block in a 'with' statement returns the exact value it matched, making the 'else' block unnecessary. This check is disabled by default and can be enabled in your .credo.exs configuration file. ```elixir # bad — identity else with {:ok, result} <- do_something() do {:ok, result} else {:error, reason} -> {:error, reason} end ``` ```elixir # good do_something() ``` -------------------------------- ### Refactoring Grapheme Length to String Length in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `String.graphemes(s) |> length()` with the more efficient `String.length(s)`. ```elixir String.graphemes(s) |> length() ``` ```elixir String.length(s) ``` -------------------------------- ### Refactoring Sort and Reverse in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Replaces `Enum.sort() |> Enum.reverse()` with the more efficient `Enum.sort(:desc)`. ```elixir Enum.sort() |> Enum.reverse() ``` ```elixir Enum.sort(:desc) ``` -------------------------------- ### Simplifying With Statements in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Removes the `else` clause from `with` statements when it's not needed. ```elixir with {:ok, v} <- f() do v else {:error, r} -> {:error, r} end ``` ```elixir drop the `else` ``` -------------------------------- ### Refactor Redundant Boolean If Expressions Source: https://hexdocs.pm/ex_slop/ExSlop.Check.Refactor.RedundantBooleanIf.md This check identifies and suggests refactoring for redundant boolean conditional expressions. It flags cases where a boolean condition is wrapped in an `if/true/false` structure, recommending the direct use of the expression instead. ```elixir is_active = if status == :active, do: true, else: false if !is_nil(x) and !is_nil(y), do: true, else: false ``` ```elixir is_active = status == :active !is_nil(x) and !is_nil(y) ``` -------------------------------- ### Removing Redundant Identity Map in Elixir Source: https://hexdocs.pm/ex_slop/readme.md Eliminates `Enum.map` calls where the function simply returns the input. ```elixir Enum.map(fn x -> x end) ``` ```elixir remove the call ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.