Add a power operator #2026

Closed
wants to merge 2 commits into
from

Conversation

Projects
None yet
Contributor

charliesome commented Jan 11, 2012

It's annoying to have to write Math.pow all the time when you're doing mathsy stuff in CoffeeScript, so I've implemented a power operator as **.

It's right associative and has higher precedence than the multiplicative operators (*, /, %)

@michaelficarra michaelficarra commented on an outdated diff Jan 11, 2012

test/operators.coffee
@@ -269,3 +269,12 @@ test "Regression with implicit calls against an indented assignment", ->
1
eq a, 1
+
+test "power operator", ->
+ eq 27, 3 ** 3
+
+test "power operator has higher precedence than other maths operators", ->
+ eq 55, 1 + 3 ** 3 * 2
+
+test "power operator is right associative", ->
+ eq 1, 1 ** 2 ** 3
@michaelficarra

michaelficarra Jan 11, 2012

Collaborator

This test would pass even if ** wasn't right associative. (1 ** 2) ** 3 === 1 ** (2 ** 3).

Collaborator

michaelficarra commented Jan 11, 2012

The patch LGTM, and I'm all for accepting it, but policy has been not to allow extra maths operators. This proposal was most recently turned down in #1990 and originally in #79. Pinging @jashkenas to make sure his mind hasn't changed (though hoping it has).

Contributor

charliesome commented Jan 11, 2012

Oh crap, that commit message is wrong. Sorry!

Also, regarding what @jashkenas said when this was first proposed:

It would be just one more thing to learn, for an operation that really isn't used that much (in JavaScript). Closing...

People are using CoffeeScript for a lot of maths-related applications these days, and I think this trend will only continue as Javascript engines get faster. There's the recent CoffeeScript ray-tracer as a prime example.

It would be nice to have a bit of sugar for an operation that is used fairly often when it comes to mathematical code.

Owner

jashkenas commented Jan 11, 2012

So, here's the deal with Math operators ...

I'd be warm to a pull request that talks about adding an entire set of useful math operators in a cohesive way. I'm not sure what that set of operators would be, or what the symbols for them should be -- but it's worth someone taking a look at.

What I don't want to do is add a few operators here and there, piecemeal ... and end up in a situation where we have to be able to teach people a couple of scattershot operators that are different than JavaScript.

/cc @mitsuhiko because he wanted to add // and %% OPs.

Contributor

charliesome commented Jan 11, 2012

A // operator would definitely be useful. How would %% work?

see #1971 for more info

👍

I understand your concern with adding things piecemeal, but I can't imagine the situation in which having ** be anything other than exponentiation makes sense.

Collaborator

michaelficarra commented Jan 26, 2012

Agreed.

jrus commented Feb 5, 2012

Just stick: {pow, sin, cos, atan2, min, max} = Math or whatever at the top of your file, and you’re set. pow x, y isn’t really so bad. On the other hand, a variant % operator that wasn’t broken like JavaScript’s would be a big help. :-)

Contributor

davidchambers commented Feb 5, 2012

… or use mathmethods.js (shameless plug) to allow x.pow y.

Contributor

charliesome commented Feb 5, 2012

@jrus It's all well and good to say that aliasing Math.pow to just pow is good enough, but imagine if there were no maths operators at all:

x = add(1, mul(2, 3))

Virtually everything in CoffeeScript can be emulated with a little bit of extra code in plain old Javascript, but the point of CoffeeScript is that it provides a whole set nice little shortcuts.

I don't see how adding a ** operator would be harmful in any way. It's just another one of those little things that make CoffeeScript nice to use.

Contributor

davidchambers commented Feb 5, 2012

For the record, I'm +1 on this pull request.

I'm new to github (and by extension this repo) but I have been annoyed by the lack of a power operator in pretty much ever js or coffeescript project I have worked on. I don't see why this shouldn't be added to the language.

