-
-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Missing primitive take_from(bag, amount)
#209
Comments
Side note: I'm using this construct quite often, maybe StreamData.one_of(things |> Enum.map(&StreamData.constant/1)) |
take_from(bag, length)
take_from(bag, amount)
The issue with (As for the |
I do not understand the intricacies of shrinking, so I can't really contribute much here. Is My actual main use case at the moment is generating chess positions. For this it's not clear what kind of shrinking would actually be desired. Other idea for more efficient implementation: I don't know enough haskell to understand the source, but maybe this helps? So maybe the missing primitive is actually |
Agreed for this case but all generators must think of what is a good way to shrink. In general yes shrinking towards "earlier" elements in the list is a good general strategy. I think the primitive is not necessarily missing, we just need to extend |
If we extend it, then it should be called I would still prefer |
If the behavior is taking from the collection then yeah but I’m not sure that's helpful. The example above could be rewritten as [card1, card2, card3, card4] <- members_of(bag, 4),
hand1 = {card1, card2},
hand2 = {card3, card4} right? |
But maybe just having The example I provided is a bit too simplified, as here taking 4 cards at once would work as well. In the first draw I place all white pieces, then I place the black pieces. The placement of the black pieces is constrained by where the white pieces where placed, for instance I can't place the black king right next to the white one. |
I think shuffling is probably a good base though, that's right. |
Alright then. I think I understand the Haskell implementation now and have replicated it below: def shuffle(bag) do
StreamData.list_of(StreamData.float(), length: length(bag))
|> StreamData.map(fn sort ->
Enum.zip(bag, sort)
|> Enum.sort_by(&elem(&1, 1))
|> Enum.unzip()
|> elem(0)
end)
end Would that be good for a PR? Would this shrink towards unsorted? How do I test the shrinking? |
Don't worry about testing the shrinking for now. I think it would be nice to implement this with a lazy tree directly since it could be a pretty fundamental primitive, so optimizing would be great, but the implementation is a bit less intuitive. Maybe diving through the source a bit would help, plus https://elixir-lang.org/blog/2017/10/31/stream-data-property-based-testing-and-data-generation-for-elixir/ 🙃 |
First of, thank you for creating and maintaining this great library!
I think there is a missing primitive which I needed quite often when writing generators:
take_from(bag, amount)
Sample usage:
I think this should be in the library, since I struggled quite a bit with implementing it myself.
First I tried this horrible mess:
It works, but throws
StreamData.TooManyDuplicatesError
quite often.I then improved it quite a bit with this recursive version:
But I still think there could be a better version, probably one that would use
Enum.take_random/2
.But I can't figure it out.
Any ideas? Could we get this into the library?
The text was updated successfully, but these errors were encountered: