Feature #20404
closed`2pi`
Description
I propose a new Float literal: 2pi
.
p 2pi #=> 6.283185307179586 == 2 * Math::PI
I am not proposing 1pi
, 3pi
or 4pi
. I do only 2pi
. Because in most cases, all you need is 2pi
. Any other multiple of pi is rarely needed.
I've got the statistics. GitHub code search revealed that more than 80% of the occurrences of n * Math::PI
and Math::PI * n
had n = 2. [1]
n | n * Math::PI |
Math::PI * n |
sum | % |
---|---|---|---|---|
0 | 48 | 1 | 49 | 1.4% |
1 | 58 | 3 | 61 | 1.7% |
2 | 2300 | 534 | 2834 | 80.4% |
3 | 218 | 17 | 235 | 6.7% |
4 | 200 | 23 | 223 | 6.3% |
5 | 24 | 2 | 26 | 0.7% |
6 | 41 | 3 | 44 | 1.2% |
7 | 14 | 0 | 14 | 0.4% |
8 | 6 | 2 | 8 | 0.2% |
9 | 8 | 0 | 8 | 0.2% |
10 | 17 | 0 | 17 | 0.5% |
11 | 2 | 0 | 2 | 0.1% |
12 | 2 | 0 | 2 | 0.1% |
Here is the PIe chart
I know that a new constant name "Tau" is proposed (#4897, #17496). But notice: "2pi" and "Tau" have the same number of characters. Then, it is obvious that familiarity is better. In fact, 2 * Math::PI
is 4 times more than Math::PI * 2
, indicating that all programmers are copying "2pi" in their textbook.
The idea of 2pi came up regularly in chats among committers. The discussion quickly shifted to its generalization: should we treat 3e
as 3 * Math::E
, or even 42foo
as 42 * foo
? However, I noticed such a generalization is unnecessary because all we need is 2pi. Unneeded generalization is evil.
Here is a patch.
diff --git a/parse.y b/parse.y
index 55619273b8..93b16a16ac 100644
--- a/parse.y
+++ b/parse.y
@@ -10208,6 +10208,13 @@ parse_numeric(struct parser_params *p, int c)
return set_number_literal(p, tINTEGER, suffix, 10, 0);
}
}
+ else if (c == '2' && peek(p, 'p') && peek_n(p, 'i', 1)) {
+ tokadd(p, c);
+ tokadd(p, nextc(p));
+ tokadd(p, nextc(p));
+ tokfix(p);
+ return set_number_literal(p, tFLOAT, 0, 0, 0);
+ }
for (;;) {
switch (c) {
diff --git a/ruby_parser.c b/ruby_parser.c
index 6d85a72c5b..3a6e0b5704 100644
--- a/ruby_parser.c
+++ b/ruby_parser.c
@@ -936,6 +936,9 @@ VALUE
rb_node_float_literal_val(const NODE *n)
{
const rb_node_float_t *node = RNODE_FLOAT(n);
+ if (strcmp(node->val, "2pi") == 0) {
+ return DBL2NUM(2 * M_PI);
+ }
double d = strtod(node->val, 0);
if (node->minus) {
d = -d;
P I
Happy a r l fool
[1] I used these queries: /[^.]\b2 ?\* ?Math::PI/ language:Ruby
and /Math::PI *\* *2\b *[^.\/]/ language:Ruby
Updated by duerst (Martin Dürst) 9 months ago
I really like this proposal. But I think for most of the world, it was a few hours too early. A time around 2024-04-01 12:00:00 UTC may have been easier to understand for most of the world.
Updated by byroot (Jean Boussier) 9 months ago
Now that Ruby has been unicode aware for over a decade, it's probably better to use actual pi letter: 2π
Updated by shan (Shannon Skipper) 9 months ago
The Tau Manifesto (https://tauday.com/) was introduced by Michael Hartl, a Rubyist, and handily 𝜏 == 2π
so it might be worth also considering the tau letter: 𝜏
Updated by jzakiya (Jabari Zakiya) 9 months ago
This has been brought up before to add the constant tau
Updated by hsbt (Hiroshi SHIBATA) 9 months ago
- Related to Feature #17496: Add constant Math::TAU added
Updated by mame (Yusuke Endoh) 9 months ago
- Status changed from Open to Rejected
April Fools' Day is over. Closing.
This proposal is half joke, half serious. I can think of some reasons why we should introduce 2pi
.
There are some languages that provide not only pi
but also commonly used values.¶
@ko1 (Koichi Sasada) and @shyouhei (Shyouhei Urabe) told me that Gauche and C (POSIX) defines the following constants. It seem reasonable to provide frequently used values, even if they can be easily computed from other values.
- Gauche (Scheme):
pi
,2pi
,pi/2
,pi/4
,pi/180
,1/pi
, and180/pi
- C (POSIX):
pi
,pi/2
,pi/4
,1/pi
,2/pi
, and2/sqrt(pi)
(but not2pi
, why?)
https://practical-scheme.net/gauche/man/gauche-refe/Mathematical-constants.html
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/math.h.html
There is no good alternative constant name.¶
We cannot define Math::2PI
unfortunately. Math::PI2
and Math::PI_2
are in unnatural word order, and also ambiguous as pi^2 or pi/2. Math::TWO_PI
does not look so good.
I mentioned Tau in the original proposal, and seriously, I don't believe that Math::Tau
is the way to go at the present. As long as most textbooks use 2pi, programmers will have to replace it with 2pi
in their mind every time they see Math::Tau
, which is too inconvenient. We should consider this when most textbooks start using Tau. (If I had a time machine, I would try to convince the ancient Greeks to consider the ratio of circumference to radius instead of diameter.)
Math::PI
is often the only used one in Math module.
Because Ruby has Complex, it is often not necessary to use Math.sin
and cos
directly. When dealing with 2D graphics, we typically use only Complex multiplication and Math::PI
.
Math::PI
leads to a bit cryptic code.
For example, to find the coordinates of the vertices of a hexagon, one would write Complex.polar(1, 2 * Math::PI / 6 * n)
. However, many people may be bothered by the redundant multiplication and rewrite it as Complex.polar(1, Math::PI / 3 * n)
. Then the original intent of the hexagon disappears from the code. Since math code tends to be originally cryptic, I think it is better if the intent remains as straightforward as possible. With 2pi
, we could write Complex.polar(1, 2pi / 6 * n)
.
... Well, but I wonder if a new literal is impossible?
Updated by zverok (Victor Shepelev) 9 months ago
This proposal is half joke, half serious.
There are several interesting things to unpack here (though I don’t see any actionable proposals). When writing/reading in Ruby some math, there are several different irky things:
-
Math::
prefix (honestly, I never felt it totally justified, likesin
orcos
is obvious without any prefixes, why should we have it?..)—but at least can be mitigated byinclude Math
-
PI
in all-caps. I understand it corresponds to the constant rules of Ruby, yet in a complicated formula, it really catches your eye as ”something I’d like to read in a less screaming manner” (in some cases, I even introduced a local variableπ
to write some cumbersome formula) - The math intuition of
2<variable>
to mean2 * <variable>
, and in some formulae, perceived as an atomic part of it
(3) in some languages (can’t remember which ones from the top of my head, but I definitely saw it) is addressed by treating <number><identifier>
as <number> * <identifier>
. IDK, maybe this is the way?.. Currently, 2x
is a syntax error, so there should be no conflicts.
And also... Can it be possible to introduce Math::pi
and Math::e
(which, by the logic of naming, should be methods, yet maybe can be treated by parser or optimizer as constants)?..
Just thoughts.
Updated by duerst (Martin Dürst) 9 months ago
zverok (Victor Shepelev) wrote in #note-7:
When writing/reading in Ruby some math, there are several different irky things:
One thing that irks me about Math::sin and friends is that these are not available as methods (on Float and so on). It's annoying, and doesn't feel like Ruby, to have to write array.map { |x| Math.sin x }
instead of just array.map(&:sin)
. I understand why in some places, you want sin
in prefix position so that it looks like it does in a Mathematical formula, but in Ruby, there are often multiple ways to write things, so it shoulsd also be possible to write x.sin
.
Updated by nobu (Nobuyoshi Nakada) 9 months ago
zverok (Victor Shepelev) wrote in #note-7:
(3) in some languages (can’t remember which ones from the top of my head, but I definitely saw it) is addressed by treating
<number><identifier>
as<number> * <identifier>
. IDK, maybe this is the way?.. Currently,2x
is a syntax error, so there should be no conflicts.
Already we have 2i
, 2r
and 2ri
.