Skip to content

Add nullable/2 generator#221

Merged
whatyouhide merged 7 commits intowhatyouhide:mainfrom
Munksgaard:nullable
Sep 19, 2025
Merged

Add nullable/2 generator#221
whatyouhide merged 7 commits intowhatyouhide:mainfrom
Munksgaard:nullable

Conversation

@Munksgaard
Copy link
Copy Markdown
Contributor

As discussed in #220, this PR implements a nullable/2 generator. It returns either the result of the generator given as the first argument or nil. The default ratio between the two possibilities is 0.5, but can be adjusted using the :ratio option.

Fixes #220

As discussed in whatyouhide#220, this PR implements a `nullable/2` generator. It returns
either the result of the generator given as the first argument or `nil`. The
default ratio between the two possibilities is 0.5, but can be adjusted using
the `:ratio` option.

Fixes whatyouhide#220
@Munksgaard
Copy link
Copy Markdown
Contributor Author

One pattern that I've also found useful is to be able to say nullable([some, other, generators]) and then have nullable inject nil with even possibility as the others, e.g. nullable([some, other, generators]) ~= one_of([nil, some, other, generators]). This is probably a more controversial suggestion, which is why I haven't added it in this PR, but I'm wondering if there would be interest in it?

@whatyouhide
Copy link
Copy Markdown
Owner

This is probably a more controversial suggestion, which is why I haven't added it in this PR, but I'm wondering if there would be interest in it?

I think the API surface is already large and that doesn't seem like a very useful addition. Also same as:

[some, other, gen]
|> one_of()
|> nullable()

Copy link
Copy Markdown
Owner

@whatyouhide whatyouhide left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice start! I left comments with minor tweaks. Also, why did you decide to force < 1.0 instead of <= 1.0?

Comment thread lib/stream_data.ex Outdated
Comment thread lib/stream_data.ex Outdated
Comment thread lib/stream_data.ex
Comment thread lib/stream_data.ex Outdated
Comment thread lib/stream_data.ex Outdated
@Munksgaard
Copy link
Copy Markdown
Contributor Author

This is probably a more controversial suggestion, which is why I haven't added it in this PR, but I'm wondering if there would be interest in it?

I think the API surface is already large and that doesn't seem like a very useful addition. Also same as:

[some, other, gen]
|> one_of()
|> nullable()

I don't think that is the same as what I was suggesting. In your code, nil would have 50% probability of being returned. In my suggested code it would have 25% probability of being returned.

However, I agree that the API surface is already large. I'll leave it as is.

Munksgaard and others added 5 commits August 29, 2025 13:19
Co-authored-by: Andrea Leopardi <[email protected]>
Co-authored-by: Andrea Leopardi <[email protected]>
Co-authored-by: Andrea Leopardi <[email protected]>
Co-authored-by: Andrea Leopardi <[email protected]>
Co-authored-by: Andrea Leopardi <[email protected]>
@Munksgaard
Copy link
Copy Markdown
Contributor Author

Your review suggestions are much appreciated. I've applied all of them.

As for the choice to force < 1.0 instead of <= 1.0, I don't think specifying a ratio of 1.0 make sense. After all, it would mean that the generator always return nil.

Also, when I wrote up the initial implementation, I tried to do funky division stuff, so I wanted to guard against an accidental division by zero. This is not a problem anymore, so I'm fine with relaxing the boundaries if you want.

@Munksgaard Munksgaard requested a review from whatyouhide August 29, 2025 11:23
@whatyouhide
Copy link
Copy Markdown
Owner

I don't think that is the same as what I was suggesting. In your code, nil would have 50% probability of being returned. In my suggested code it would have 25% probability of being returned.

Solved by |> nullable(ratio: 0.25)? or |> nullable(ratio: length(generators) / (length(generators) + 1)) or something.

I don't think specifying a ratio of 1.0 make sense.

Then 0.0 doesn't make sense either, and in any case, allowing both makes it easier to have that ratio come from other parts of the code if necessary. So yes, let's relax this.

The nullable ratio is now allowed to be 0.0 and 1.0.
@Munksgaard
Copy link
Copy Markdown
Contributor Author

Solved by |> nullable(ratio: 0.25)? or |> nullable(ratio: length(generators) / (length(generators) + 1)) or something.

Correct.

Then 0.0 doesn't make sense either, and in any case, allowing both makes it easier to have that ratio come from other parts of the code if necessary. So yes, let's relax this.

0.0 also wasn't allowed, but I've pushed a new commit that relaxes the constraints.

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build dac84709b7ef95616a3e131ecd7ff9dd36a4d712-PR-221

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 2 of 2 (100.0%) changed or added relevant lines in 1 file are covered.
  • 11 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.9%) to 93.208%

Files with Coverage Reduction New Missed Lines %
lib/stream_data.ex 11 93.48%
Totals Coverage Status
Change from base Build 1f220e88b6df08fbe5a3f83c8e1c35d887171bf5: -0.9%
Covered Lines: 398
Relevant Lines: 427

💛 - Coveralls

@whatyouhide whatyouhide merged commit 0746c34 into whatyouhide:main Sep 19, 2025
1 of 2 checks passed
@whatyouhide
Copy link
Copy Markdown
Owner

Thanks @Munksgaard 💟

@Munksgaard
Copy link
Copy Markdown
Contributor Author

Thank you, and thanks for the presentation at Goatmire ❤️ (we didn't get to chat, but I still enjoyed it)

@Munksgaard Munksgaard deleted the nullable branch September 19, 2025 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: Add nilable or maybe function

3 participants