Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure the
response on the list to actually get it merged before writing an RFC.
My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operator
It introduces the pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).
The logic gets exposed via the ZEND_POW opcode and all the logic that went
into pow()
itself is copied into it. The exceptions are that an expression
such as [] ** 2 (squared empty array) will cause a fatal error because the
operands are incompatible, whereas pow([], 2) would give 0.
Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.
Btw, changes to vld aren't pushed yet.
Let me know!
--
Tjerk
On Fri, Nov 22, 2013 at 9:58 AM, Tjerk Meesters tjerk.meesters@gmail.comwrote:
It introduces the pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).
I would prefer the more math standard ^ (carat) but as that's a bitwise
operator (XOR) I know my dream will never be realized ;)
On Fri, Nov 22, 2013 at 11:58 AM, Tjerk Meesters
tjerk.meesters@gmail.comwrote:
Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure the
response on the list to actually get it merged before writing an RFC.My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operatorIt introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).The logic gets exposed via the ZEND_POW opcode and all the logic that went
intopow()
itself is copied into it. The exceptions are that an expression
such as [] ** 2 (squared empty array) will cause a fatal error because the
operands are incompatible, whereas pow([], 2) would give 0.Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.Btw, changes to vld aren't pushed yet.
Let me know!
--
Tjerk
I definitely like the idea of having pow as an operator. I've actually been
wanting to copy that from Python for a while. I'm all for it.
Definitely something that is missing and would be a welcome addition.
Where have you placed it in terms of operator precedence?
Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure the
response on the list to actually get it merged before writing an RFC.My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operatorIt introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).The logic gets exposed via the ZEND_POW opcode and all the logic that went
intopow()
itself is copied into it. The exceptions are that an expression
such as [] ** 2 (squared empty array) will cause a fatal error because the
operands are incompatible, whereas pow([], 2) would give 0.Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.Btw, changes to vld aren't pushed yet.
Let me know!
--
Tjerk
Hi,
Definitely something that is missing and would be a welcome addition.
Where have you placed it in terms of operator precedence?
It was equal to the shift operators and left associative, which was most
definitely wrong ;-)
I've now changed the operator precedence to one higher than ~ (bitwise not)
and right associative.
So:
-3 ** 2 == -9
~3 ** 2 == -10,
2 ** 3 ** 2 == 512
I should probably add this in a test case as well =D
On 22 November 2013 16:58, Tjerk Meesters tjerk.meesters@gmail.com
wrote:Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure
the
response on the list to actually get it merged before writing an RFC.My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operatorIt introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).The logic gets exposed via the ZEND_POW opcode and all the logic that
went
intopow()
itself is copied into it. The exceptions are that an
expression
such as [] ** 2 (squared empty array) will cause a fatal error because
the
operands are incompatible, whereas pow([], 2) would give 0.Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.Btw, changes to vld aren't pushed yet.
Let me know!
--
Tjerk
--
Tjerk
On Fri, Nov 22, 2013 at 1:03 PM, Tjerk Meesters tjerk.meesters@gmail.comwrote:
2 ** 3 ** 2 == 512
That looks very wrong. pow(pow(2,3),2) == 64
Exponent precedence should always be one higher than multiplication
precedence.
I definitely like the idea of having pow as an operator. I've actually been
wanting to copy that from Python for a while. I'm all for it.
That looks very wrong. pow(pow(2,3),2) == 64
Exponent precedence should always be one higher than multiplication
precedence.
Where Tjerk has placed it is exactly as python has it. I think right
assoc is the correct choice here. If you imagine 2^3^2 written down,
you would do 2^(3^2), not (2^3)^2
Python 2.7.3 (default, Jan 2 2013, 13:56:14)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
2 ** 3 ** 2
512
On Fri, Nov 22, 2013 at 12:56 PM, Sherif Ramadan theanomaly.is@gmail.comwrote:
On Fri, Nov 22, 2013 at 1:03 PM, Tjerk Meesters <tjerk.meesters@gmail.com
wrote:
2 ** 3 ** 2 == 512
That looks very wrong. pow(pow(2,3),2) == 64
Exponent precedence should always be one higher than multiplication
precedence.
I don't know if we consider Google to be the authority but they also do 512:
2 ^ 3 ^ 2 = 512
On Fri, Nov 22, 2013 at 12:56 PM, Sherif Ramadan theanomaly.is@gmail.comwrote:
On Fri, Nov 22, 2013 at 1:03 PM, Tjerk Meesters <tjerk.meesters@gmail.com
wrote:
2 ** 3 ** 2 == 512
That looks very wrong. pow(pow(2,3),2) == 64
Exponent precedence should always be one higher than multiplication
precedence.I don't know if we consider Google to be the authority but they also do
512:2 ^ 3 ^ 2 = 512
Well, it's correct in the sense that ** should be a right-associative
operator (and as such Python will provide the same result). The get the
same effect as pow(pow(2,3),2), one would have to do ((2**3)**2), in which
case the result woudl be 64.
I just didn't realize the patch made the operator right-associative until
now.
On Fri, Nov 22, 2013 at 12:56 PM, Sherif Ramadan theanomaly.is@gmail.comwrote:
On Fri, Nov 22, 2013 at 1:03 PM, Tjerk Meesters <tjerk.meesters@gmail.com
wrote:
2 ** 3 ** 2 == 512
That looks very wrong. pow(pow(2,3),2) == 64
Exponent precedence should always be one higher than multiplication
precedence.I don't know if we consider Google to be the authority but they also do 512:
2 ^ 3 ^ 2 = 512
SpeedCrunch also reports 512. It is my current desktop calculator of
choice (except for decimal/hex conversions) but it hasn't been updated
in a while, which is an indicator of a dead project.
IMO, things that "look very wrong" are better written with parenthesis.
Parenthesis = clarification.
2 ** (3 ** 2) is probably clearer to read than 2 ** 3 ** 2 even though
they have the same result.
--
Thomas Hruska
CubicleSoft President
I've got great, time saving software that you might find useful.
It introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).
This is great! I like Python's ** operator and having it in PHP would be
great too. It's a very versatile mathematical operator. With ** you get
three for the price of one: You can do powers ($x ** 2), you can do
square roots ($x ** (1/2)) and you can do reciprocals ($x ** -1), though
for that last one there was already 1 / $x.
I will definitely vote for this proposal if it works and you make an RFC.
I do have one concern, however. It looks like your current pull request
doesn't make gmp support it. Nikita's (nikic) proposal to add internal
operator overloading so that the gmp library could support it has been
merged in. So could you make it overloadable (if it isn't already), and
make sure gmp supports it?
Thanks!
Andrea Faulds
http://ajf.me/
Hi Andrea,
It introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).This is great! I like Python's ** operator and having it in PHP would be
great too. It's a very versatile mathematical operator. With ** you get
three for the price of one: You can do powers ($x ** 2), you can do square
roots ($x ** (1/2)) and you can do reciprocals ($x ** -1), though for that
last one there was already 1 / $x.I will definitely vote for this proposal if it works and you make an RFC.
I do have one concern, however. It looks like your current pull request
doesn't make gmp support it. Nikita's (nikic) proposal to add internal
operator overloading so that the gmp library could support it has been
merged in. So could you make it overloadable (if it isn't already), and
make sure gmp supports it?
Sure, gmp has gmp_pow(), so I don't think it will be a huge problem to
support this :)
Thanks!
Andrea Faulds
http://ajf.me/
--
Tjerk
+1
Does it work with https://wiki.php.net/rfc/operator_overloading_gmp ?
Am 22.11.2013 17:58, schrieb Tjerk Meesters:
Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure the
response on the list to actually get it merged before writing an RFC.My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operatorIt introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).The logic gets exposed via the ZEND_POW opcode and all the logic that went
intopow()
itself is copied into it. The exceptions are that an expression
such as [] ** 2 (squared empty array) will cause a fatal error because the
operands are incompatible, whereas pow([], 2) would give 0.Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.Btw, changes to vld aren't pushed yet.
Let me know!
On Fri, Nov 22, 2013 at 5:58 PM, Tjerk Meesters tjerk.meesters@gmail.comwrote:
Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure the
response on the list to actually get it merged before writing an RFC.My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operatorIt introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).The logic gets exposed via the ZEND_POW opcode and all the logic that went
intopow()
itself is copied into it. The exceptions are that an expression
such as [] ** 2 (squared empty array) will cause a fatal error because the
operands are incompatible, whereas pow([], 2) would give 0.Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.Btw, changes to vld aren't pushed yet.
Let me know!
I don't really see a need for this operator in PHP. From my experience
pow()
isn't some particularly commonly used function, so I don't think it
needs its own operator. (But I don't think that adding it would
particularly hurt either...)
Anyway, if this is added I would strongly recommend to make the operator
non-associative. I have no idea how Python came up with the idea to make **
right-associative, which violates basic programming language design rules
(all binary non-assignment operators are left-associative) and goes against
(at least my) common sense, but now that they made the choice it's likely
unwise to deviate from it by making it left-associative in PHP (see ternary
operator mess...) So I think making it non-associative makes for a safe
middle ground. This will cause 2 ** 3 ** 2 to throw an error and require
you to group it as either (2 ** 3) ** 2 or 2 ** (3 ** 3). Less ambiguity.
Nikita
On Fri, Nov 22, 2013 at 5:58 PM, Tjerk Meesters <tjerk.meesters@gmail.com
wrote:
Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure
the
response on the list to actually get it merged before writing an RFC.My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operatorIt introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).The logic gets exposed via the ZEND_POW opcode and all the logic that
went
intopow()
itself is copied into it. The exceptions are that an
expression
such as [] ** 2 (squared empty array) will cause a fatal error because
the
operands are incompatible, whereas pow([], 2) would give 0.Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.Btw, changes to vld aren't pushed yet.
Let me know!
I don't really see a need for this operator in PHP. From my experience
pow()
isn't some particularly commonly used function, so I don't think it
needs its own operator. (But I don't think that adding it would
particularly hurt either...)Anyway, if this is added I would strongly recommend to make the operator
non-associative. I have no idea how Python came up with the idea to make **
right-associative, which violates basic programming language design rules
(all binary non-assignment operators are left-associative) and goes against
(at least my) common sense, but now that they made the choice it's likely
unwise to deviate from it by making it left-associative in PHP (see ternary
operator mess...) So I think making it non-associative makes for a safe
middle ground. This will cause 2 ** 3 ** 2 to throw an error and require
you to group it as either (2 ** 3) ** 2 or 2 ** (3 ** 3). Less ambiguity.Nikita
I'm not entirely sure that making it non-associative is a great idea
either, but I have to agree that it does find some middle ground.
Right-associative exponent operator didn't seem right to me either.
Hi,
I'm not entirely sure that making it non-associative is a great idea
either, but I have to agree that it does find some middle ground.
Right-associative exponent operator didn't seem right to me either.
I think there is a good mathematical reason for right associative exponent.
It calls tetration or power tower. Please look at following sources for
more details:
http://math.stanford.edu/circle/notes08f/bignumbers.pdf
http://en.wikipedia.org/wiki/Tetration
http://mathworld.wolfram.com/PowerTower.html
Regards
Jakub
Hi,
I'm not entirely sure that making it non-associative is a great idea
either, but I have to agree that it does find some middle ground.
Right-associative exponent operator didn't seem right to me either.I think there is a good mathematical reason for right associative
exponent. It calls tetration or power tower. Please look at following
sources for more details:http://math.stanford.edu/circle/notes08f/bignumbers.pdf
http://en.wikipedia.org/wiki/Tetration
http://mathworld.wolfram.com/PowerTower.htmlRegards
Jakub
Right, that would be why I'm not entirely convinced.
Hi again,
On Sat, Nov 23, 2013 at 12:58 AM, Tjerk Meesters
tjerk.meesters@gmail.comwrote:
Hi,
To challenge myself I had tasked myself to introduce a new operator and
opcode to the language; now that I'm done with it, I wanted to measure the
response on the list to actually get it merged before writing an RFC.My work can be found here:
https://github.com/datibbaw/php-src/compare/pow-operatorIt introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).The logic gets exposed via the ZEND_POW opcode and all the logic that went
intopow()
itself is copied into it. The exceptions are that an expression
such as [] ** 2 (squared empty array) will cause a fatal error because the
operands are incompatible, whereas pow([], 2) would give 0.Why this operator? Basically because:
- it's shorter (the keyboard rejoices).
- it's faster (no ZEND_CALL).
- it's found in other languages too.
I've only implemented one of the test suites; there are quite a few for
just one function, but when needed I can add those others as well.Btw, changes to vld aren't pushed yet.
Let me know!
--
Tjerk
So far, there have been no violent objections against the proposal, so I
shall go ahead and effect the following:
- Investigate the GMP overloading option.
- Write an RFC
As for the associativity argument (assuming the precedence is now correct),
if not resolved before the voting begins, I would suggest to move that into
the vote itself, i.e.:
a) don't implement;
b) yes, with left associativity;
c) yes, with right associativity.
--
Tjerk
As for the associativity argument (assuming the precedence is now
correct), if not resolved before the voting begins, I would suggest to
move that into the vote itself, i.e.:
a) don't implement;
b) yes, with left associativity;
c) yes, with right associativity.
Shouldn't this include:
d) yes, with no associativity?
cheers,
Derick
Hi Derick,
As for the associativity argument (assuming the precedence is now
correct), if not resolved before the voting begins, I would suggest to
move that into the vote itself, i.e.:a) don't implement;
b) yes, with left associativity;
c) yes, with right associativity.Shouldn't this include:
d) yes, with no associativity?
Yes, it should. I'm proposing to split the voting into two sections:
- Whether it should be included in the first place
- And if so, how it should behave in terms of associativity (assuming
precedence is agreed upon).
cheers,
Derick
--
Tjerk
Hi,
It introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).
As a comment: In my view we try to keep the language understandable even
for people who aren't as deep into it as we are. There having power as
function serves two purposes. For one it is a normal function and can
easily identified as such with clear precedence etc. Secondly people can
stick it in their favorite search engine and can understand what it
means. Searching for ** however isn't as trivial.
Is the power operation really that common so we have to have it as an
operator and opcode? I don't know what the threshold is, but -/ might be
a nice unary (square) root operator ;-)
Looking at github search results
https://github.com/search?l=PHP&p=1&q=pow&source=cc&type=Code
I see quite a few search results but most of them duplication (pow.phpt
from our test suite comes very often) and in others I inspected it
didn't see to be critical code paths gaining much from performance in
(in my personal opinion) loosing readability.
Randomly picked example:
} elseif ($dec - pow(2,$i) >= 0) {
vs.
} elseif ($dec - (2 ** $i) >= 0) {
https://github.com/pkeane/exercises/blob/68b58fb11abfbe8301c202b94906a4ec7e041c10/binpal.php#L59
I consider the former to be better to parse with my brain.
And yes, I understand that there are cases where this will boost
performance by quite a bit, but then we'd rather make strlen()
an
opcode. ;-)
johannes
Hi Johannes,
On Sat, Nov 23, 2013 at 11:47 PM, Johannes Schlüter
johannes@schlueters.dewrote:
Hi,
It introduces the
pow()
function as an operator ** (double asterisk), as
can be found in languages such as Python (with perhaps the notable
difference that it's right associative there).As a comment: In my view we try to keep the language understandable even
for people who aren't as deep into it as we are. There having power as
function serves two purposes. For one it is a normal function and can
easily identified as such with clear precedence etc. Secondly people can
stick it in their favorite search engine and can understand what it
means. Searching for ** however isn't as trivial.
I agree with both comments; it's easy to forget the practicality of being
able to search on something you don't know, although I would hope that
people recognize it as an operator and go here:
http://php.net/manual/en/language.operators.arithmetic.php :)
Is the power operation really that common so we have to have it as an
operator and opcode? I don't know what the threshold is, but -/ might be
a nice unary (square) root operator ;-)
Actually, I was going to suggest creating a Unicode token √ for that ;-)
Looking at github search results
https://github.com/search?l=PHP&p=1&q=pow&source=cc&type=Code
I see quite a few search results but most of them duplication (pow.phpt
from our test suite comes very often) and in others I inspected it
didn't see to be critical code paths gaining much from performance in
(in my personal opinion) loosing readability.Randomly picked example:
} elseif ($dec - pow(2,$i) >= 0) {
vs.
} elseif ($dec - (2 ** $i) >= 0) {https://github.com/pkeane/exercises/blob/68b58fb11abfbe8301c202b94906a4ec7e041c10/binpal.php#L59
I consider the former to be better to parse with my brain.
Actually the latter could read:
} elseif ($dec - 2 ** $i >= 0) {
I can't judge on that, because my opinion will obviously be biased :)
And yes, I understand that there are cases where this will boost
performance by quite a bit, but then we'd rather makestrlen()
an
opcode. ;-)
Well, why don't we? :)
johannes
--
--
Tjerk