Parse integer division operator#6470
Conversation
Isn't it the other way around? |
|
Yes @straight-shoota I mean to overflow as "raise overflow". |
This reminds me of perl. I don't like it. |
|
I really don't like all these new operators being proposed. I really don't think we should introduce all these operators, they're just more things for a newcomer to learn to save a few characters typing ( |
|
I would expect that from all the operators added in this PR The division operator Adding The wrapper api, can be implemented on top of this. But not the other way around. So operators are more powerful and expressive. For wrapper to work well with overloads you will need The discussion left (hence this PR) is not about if the language needs to add this, but if the implementation is good enough. |
|
Back to this issue, I'm not sure what your concern is about I'm really against adding these operators because what we have now just isn't broken, so lets not fix it. Change for the sake of change is a bad thing. |
|
I just want data that this is actually a problem in the real world, and not a solution to a problem that we've invented in our heads. |
Let's use an example, if The Again, the fact that we are used to C like math operators does not make it the best option. |
|
@bcardiff I think issues like that are fairly rare, and |
|
That snippet is a workaround and harder to come up when learning the language. Having different operators is cleaner. Something new to learn today, yes. But is a more consistent set of operators. Try to explain that line when coding a method that manipulate numbers vs explain that
I could understand removing 3 from the PR, if and only if |
|
@bcardiff it's not just something new to learn today, it's something new that every newcomer from now until forever will have to learn. At the end of the day though, I'm more concerned about the overflow stuff adding a bazillion more operators than this PR only adding two. |
|
src/compiler/crystal/syntax/to_s.cr
Outdated
| when StringInterpolation | ||
| visit_interpolation(exp) { |s| Regex.append_source s, @str } | ||
| if (exp = node.value).is_a?(StringLiteral) && exp.value.empty? | ||
| # // is not allways an empty regex, sometimes is an operator |
j8r
left a comment
There was a problem hiding this comment.
Generally there is no point of using case statements for only one single condition vs if.
There is strictly no performance difference between the two. However using a case adds one more line to the code because the condition is splitted in two lines, which is IMO less clear than on one line with if
| private def it_lexes(string, type, *, slash_is_regex : Bool? = nil) | ||
| it "lexes #{string.inspect}" do | ||
| lexer = Lexer.new string | ||
| unless (v = slash_is_regex).nil? |
There was a problem hiding this comment.
Replace simply by if v = slash_is_regex
There was a problem hiding this comment.
This is not the same. slash_is_regex is Bool? so you need to test for .nil?
There was a problem hiding this comment.
Ok 👍 - the language evaluate if the expression is true and not nil, and we just want to know if it isn't nil.
There was a problem hiding this comment.
That would be abusing that the default value of slash_is_regex is false.
| char = next_char | ||
| if !@slash_is_regex && char == '=' | ||
| if (@wants_def_or_macro_name || !@slash_is_regex) && char == '/' | ||
| case next_char |
There was a problem hiding this comment.
Can be replaced by a smaller if statement
There was a problem hiding this comment.
Using the case is more about following the pattern of the rest of the lexer.
But I don't follow which is the proposed smaller if.
There was a problem hiding this comment.
This is fine - this just makes the lexer looks a bit more complex that it is, that's it :)
Here it would be
if next_char == '/'
next_char :"//="
else
@token.type = :"//"
endThere was a problem hiding this comment.
I thought you ment the if (@wants_def_or_macro_name ....
There are some if in the lexer, bust mostly case even single when-ed (?) case. I found them easier to read the lexer if all the structures are the same and not case by case based that we will end up having if your suggestions are applied.
At there is no real change the the actual code.
So case are kept. But thanks.
src/compiler/crystal/syntax/lexer.cr
Outdated
| when '/' | ||
| case next_char | ||
| when '/' | ||
| case next_char |
There was a problem hiding this comment.
With ifs it would be (start at line 648, replacing the 2 cases):
raise "&/ is not a valid operator. Did you mean &// ?" if next_char != '/'
if next_char == '='
next_char :"&//="
else
@token.type = :"&//"
endThere was a problem hiding this comment.
At a note, the previous code was:
case next_char
when '/'
case next_char
when '='
next_char :"&//="
else
@token.type = :"&//"
end
else
raise "&/ is not a valid operator. Did you mean &// ?"
end
src/compiler/crystal/syntax/lexer.cr
Outdated
| symbol "&*" | ||
| end | ||
| when '/' | ||
| case next_char |
There was a problem hiding this comment.
And here it would be:
if next_char == '/'
next_char_and_symbol "&//"
else
symbol "&/"
end| end | ||
| when '/' | ||
| next_char_and_symbol "/" | ||
| case next_char |
There was a problem hiding this comment.
It would be here
if next_char == '/'
next_char_and_symbol "//"
else
symbol "/"
end
ysbaddaden
left a comment
There was a problem hiding this comment.
Let's merge!
I regularly fumble on this in Ruby or put to_f in too many places because I can't trust / to rrturn a float. This is inconsistent and I'm happy we finally fix this in Crystal, with a minimal change for floor division (just add a /).
@RX14 points were already made/refuted in related issues.
|
I forgot we'd already merged all the |
|
I would prefer And if anyone else is thinking: how can integer division overflow? 🤔 |
def342d to
a85334f
Compare
|
I fixed the typo and rebased. @oprypin I will still raise the card of completeness regarding the |
|
By the way: https://stackoverflow.com/questions/30378591/overflow-division-operator-not-recognized I would recommend not having the &/ operator in Crystal, just like in Swift. It's an extra check for something that can rarely happen. |
|
completeness for completeness's sake seems like a very bad idea to me. It just expands the set of operators. I'd be much happier if the only operators we were adding were |
|
Since division by zero would still be raised in |
Refactor specs to assert operators all together
Allow // to be used as empty regex in some context only. Use %r() for empty regex when in to_s of AST.
the position of :"[]?" was off, new line added to compare them easily
DRY logic of allowed operators names for def and macro
a85334f to
5cb2886
Compare
In the path to implement #2968 first the operators needs to be allowed.
This PR allows
//andoperator&//sto be defined.The behavior will need to wait to the next release.
//will raise on overflowand&//won't. Similar to+vs&+.//will continue to mean empty regex when possible:foo // baris equivalent tofoo.//(bar)foo //is a syntax error (from now on)foo(//)is a call passing empty regexThe
ASTNode#to_swill use%r()as empty regex always since//will not always work.There are some refactors on specs and code for allowing operators to be used as methods and macro names introducing a state ivar
@wants_def_or_macro_namethat works similar to@slash_is_regexconfiguring the behavior of the lexer depending on the context.