Skip to content

small syntax suggestion

11 messages · Barry Rowlingson, Philippe GROSJEAN, Davor Cubranic +3 more

#
Dear R development Team:  I really know very little, so you may ignore
this post.  I have found that my students often make the mistake of
mixing up comparisons and assignments with negative numbers:

  if (x<-3) do_something;

I parenthesize, but every once in a while, I forget and commit this
mistake, too.  so, I would suggest that R simply warn about an
ambiguity.  that is, it could suggest a space either between the < and
- , or after the <- .

  x< -3  ## means comparison already
  x<- 3  ## means assignment already
but warn when
  x<-3  ## ambiguity warning instead of assignment
  x<-(whatever)  ## ok

just a suggestion...

regards,

/iaw
----
Ivo Welch (ivo.welch at brown.edu, ivo.welch at gmail.com)
#
On Sun, Aug 22, 2010 at 4:33 PM, ivo welch <ivo.welch at gmail.com> wrote:
If you tell your students not to use '<-' for assignment, then they
can't make this mistake, because = for assignment has additional
restrictions on it:

 > x
 [1] 3
 > if(x=3)print("yay")
 Error: unexpected '=' in "if(x="

Anyway, if students didn't make mistakes how will they learn about debugging?

Barry
#
On 2010-08-23, at 6:15 AM, Barry Rowlingson wrote:

            
The students are trying to *compare* to a negative number, and trip on R's parsing of "<-". They could use '=' for assignment all they want (which I thought is being discouraged as a code style these days, BTW), and they'll still run into this problem.

Davor
#
On Mon, Aug 23, 2010 at 6:06 PM, Davor Cubranic <cubranic at stat.ubc.ca> wrote:

            
Oops yes, negative logic assumption from me.

 Okay, back to the question...

 Looks tricky, because if(x=2){...} fails because of syntax. There's
stuff in gram.y that makes x=1 a bit special, and only lets it occur
as a top-level expression. However x<-1 is allowed anywhere an
expression can be. Both expressions then call the same 'primitive'
function. At that point I'm not sure how the code could find out if
it's being called from a <- or an = assignment. And then whether its a
top-level expression or not. And this would need checking on every <-
call, which could be a problem...

 Barry
#
On 23-Aug-10 17:50:44, Barry Rowlingson wrote:
Indeed! R has a number of these tricky little syntatic traps,
perhaps especially where precedence or operators is concerned.
For example:

  1:10-1
  # [1] 0 1 2 3 4 5 6 7 8 9
  1-1:10
  # [1]  0 -1 -2 -3 -4 -5 -6 -7 -8 -9
  -1:10
  # [1] -1  0  1  2  3  4  5  6  7  8  9 10
  1+ -1:10
  # [1]  0  1  2  3  4  5  6  7  8  9 10 11
  1+ -(1:10)
  # [1]  0 -1 -2 -3 -4 -5 -6 -7 -8 -9

In due course people will learn (most of) the details of
precedence, but certainly at the beginning stage I would
strongly recommend putting brackets round *anything* which
is to be considered as an entity, just to avoid getting
things wrong. So, with the item in the original query:

  if (x<-3) do_something;

if they wrote it as

  if (x<(-3)) do_something;

there would be no problem (and no doubt about what went
with what). Of course in complicated expressions this could
induce an episode of ocular lispopia, but apart from that
it's safe! It's certainly something I tend to do even now,
simply for the sake of readability (aka "visual parsing").

Ted.

--------------------------------------------------------------------
E-Mail: (Ted Harding) <Ted.Harding at manchester.ac.uk>
Fax-to-email: +44 (0)870 094 0861
Date: 23-Aug-10                                       Time: 20:13:26
------------------------------ XFMail ------------------------------
#
I tell to my students that it is very important (not only for 
legibility) to place spaces between operands. They have to write such a 
code like this:

if (x < -3) do_something

That way, there is no ambiguity. Don't you think it's important to write 
clear code, including by using spaces where it makes it easier to 
read,... and less ambiguous, as you just realize?

Best,

Philippe Grosjean
On 23/08/10 19:06, Davor Cubranic wrote:
#
On August 23, 2010 01:27:24 pm Philippe Grosjean wrote:
I fully agree, and I'm sure nobody here would dispute your advice. But 
we all sometimes make typos, and the point here is that the grammar's 
ambiguity makes for hard-to-find bugs.

So, if I may focus us back on the OP's suggestion: "that R simply warn 
about an ambiguity" in 'if' statement's comparison involving '<-[0-9]'. 
It doesn't seem like an unreasonable suggestion. For comparison, GCC 
will do the same thing with C code when the '-Wparentheses' switch if 
assignment is used in a context where a truth value is expected. (E.g., 
'if (x = 3)'.)

