-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
logical operators for option type #8369
Conversation
This is a direct competitive to the |
lib/pure/options.nim
Outdated
@@ -312,3 +340,77 @@ when isMainModule: | |||
|
|||
let noperson = none(Person) | |||
check($noperson == "None[Person]") | |||
|
|||
test "logical operatior()": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cosmetic typo: operatior -> operator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true. But it's a test case. I don't think it matters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why I said "cosmetic" :) But I personally fix those too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a huge deal but it certainly matters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code style: I prefer if we use the least powerful construct (inline proc) instead of template if we can.
or
and and
are better than optOr
and optAnd
, but due to potential confusion with Option[bool], I would like a different name for option combinators. Rust uses and_then
and or_else
for example.
Tagging @PMunch
@@ -139,6 +139,34 @@ proc get*[T](self: Option[T], otherwise: T): T = | |||
else: | |||
otherwise | |||
|
|||
template `or`*[T](x: Option[T]; y: T): T = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If an inline proc is enough, I much prefer them than templates
lib/pure/options.nim
Outdated
get(x,y) | ||
|
||
template `or`*[T](x, y: Option[T]): Option[T] = | ||
let xx = x |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline proc wouldn't need this for example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would an inline proc guarantee that y is not run if x has a value though? AFAIK it still runs procedures to generate an Option to pass in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mratsim an linline proc evaluates all arguments before entering the function body. I explicity want to avoid that. The logical or operator also works like that. That is why you can write conditions like this: if a != nil and a.member > 123
. If or
would evaluate all arguments first, this would crash when a
is nil
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that's a good reason :). I would add a comment using templates to allow evaluation shortcuting
so that people don't change it to proc later then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mratsim I have a testcase that covers that.
Nothing at the moment. When this was created there was a difference, but I copied this solution into mine when I rewrote it. |
I'm okay with the |
I think that changes to "and/or" require discussion as RFC. In particular, I propose the following, more generic approach that I used to deal with empty arrays too: template `|||`(a,b:T):T = if isTrue(a): a; else: b
template `&&&`(a,b:T):T = if isTrue(a): b; else: a
template `&&&`(a:T,b:U):U = if isTrue(a): b; else: Null(b)
template iif(a:T; b,c:U):U = if isTrue(a): b; else: c where isTrue and Null are overloaded for each type (bool, Option[T], seq[T]...) |
@Bulat-Ziganshin I don't like the idea to introduce new operators and even a new kind of My original idea to overload these operators for options comes from elisp (emacs lisp). elisp has a builtin called and, |
@PMunch there are still lots of differences. Just look closely at the tests that I asked you to adopt. You changed a lot of it in your version and added much more verbosity. |
Lots of differences is an over-statement. I copied your |
@dom96 I removed the |
## With the ``or`` operator you can chain together several expressions | ||
## of type ``Option[T]`` and the whole expression will evaluate the | ||
## operand from left to right until an the operand that is not | ||
## none. This operand will be returned. If all operands are none, then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are not British, we use one space after a dot. (nitpick, I know)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is fine, the docs could be better.
## of such an expression does not need to be of type ``Option[T]``, it | ||
## can be just of type ``T`` for the last fallback. If that is the | ||
## case the whole expression will be of type ``T``, because it could | ||
## not evaluate to none anymore. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your docs, while appreciated, are far too verbose.
Create a short, and to the point heading:
## Retrieving values from an option
## ========================
##
## Values can be retrieved in many ways, primarily using ``get`` or the ``or`` operator.
##
## Using ``get``
## --------------
##
## This is the simplest approach:
##
## ..code-block:: ....
##
##
## But it means there is an exception raised when the option isn't a ``some``.
##
## Using ``or``
## -------------
##
## ....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short sentences, and short specific examples are always better than a huge paragraph and a huge example.
Hrm, I still think this conflates the wrapped type's |
@Varriount 'optOr' isn't even close as readable - look at examples. Overall, I proposed RFC-style discussion what 'or' should mean. I think that we should just make a general decision and then go together in the chosen way. |
Sorry, rejected. If in doubt, leave it out. |
No description provided.