rlidwka commented Mar 19, 2012

👍

** is a standard notation for power operator in lots of languages (Perl, Python, etc.).

@michaelficarra michaelficarra added a commit to michaelficarra/coffee-of-my-dreams that referenced this pull request Mar 19, 2012

@michaelficarra michaelficarra add `**` exponentiation operator to additions
since jashkenas/coffeescript#2026 isn't looking good
58b0b73

michaelficarra referenced this pull request Apr 8, 2012

Closed

1.3.0 #2135

Owner

jashkenas commented Apr 10, 2012

I think I'm going to stick to my guns, and say that let's entertain a holistic patch that tries to come up with the complete set of math operators we should be embracing above and beyond what JS provides. Let's not merge them one-at-a-time.

jashkenas closed this Apr 10, 2012

Collaborator

michaelficarra commented Apr 10, 2012

Agreed. Re-opening this issue (to continue discussion) for exactly that reason.

Owner

jashkenas commented Apr 10, 2012

Fair enough.

Collaborator

michaelficarra commented Apr 10, 2012

Alright, community: it's up to you. Debate about which maths operators you need in CoffeeScript. With the right motivation, this'll actually make it in.

We NEED **. %% Wouldn't hurt either.

x3ro commented Apr 10, 2012

+1 for **. I don't know of any other operator that would be worth adding, though (imho).

gkz commented Apr 10, 2012

In your attached code I see that unary ops have a higher precedence than **. Thus -2 ** 2 would be 4, not -4 (as in math and many languages). [I should give credit to satyr for pointing this out to me to fix in LiveScript]

Contributor

charliesome commented Apr 11, 2012

@gkz

While making exponenation have a higher precedence than unary operators might be more mathematically correct, I could forsee it being quite unintuitive in situations like this:

-x ** y

That appears to be equivalent with Math.pow(-x, y) on first glance.

gkz commented Apr 11, 2012

@charliesome

Well, consider consistency with other languages:

Python: -2 ** 2 is -4
Ruby: -2 ** 2 is -4
Haskell: -2 ^ 2 is -4 (-2 ** 2 is -4.0)

Contributor

charliesome commented Apr 12, 2012

@gkz

Hmm, I've changed my mind - you've got a good point, consistency with other languages should be a priority

2 ** -2 = 0.25 also

I was thinking about asking for
|-3| === abs(-3) === 3
though I don't know that notation used in other programming languages.

Nothing else in http://en.wikipedia.org/wiki/List_of_mathematical_symbols I can see look tempting, save a few subset symbols that would be hard to type.

Contributor

charliesome commented May 19, 2012

I actually gave an abs operator with the same syntax some thought, but I wasn't sure how useful it'd be.

It's perfectly doable though

@tomByrer I think the average operator looks interesting

<- <4, 8, 9>
-> 7

osuushi commented May 19, 2012

|x| === abs(x) is pretty clearly irreconcilable with the bitwise-or operator, and doesn't have unambiguous meaning if nested. It also seems to me that traditionally infix operators are the most useful ones to give symbols to; in particular, I don't imagine that symbols for unary operators that traditionally act like parentheses (e.g. floor, abs, etc.) will add much convenience at all, especially since the number of easily-typed characters with "open" and "close" versions that aren't already spoken for is zero. I suppose you could do something like <!x!> === abs(x) , and <_x_> === floor(x) , but that has got to be some of the ugliest notation I've ever seen.

rlidwka commented May 19, 2012

@osuushi: floor(x) == ~~x, and it's a very popular notation in javascript... no need to invent another one :D

osuushi commented May 19, 2012

