profile
viewpoint

c0b/chrome-in-docker 195

run Google Chrome in container (as a perfect headless browser)

c0b/docker-elixir 187

Official Docker image for Elixir :whale: :turtle: :rocket:

erlang/docker-erlang-otp 141

the Official Erlang OTP image on Docker Hub

c0b/gosuv 1

Process managerment writtern by golang, inspired by python-supervisor

c0b/beam 0

Mirror of Apache Beam

c0b/chrome-remote-interface 0

Chrome Remote Debugging Protocol interface

c0b/comm 0

Communication primitives

c0b/docker 0

Docker - the open-source application container engine

push eventelixir-lang/elixir

Zach Daniel

commit sha 157cc70f65478d9db18d1bfe27e4ce3e5a82cc6c

Add `Enum.count_until/2` and `Enum.count_until/3` (#10532)

view details

push time in 5 hours

pull request commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

:green_heart: :blue_heart: :purple_heart: :yellow_heart: :heart:

zachdaniel

comment created time in 5 hours

PR merged elixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

The discussion around it can be found here: https://groups.google.com/g/elixir-lang-core/c/ZJ3yUnVaF0c/m/NBElBo4GBwAJ

+106 -1

0 comment

3 changed files

zachdaniel

pr closed time in 5 hours

pull request commentelixir-lang/elixir

Indent specs after line breaks

I agree. The issue is only related to ExDoc.

eksperimental

comment created time in 11 hours

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  This is useful for checking certain properties of the count of an enumerable+  without having to actually count the entire enumerable. For example, if you+  wanted to check that the count was exactly, at least, or more than a value.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+      iex> Enum.count_until(1..10, 10) == 10 # At least 10+      true+      iex> Enum.count_until(1..11, 10 + 1) > 10 # More than 10+      true+      iex> Enum.count_until(1..5, 10) < 10 # Less than 10+      true+      iex> Enum.count_until(1..10, 10 + 1) == 10 # Exactly ten+      true++  """+  @doc since: "1.12.0"+  @spec count_until(t, pos_integer) :: non_neg_integer+  def count_until(enumerable, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    case Enumerable.count(enumerable) do+      {:ok, value} ->+        Kernel.min(value, limit)++      {:error, module} ->+        enumerable+        |> module.reduce(+          {:cont, 0},+          fn+            _, ^stop_at ->+              {:halt, limit}++            _, acc ->+              {:cont, acc + 1}+          end+        )+        |> elem(1)+    end+  end++  @doc """+  Counts the elements in the enumerable for which `fun` returns a truthy value, stopping at `limit`.++  See `count/2` for more information.++  ## Examples+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 7)+      7+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 11)+      10+  """+  @doc since: "1.12.0"+  @spec count_until(t, (element -> as_boolean(term)), pos_integer) :: non_neg_integer+  def count_until(enumerable, fun, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    reduce_while(enumerable, 0, fn+      entry, ^stop_at ->+        if fun.(entry) do+          {:halt, limit}+        else+          {:cont, stop_at}+        end++      entry, acc ->+        if fun.(entry) do+          {:cont, acc + 1}+        else+          {:cont, acc}+        end+    end)
    end)
    |> elem(1)
zachdaniel

comment created time in 13 hours

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  This is useful for checking certain properties of the count of an enumerable+  without having to actually count the entire enumerable. For example, if you+  wanted to check that the count was exactly, at least, or more than a value.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+      iex> Enum.count_until(1..10, 10) == 10 # At least 10+      true+      iex> Enum.count_until(1..11, 10 + 1) > 10 # More than 10+      true+      iex> Enum.count_until(1..5, 10) < 10 # Less than 10+      true+      iex> Enum.count_until(1..10, 10 + 1) == 10 # Exactly ten+      true++  """+  @doc since: "1.12.0"+  @spec count_until(t, pos_integer) :: non_neg_integer+  def count_until(enumerable, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    case Enumerable.count(enumerable) do+      {:ok, value} ->+        Kernel.min(value, limit)++      {:error, module} ->+        enumerable+        |> module.reduce(+          {:cont, 0},+          fn+            _, ^stop_at ->+              {:halt, limit}++            _, acc ->+              {:cont, acc + 1}+          end+        )+        |> elem(1)+    end+  end++  @doc """+  Counts the elements in the enumerable for which `fun` returns a truthy value, stopping at `limit`.++  See `count/2` for more information.++  ## Examples+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 7)+      7+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 11)+      10+  """+  @doc since: "1.12.0"+  @spec count_until(t, (element -> as_boolean(term)), pos_integer) :: non_neg_integer+  def count_until(enumerable, fun, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    reduce_while(enumerable, 0, fn
    Enumerable.reduce(enumerable, {:cont, 0}, fn
zachdaniel

comment created time in 13 hours

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  This is useful for checking certain properties of the count of an enumerable+  without having to actually count the entire enumerable. For example, if you+  wanted to check that the count was exactly, at least, or more than a value.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+      iex> Enum.count_until(1..10, 10) == 10 # At least 10+      true+      iex> Enum.count_until(1..11, 10 + 1) > 10 # More than 10+      true+      iex> Enum.count_until(1..5, 10) < 10 # Less than 10+      true+      iex> Enum.count_until(1..10, 10 + 1) == 10 # Exactly ten+      true++  """+  @doc since: "1.12.0"+  @spec count_until(t, pos_integer) :: non_neg_integer+  def count_until(enumerable, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    case Enumerable.count(enumerable) do+      {:ok, value} ->+        Kernel.min(value, limit)++      {:error, module} ->+        enumerable+        |> module.reduce(+          {:cont, 0},+          fn+            _, ^stop_at ->+              {:halt, limit}++            _, acc ->+              {:cont, acc + 1}+          end+        )+        |> elem(1)+    end+  end++  @doc """+  Counts the elements in the enumerable for which `fun` returns a truthy value, stopping at `limit`.++  See `count/2` for more information.++  ## Examples
  See `count/2` and `count_until/3` for more information.

  ## Examples

zachdaniel

comment created time in 13 hours

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  This is useful for checking certain properties of the count of an enumerable+  without having to actually count the entire enumerable. For example, if you+  wanted to check that the count was exactly, at least, or more than a value.
  This is useful for checking certain properties of the count of an enumerable
  without having to actually count the entire enumerable. For example, if you
  wanted to check that the count was exactly, at least, or more than a value.

  If the enumerable implements `c:Enumerable.count/1`, the enumerable is
  not traversed and we return the lower of the two numbers. To force
  enumeration, use `count_until/3` with `fn _ -> true end` as the second
  argument.
zachdaniel

comment created time in 13 hours

PR closed elixir-lang/elixir

Indent specs after line breaks

Related to https://github.com/elixir-lang/ex_doc/pull/1296

+12 -0

0 comment

2 changed files

eksperimental

pr closed time in 13 hours

Pull request review commentelixir-lang/elixir

Indent specs after line breaks

 defmodule IEx.HelpersTest do       assert capture_io(fn -> h(def) end) =~ def_h     end +    test "indents after line break in long specs" do+      spec =+        "\n" <>+          "  @spec ascii_printable?([...], limit) :: boolean()\n" <>+          "          when limit: :infinity | pos_integer()\n"

If we consider Elixir's indention, the code is actually correct. So I will close this. Thank you!

eksperimental

comment created time in 13 hours

Pull request review commentelixir-lang/elixir

Indent specs after line breaks

 defmodule IEx.HelpersTest do       assert capture_io(fn -> h(def) end) =~ def_h     end +    test "indents after line break in long specs" do+      spec =+        "\n" <>+          "  @spec ascii_printable?([...], limit) :: boolean()\n" <>+          "          when limit: :infinity | pos_integer()\n"

Also note that Elixir doesn't indent when. This is how Elixir formats this code:

@spec ascii_printable?([...], limit) :: boolean()
      when limit: :infinity | pos_integer()
eksperimental

comment created time in 13 hours

Pull request review commentelixir-lang/elixir

Indent specs after line breaks

 defmodule IEx.Introspection do     string = "@#{kind} #{Macro.to_string(definition)}"      try do+      whitespace = String.duplicate(" ", nesting)+       string       |> Code.format_string!(line_length: IEx.width() - 2 * nesting)       |> IO.iodata_to_binary()+      |> String.replace("\n", "\n#{whitespace}")

I am afraid this is going to be indented twice, because we already indent after the try/catch block.

eksperimental

comment created time in 13 hours

issue commentelixir-lang/elixir

MatchError coverage test with specific macro and typespecs

@sb8244 right, they would most likely accept a PR that made it clearer. However, in this case, it is also an Elixir bug, so I filed a separate report too. Thanks!

Eiji7

comment created time in 13 hours

issue openedelixir-lang/elixir

Check dialyzer attributes

Otherwise a module may fail to be cover compiled with an unclear error message. We need to port the checks from here:

https://github.com/erlang/otp/blob/master/lib/stdlib/src/erl_lint.erl#L959

See: https://github.com/elixir-lang/elixir/issues/9460#issuecomment-739119712

created time in 13 hours

PR opened elixir-lang/elixir

Indent specs after line breaks

Related to https://github.com/elixir-lang/ex_doc/pull/1296

+12 -0

0 comment

2 changed files

pr created time in 18 hours

issue commentelixir-lang/elixir

MatchError coverage test with specific macro and typespecs

I know this is a long dead issue, but I figure it wouldn't hurt to ask here.

Do you think that adding the module that is being compiled (and failed) to the :cover.do_compile_beam2/6 error would be a experience improvement? Or is there something I'm missing and it wouldn't be a good idea? It seems like a potential good first commit to BEAM for me if it's a good idea.

I just spent ~2 hours tracking down this same error, and it ended up being a dialyzer module attribute ignoring a function that didn't exist (copy/paste and forgot to rename it). Like @dialyzer {:nowarn_function, execute: 2}

Eiji7

comment created time in 19 hours

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  This is useful for checking certain properties of the count of an enumerable+  without having to actually count the entire enumerable. For example, if you+  wanted to check that the count was exactly, at least, or more than a value.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+      iex> Enum.count_until(1..10, 10) == 10 # At least 10+      true+      iex> Enum.count_until(1..11, 10 + 1) > 10 # More than 10+      true+      iex> Enum.count_until(1..5, 10) < 10 # Less than 10+      true+      iex> Enum.count_until(1..10, 10 + 1) == 10 # Exactly ten+      true++  """+  @doc since: "1.12.0"+  @spec count_until(t, pos_integer) :: integer

Yep, good point.

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  This is useful for checking certain properties of the count of an enumerable+  without having to actually count the entire enumerable. For example, if you+  wanted to check that the count was exactly, at least, or more than a value.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+      iex> Enum.count_until(1..10, 10) == 10 # At least 10+      true+      iex> Enum.count_until(1..11, 10 + 1) > 10 # More than 10+      true+      iex> Enum.count_until(1..5, 10) < 10 # Less than 10+      true+      iex> Enum.count_until(1..10, 10 + 1) == 10 # Exactly ten+      true++  """+  @doc since: "1.12.0"+  @spec count_until(t, pos_integer) :: integer

Would we want to specify the return value of these functions as non_neg_integer too?

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+  """+  def count_until(enumerable, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    case Enumerable.count(enumerable) do+      {:ok, value} ->+        Kernel.min(value, limit)++      {:error, module} ->+        enumerable+        |> module.reduce(+          {:cont, 0},+          fn+            _, ^stop_at ->+              {:halt, limit}++            _, acc ->+              {:cont, acc + 1}+          end+        )+        |> elem(1)+    end+  end++  @doc """+  Counts the elements in the enumerable for which `fun` returns a truthy value, stopping at `limit`.++  ## Examples+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 7)+      7+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 11)+      10+  """

I suggest for count_until/2 to be defined in terms of count_until/3 using the function fn _ -> true end.

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+

added

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  ## Examples

added

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  ## Examples

Jose had some good examples in the thread for is-at-least and is-exactly scenarios that would be worth adding as examples. In particular, if you want to know that you have exactly ten items, the fact that you need to count_until(enum, 11) is non-obvious.

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+  """+  def count_until(enumerable, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    case Enumerable.count(enumerable) do+      {:ok, value} ->+        Kernel.min(value, limit)++      {:error, module} ->+        enumerable+        |> module.reduce(+          {:cont, 0},+          fn+            _, ^stop_at ->+              {:halt, limit}++            _, acc ->+              {:cont, acc + 1}+          end+        )+        |> elem(1)+    end+  end++  @doc """+  Counts the elements in the enumerable for which `fun` returns a truthy value, stopping at `limit`.++  ## Examples+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 7)+      7+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 11)+      10+  """

Same here

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+  """

You can be more specific with non_neg_integer()

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+

I'd add a small explanation about why someone would want to use it.

zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+  """
  """
  @doc since: "1.12.0"
  @spec count_until(t, non_neg_integer) :: integer
zachdaniel

comment created time in a day

Pull request review commentelixir-lang/elixir

feat: implement `Enum.count_until/2` and `Enum.count_until/3`

 defmodule Enum do     end)   end +  @doc """+  Counts the enumerable stopping at `limit`.+++  If the enumerable implements `c:Enumerable.count/1`, this optimization is+  not discarded. We simply call it and return the lower of the two numbers.+  This means that `count_until/2` may not iterate over each item until count+  is reached. To force enumeration, use `count_until/3`.++  ## Examples++      iex> Enum.count_until(1..20, 5)+      5+      iex> Enum.count_until(1..20, 50)+      20+  """+  def count_until(enumerable, limit) when is_integer(limit) and limit > 0 do+    stop_at = limit - 1++    case Enumerable.count(enumerable) do+      {:ok, value} ->+        Kernel.min(value, limit)++      {:error, module} ->+        enumerable+        |> module.reduce(+          {:cont, 0},+          fn+            _, ^stop_at ->+              {:halt, limit}++            _, acc ->+              {:cont, acc + 1}+          end+        )+        |> elem(1)+    end+  end++  @doc """+  Counts the elements in the enumerable for which `fun` returns a truthy value, stopping at `limit`.++  ## Examples+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 7)+      7+      iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 11)+      10+  """
  """
 @doc since: "1.12.0"
 @spec count_until(t, non_neg_integer) :: integer
zachdaniel

comment created time in a day

pull request commentelixir-lang/elixir

Be specific about lists when they are proper lists

The convention is that all lists are proper unless it is said they are explicitly improper. I really don't want to add the "proper" prefix to everything because I think it will be verbose and potentially even confusing. Thank you!

I agree with not mentioning it everywhere, so the change in the Keyword module can be ignored, but after so all these years I was not 100% if the spec [type] would include improper lists. So I went to read the Typespec page and is not clear: I had to take my conclusions by making reading reference after reference: [type] -> [...] -> nonempty_list(type) -> "non-empty proper list"

eksperimental

comment created time in a day

pull request commentelixir-lang/elixir

Be specific about lists when they are proper lists

The convention is that all lists are proper unless it is said they are explicitly improper. I really don't want to add the "proper" prefix to everything because I think it will be verbose and potentially even confusing. Thank you!

Is this convention formally written somewhere in the docs?

eksperimental

comment created time in a day

more