Skip to content
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

Introduce cond/1 support in queries #706

Merged
merged 5 commits into from
Sep 15, 2023

Conversation

sasikumar87
Copy link
Contributor

Referring to #515, this PR introduces multi-clause select as a macro, which in-turn expand to nested Series.select/3 queries. This makes nested selects easy to write in a flat structure and improves readability.

Below are the list of assumptions made in this PR

  • Each clause will be prioritised by top-down by their order of definition
  • If none of the clauses match, it will be calculated to nil

Creating the PR for initial feedback, will add the docs if the approach is good.

Copy link
Contributor

@philss philss left a comment

Choose a reason for hiding this comment

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

For me it looks amazing! 😍

But let's wait to hear from José :)

defmacro select(do: clauses) do
conditions =
clauses
|> Enum.map(fn {:->, _, [[condition], on_true]} -> [condition, on_true] end)
Copy link
Member

Choose a reason for hiding this comment

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

You can do the reverse here, so we don't do it at runtime, and you can use tuples (semantically better):

Suggested change
|> Enum.map(fn {:->, _, [[condition], on_true]} -> [condition, on_true] end)
|> Enum.map(fn {:->, _, [[condition], on_true]} -> {condition, on_true} end)
|> Enum.reverse()


unquote(conditions)
|> Enum.reverse()
|> Enum.reduce(nil, fn [condition, truthy], acc ->
Copy link
Member

Choose a reason for hiding this comment

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

Something you could optimize is to check if condition == true. If that's the case, you know it will always be true and you can skip the whole select. Something like this:

  {true, truthy}, _acc -> Explorer.Shared.lazy_series!(truthy)
  {condition, truthy}, acc -> ...

Copy link
Member

@josevalim josevalim left a comment

Choose a reason for hiding this comment

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

This is great @sasikumar87!

The only question I have is if we want to call it cond do instead of select. I would prefer to keep it closer to Elixir, so cond is my vote.

In that case, instead of defining a defmacro select(...) do, you should match on defp traverse({:cond, _meta, clauses}) do. Everything else should remain the same. The documentation would go in the module docs.


PS: Now that I think about it, we could also support case ... do but an initial version would require all patterns to be literals (i.e. integers or strings). But that's for another PR. :)

@sasikumar87
Copy link
Contributor Author

The only question I have is if we want to call it cond do instead of select. I would prefer to keep it closer to Elixir, so cond is my vote.

@josevalim I read the following in #515,

We chose select do instead of cond because, opposite to cond which only evaluates the clauses that matches, queries always evaluates all clauses in order to build the expression.

Do you think this argument still has merit to use select? Personally I would prefer cond too.

@josevalim
Copy link
Member

I see @josevalim from the past disagrees with @josevalim from the future. Let me think about it, haha.

@josevalim
Copy link
Member

@sasikumar87 let's go with cond. Thank you!

@sasikumar87 sasikumar87 changed the title Introduce multi-clause select Introduce cond/1 support in queries Sep 15, 2023
@sasikumar87 sasikumar87 marked this pull request as ready for review September 15, 2023 16:14
lib/explorer/query.ex Outdated Show resolved Hide resolved
@josevalim josevalim merged commit 5329031 into elixir-explorer:main Sep 15, 2023
@josevalim
Copy link
Member

💚 💙 💜 💛 ❤️

@sasikumar87 sasikumar87 deleted the multi-clause-select branch September 15, 2023 16:19
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.

3 participants