It's been a very long time since I looked at Yacc and Lex source, but it 
looks like function 'xxif' in gram.y is the earliest place where we have 
a whole IF statement. AFAICT, this is evaluated in 'do_if' function of 
eval.c. There, the condition is evaluated via 'asLogicalNoNA'. Could 
'do_if' instead use a function similar to 'asLogicalNoNA' but which 
issues a warning if the condition is an assignment?

Davor
#
hi ted, philippe, and others---I agree with everything you write about
good coding practice.    none of us would be writing x<-3, even when
we want to assign 3.  we know better.   we would at least use a space,
if not a paren.  alas, my suggestion is not so much for you.  It is
trying to spare novices that are just beginning to use R some
unnecessary frustration.   I bet that most of us have made this
mistake at least once.

to the extent that it requires a token "<-[0-9]" to recognize this, it
could be an easy special case/warning/error.  to the extent that it
requires more, it is probably not worth the hassle.

[I am a great fan of syntax checking.  I am not a great fan of many
but the simplest recycling rules (from 1 to N) BY DEFAULT.  It's just
asking for trouble.]

regards,

/iaw
----
Ivo Welch (ivo.welch at brown.edu, ivo.welch at gmail.com)




On Mon, Aug 23, 2010 at 4:27 PM, Philippe Grosjean
<phgrosjean at sciviews.org> wrote:
#
On 24-Aug-10 14:42:11, Davor Cubranic wrote:
I'm a bit doubtful about the suggestion to "trap" this kind of
thing and issue warnings afterwards. It's not just in if() statements,
but anywhere where a logical value (as "x< -3") can validly be placed
and an assignment (as "x<-3") can validly be placed.

E.g.:

  if(x<-3) print("yes") else print("no")
  # [1] "yes"

because:

  as.logical(x<-3)
  # [1] TRUE
  as.logical(x<-0)
  # [1] FALSE

Or:

  x <- -5
  y <- c(5,4,3,2,1)
  y[x<-3]
  # [1] 3

  x <- -5
  y[x< -3]
  # [1] 5 4 3 2 1

It may be all very well to say that such examples look silly
(in what context might anyone mean them seriously?), but
remember that the context of this discussion is precisely
where someone has written something they didn't mean, so
"might mean them seriously" is not a criterion.

As illustrated above, "x<-3" is valid in all sorts of syntactic
contexts.

The upshot is that, if such warnings are to be implemented
in any context -- not just "if()" -- where one wanted to
protect the innocent from their own fingers, then they would
be triggered *every time* the expression "x<-3" (or the like)
occurred! Of course one would need to be able to turn this
warning off, but if (e.g. as a precaution in a class of
beginnners) it were turned on, then there would be a huge
number of false positives filling up the screen in almost
any normal program. Reassuring for beginners!

So, on those grounds, I doubt its wisdom (and would prefer
giving the advice to bracket things, as in "x<(-3)". It's
a potential syntactic trap, but it's only one of many which
can be avoided in similar ways, and I think it's better to
teach avoidance rather than warning after the event.

Ted.

--------------------------------------------------------------------
E-Mail: (Ted Harding) <Ted.Harding at manchester.ac.uk>
Fax-to-email: +44 (0)870 094 0861
Date: 24-Aug-10                                       Time: 16:18:27
------------------------------ XFMail ------------------------------
#
On Tue, Aug 24, 2010 at 4:18 PM, Ted Harding
<Ted.Harding at manchester.ac.uk> wrote:

            
Actually I think its better to teach _testing_ since it is hard to
teach all the things to avoid - they're not all listed in Patrick
Burns' R Inferno! (This particular problem *is* listed on page 49 of
said marvellous tome).

Barry
#
In the mean time you could have student run the following code each time (put it into .Rprofile or something) until they learn good coding practices:

testfunc <- function(expr, value, ok, visible) {
	tmp <- deparse(expr)
	if( grepl( '<- *[0-9.]+ *[])&|]', tmp ) ) {
		warning(' You used "<-" in the above expression,\nit was interpreted as an assignment\nif you wanted a comparison, use a space between the "<" and the "-"')
	}
	TRUE
}

addTaskCallback( testfunc )



you might want to change the warning to cat (and add \n), or extend the regular expression logic to other cases, or ...

But if nothing else getting the warning will reinforce that parens/spaces are a good idea if only to avoid the computer complaining.  The problem is I can think of some false positives that I have not worked out yet how to avoid.