Skip to content
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

Add a power operator #2026

Closed
wants to merge 2 commits into from
Closed

Conversation

haileys
Copy link
Contributor

@haileys haileys 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 (*, /, %)

eq 55, 1 + 3 ** 3 * 2

test "power operator is right associative", ->
eq 1, 1 ** 2 ** 3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@michaelficarra
Copy link
Collaborator

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).

@haileys
Copy link
Contributor Author

haileys 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.

@jashkenas
Copy link
Owner

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.

@paulmillr
Copy link

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

@haileys
Copy link
Contributor Author

haileys commented Jan 11, 2012

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

@paulmillr
Copy link

see #1971 for more info

@andrewrk
Copy link

👍

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.

@michaelficarra
Copy link
Collaborator

Agreed.

@jrus
Copy link

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. :-)

@davidchambers
Copy link
Contributor

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

@haileys
Copy link
Contributor Author

haileys 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.

@davidchambers
Copy link
Contributor

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

@sebzim4500
Copy link

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
Copy link

rlidwka commented Mar 19, 2012

👍

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

michaelficarra added a commit to michaelficarra/coffee-of-my-dreams that referenced this pull request Mar 19, 2012
@michaelficarra michaelficarra mentioned this pull request Apr 8, 2012
@jashkenas
Copy link
Owner

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 jashkenas closed this Apr 10, 2012
@michaelficarra
Copy link
Collaborator

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

@jashkenas
Copy link
Owner

Fair enough.

@michaelficarra
Copy link
Collaborator

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.

@sebzim4500
Copy link

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

@x3ro
Copy link

x3ro commented Apr 10, 2012

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

@gkz
Copy link

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]

@haileys
Copy link
Contributor Author

haileys 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
Copy link

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)

@tomByrer
Copy link

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.

@haileys
Copy link
Contributor Author

haileys 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

@aslilac
Copy link

aslilac commented May 19, 2012

@tomByrer I think the average operator looks interesting

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

@osuushi
Copy link

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
Copy link

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
Copy link

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.

@tomByrer
Copy link

@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".

@satyr
Copy link
Collaborator

satyr commented May 19, 2012

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

You mean: while(x --> 0)

@osuushi
Copy link

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.

@aseemk
Copy link
Contributor

aseemk commented May 20, 2012

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

@tomByrer
Copy link

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

@BruceSherwood
Copy link

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.)

@BruceSherwood
Copy link

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).

@epidemian
Copy link
Contributor

@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".

@michaelficarra
Copy link
Collaborator

+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.

@davidchambers
Copy link
Contributor

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.

@bjouhier
Copy link

** 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.

@jashkenas
Copy link
Owner

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...

@BruceSherwood
Copy link

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?

@jashkenas
Copy link
Owner

This is something for the (hopefully near) future.

@mrspeaker
Copy link

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.

@BruceSherwood
Copy link

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 added a commit to michaelficarra/CoffeeScriptRedux that referenced this pull request Aug 29, 2012
@michaelficarra
Copy link
Collaborator

@BruceSherwood
Copy link

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

@vendethiel
Copy link
Collaborator

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

@vendethiel vendethiel closed this Mar 25, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.