@rlidwka: first of all, floor(x) != ~~x when x < 0. ~~ performs "round toward zero", and is not a special operator, but simply double bitwise negation which exploits JavaScripts behavior of truncating floats when performing bitwise operations. You could achieve the same effect with 0|x. I would say that ~~ as a "popular" notation is an example of excessive cleverness akin to the old while(0 <= x) { "down to zero" hack. We have a perfectly good named floor function, and ~~ does not mean "truncate" in any other language, or resemble any conventional notation. I have used it myself, of course, when I actually need truncation, but I usually wrap it in a function, or give it a comment so that it's clear what I'm doing.

But all of that is moot since I was just using floor as an example of a "parenthesis-style operator" that shouldn't get its own new notation in CoffeeScript.

@osuushi: Why would anyone nest |absMe| without parenthesis? I guess the same way people could nest - + " also...? Perhaps it could cause trouble for those who want to play CoffeeScript golf with the fewest characters.
I do want to note that |absMe| |absAlso| |absThree| can be an issue if the parser doesn't outsmart the users who forget to hit the spacebar. :)

|absMe| is not a standard in programming languages AFAIK, but it is used in math notation, so I'm not sure why you suggested alternatives to straw-man them. I'm not dead-set on it appearing in CS, but wanted to ensure the discussion for it is opened as per jashkenas' request, "entertain a holistic patch that tries to come up with the complete set of math operators".

Collaborator

satyr commented May 19, 2012

the old while(0 <= x) { "down to zero" hack

You mean: while(x --> 0)

osuushi commented May 19, 2012

Whoops, yes I did mean while(x --> 0)

Edit:

And re @tomByrer: I thought I had a compelling case for where the syntax could be ambiguous between bitwise-or, absolute value, and paren-less function calling, but examining it some more, it doesn't look so bad after all.

Contributor

aseemk commented May 20, 2012

Considering #1971, it seems **, %% and // would be a great set of three really helpful operators.

@osuushi: It is good to consider all the hazards, & your post did remind me my white-space reservations. :)

I'd like to add a novel argument for adding ** for exponentiation, with or without achieving consensus on the larger operator issues. Every semester thousands of engineering and science college freshmen use the Python-based VPython environment (vpython.org) to model physical systems in the intro physics course where the adopted textbook is "Matter & Interactions" by Ruth Chabay and me (matterandinteractions.org). Most of these students have never written a computer program before, and it is possible to introduce them to serious computational modeling, an essential part of contemporary physics, only if the program syntax is as simple as possible and as close to standard algebra as possible. For these novice programmers, pow(base, exponent) is likely to be a major impediment, because expressions like 1/r**2 (in the gravitational force law) come up all the time. It's NOT a rare operation in this scientific computational environment.

I realize that JavaScript (and therefore CoffeeScript) have in the past been used mainly by expert programmers, not novices, nor has computation been a major target of JS/CS. For these reasons some of the discussions I've seen about ** in CoffeeScript have not taken into account the needs of novice programmers who are calculating physical quantities. For example, I've seen notes by programmers saying basically that they never have a need for pow(), so it's irrelevant to have **. For the uses of these technical students, it's highly relevant.

There is interest in using CoffeeScript as an alternative to VPython, including in precollege science courses where there are advantages to being able to run in a browser instead of begging IT to install Python. I'm developing GlowScript (glowscript.org), a place where you can write simple programs in JS or CS that exploit WebGL to generate real-time navigable 3D animations, with syntax so easy to use that even novice programmers can exploit WebGL. Already a colleague at Georgia Tech has proposed trying out GlowScript/CoffeeScript in a few trial sections next spring. It would make a significant difference if the pow() barrier were removed.

There is already some preprocessing of CS in the GlowScript environment to permit addition of vectors in the form A+B, essential for these purposes, and I could certainly add to the preprocessing ** as expanding to pow(), but it would be much better to have ** built-in. Again, my point is that I detected some sentiment against adding ** because it wasn't important to have an alternative to pow(). For the student environment, it is important.

Incidentally, I recently managed to update the GlowScript environment to give programmers the exact CS line number in the case of an error in the corresponding JS program, something that is crucial for novice programmers. (This works fully only with Chrome.)

Slight correction. The GlowScript preprocessing that permits adding and subtracting vectors using "+" and "-" rather than functions is performed on the JavaScript that is generated by CoffeeScript. There is no modification of the CoffeeScript source code before compiling to JavaScript (except for adding some ### comments with CS line numbers, which makes possible the display in error messages on Chrome of the original CS line number).

Contributor

epidemian commented Aug 28, 2012

@BruceSherwood, i totally agree on that ** would be a very good addition to the language. I think you explained why very clearly, so i won't repeat that. I just want to reiterate that math operators are very important when writing math (anyone who has had the sad experience of using java.BigInteger will acknowledge that), and some applications need exponentiation just as much as others need addition, mutiplication and their inverses. And lots of people are used to the exponentiation being standard math syntax (e.g. ) or an operator in most calculators and math-related languages.

I've seen notes by programmers saying basically that they never have a need for pow(), so it's irrelevant to have **. For the uses of these technical students, it's highly relevant.

That's a very important point IMO. I think it's easy to sometimes fall in the "i've never needed to use that, so it sure is unimportant" trap.

My idealistic side agrees with @jashkenas in that it would be nice to discuss the addition of a whole set of new math operators. Integer division '//' and non-broken modulus operators would be awesome to have too. But my pragmatic side is just shouting "add the ** already! It most probably won't change syntax (as ^ is already taken); we can see which other operators we might include later on".

Collaborator

michaelficarra commented Aug 28, 2012

+1 @epidemian. There's no question that the ** operator will be going in, let's just add it already. We can discuss which other operators will be added later.

Contributor

davidchambers commented Aug 28, 2012

Reaching consensus on a comprehensive suite of mathematical operators would be wonderful, but might take a long time. I agree with @epidemian and @michaelficarra that ** could safely be added before then, as no one disputes the appropriateness of the token.

** looks so obvious!

// and %% also get my vote. It is painful to have to write Math.floor all over the place. These operators would make the code leaner, easier to understand and less error prone.

BTW, we're writing most of our stuff in JS today so count my vote for half. But things like this (and list comprehensions) are real incentives to move to CS.

Owner

jashkenas commented Aug 28, 2012

There's no question that the ** operator will be going in, let's just add it already.

Sounds fine to me -- @michaelficarra, if you want to add it on master, or if you'd prefer just to put it in CoffeeScriptRedux for now...

Thanks much! I really appreciate your willingness to support the student needs.

I'm relatively new to CoffeeScript and ignorant about CoffeeScriptRedux, so I'll ask, should I be deploying the CoffeeScriptRedux compiler within GlowScript rather than the standard CoffeeScript compiler? Or is this something for the future?

Owner

jashkenas commented Aug 28, 2012

This is something for the (hopefully near) future.

I'd love a // and a %% as much as the next guy, but I think @jashkenas original concern wasn't really addressed, right? Adding ** now means it's set in stone (relatively) and if there was to be some kind of fix-all-the-math-operators effort then it'll either clash with or confine what can be done with everything else.

Maybe I'm naive, but I don't see how ** could possibly "clash or confine". Looking back over this discussion, ** seems to stand out in everyone's mind as a special case. In particular, it would be an alternative for Math.pow(x,y), which is manifestly not an operator, whereas I gather that some of the other things contemplated might be changes in existing operators, such as %, which obviously does require careful analysis.

@michaelficarra michaelficarra added a commit to michaelficarra/CoffeeScriptRedux that referenced this pull request Aug 29, 2012

@michaelficarra michaelficarra implement exponentiation operator; fixes jashkenas/coffeescript#2026 6bc355d

Thank you! This will make a big difference for computational use of CoffeeScript.

Collaborator

vendethiel commented Mar 25, 2013

Moving the discussion to #2887 because it's a superset as asked by @jashkenas

vendethiel closed this Mar 25, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment