Closed jesperes closed 1 year ago
@jesperes Thank you for submitting this, I always like it when we can add another language to the collection. As a former user of CouchDB and RabbitMQ, I'm particularly pleased to see a solution in Erlang.
I've reviewed the solution, and I think we will have to change the faithfulness qualification. This relates to the second requirement for faithful solutions as mentioned in the respective section of the contributing guidelines:
- It uses a class to encapsulate the sieve, or a (closest) equivalent feature in your language if a class construct is not available. This class must contain the full state of the sieve. Each iteration should re-create a new instance of this class from scratch.
As far as I can tell, the solution is currently purely procedural. I recognize that Erlang may not offer a class-like structure to use, but as has been documented many times in earlier PRs that doesn't change the evaluation of this part of the rules.
Admittedly, it uses the non-functional atomics
module to store the bits, but apart from that it isn't fundamentally different from e.g. Elixir/solution_2. How would you recommend I modify the solution if I want to keep it faithful?
I'm not sure it is possible to create an Erlang solution that is faithful by the contributor guidelines definition. There's quite a few languages that don't offer a structure in which the "entire sieve state" (by now established to be at least the sieve buffer and sieve limit) can be captured. That means that there are languages for which only "unfaithful" solutions exist, even though their authors would have made them faithful if it were possible. That said, in the case of the Elixir solution you refer to, there is a function that does create an object-like structure:
def create_sieve(size) do
size = div2(size)
<<-1::size(size)>>
end
This structure is then passed to/between functions that are involved with calculating the sieve and processing results. If you could do something similar in your Erlang solution, that would be enough to qualify the solution as faithful.
It may help when I add that the label "faithful" in the context of Primes can be considered an unfortunate choice of words. It's a label for a number of implementation characteristics that could be viewed as more or less arbitrary. That being as it may, it's just the nomenclature we've settled on over the past 2 years. (In fact, when Dave uses the "faithful" denomination, he means a blend of "base algorithm", some of the faithful characteristics as discussed here, and 1 bit per prime.)
Ok, I'll rewrite it to store the sieve buffer and the sieve limit in a record (in Erlang terminology).
Refactored the code to use a #sieve
record:
-spec sieve_new(Size :: integer()) -> sieve().
sieve_new(Size) ->
#sieve{q = math:sqrt(Size),
size = Size,
bits = atomics:new(Size, [])}.
Hopefully this satisfies the "faithful" criteria.
Description
Straight-forward Erlang solution.
Contributing requirements
drag-race
as the target branch.