Re: [Rd] Extending suggestion for stopifnot

2013-08-21 Thread Deepayan Sarkar
On Wed, Aug 21, 2013 at 3:30 AM, ivo welch ivo.we...@gmail.com wrote:
 thx, deepayan:  how is stopifnot better than
 if (!all(...)) stop()

But I am not claiming that it is!

If you think it is not useful, then don't use stopifnot(), use stop()
instead, and tell your students to do so as well.

 given that we have stopifnot() and I have seen it used often, I think
 my two suggestions would make it better.

Maybe it will (in some specific use cases). But looking at your
suggestion purely from the point of view of is it worth incorporating
into base R?, I don't see enough justification. The disadvantage is
that it will complicate a simple function. The supposed advantage is
only an advantage when you use stopifnot() in a way that was not
intended, whereas there is already an alternative that does almost
exactly what you want (at least you haven't yet explained why you are
not happy with stop()). Interpolated strings may be cool, but I don't
see a big readability advantage of

if (!is.matrix(m)) stop(m is not a matrix, but a {{class(m)}})

over

if (!is.matrix(m)) stop(m is not a matrix, but a , class(m))

Note that I'm not saying that stop() is perfect or anything, or that
there is no need for alternatives. Just that I'm not convinced that
the base R changes you want are justified.

-Deepayan

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-21 Thread Geoff Jentry

first, I think it would be more useful if it had an optional character
string, so users could write
 stopifnot( is.matrix(m), m is not a matrix )


stop() allows for arbitrary strings 

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


[Rd] Extending suggestion for stopifnot

2013-08-20 Thread ivo welch
I am using a variant of stopifnot a lot.  can I suggest that base R
extends its functionality?  I know how to do this for myself.  this is
a suggestion for beginners and students.  I don't think it would break
anything.

first, I think it would be more useful if it had an optional character
string, so users could write

  stopifnot( is.matrix(m), m is not a matrix )

this would mean that stopifnot would have to detect whether the last
argument is a string.  (I think stopifnot should have had only one
condition, and one should have used all() to test multiple conditions,
but this is a bridge that was already crossed.)  upon failure,
stopifnot should print the character string.  that's it.


A second enhancement would be a smart string, which knows that
everything inside {{...}} should be evaluated.

  stopifnot( is.matrix(m), m is not a matrix, but a {{class(m)}} )


my own programming variant looks even nicer,

   is.matrix(m) %or% m is not a matrix but a {{class(m)}}

but requesting base R to add the %and% and %or% (or, better yet, 'and'
and 'or') operators by default would be pushing my luck.

/iaw



Ivo Welch (ivo.we...@gmail.com)

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread Deepayan Sarkar
On Wed, Aug 21, 2013 at 12:11 AM, ivo welch ivo.we...@anderson.ucla.edu wrote:

 I am using a variant of stopifnot a lot.  can I suggest that base R
 extends its functionality?  I know how to do this for myself.  this is
 a suggestion for beginners and students.  I don't think it would break
 anything.

 first, I think it would be more useful if it had an optional character
 string, so users could write

   stopifnot( is.matrix(m), m is not a matrix )

How is this better/nicer/more preferable than, say,

if (!is.matrix(m)) stop(m is not a matrix)

?

I think stopifnot() is mostly meant for regression tests and sanity
checks, and should not be used instead of stop() if you want nicely
formatted error messages.

-Deepayan


 this would mean that stopifnot would have to detect whether the last
 argument is a string.  (I think stopifnot should have had only one
 condition, and one should have used all() to test multiple conditions,
 but this is a bridge that was already crossed.)  upon failure,
 stopifnot should print the character string.  that's it.


 A second enhancement would be a smart string, which knows that
 everything inside {{...}} should be evaluated.

   stopifnot( is.matrix(m), m is not a matrix, but a {{class(m)}} )


 my own programming variant looks even nicer,

is.matrix(m) %or% m is not a matrix but a {{class(m)}}

 but requesting base R to add the %and% and %or% (or, better yet, 'and'
 and 'or') operators by default would be pushing my luck.

 /iaw


 
 Ivo Welch (ivo.we...@gmail.com)

 __
 R-devel@r-project.org mailing list
 https://stat.ethz.ch/mailman/listinfo/r-devel

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread R. Michael Weylandt michael.weyla...@gmail.com


On Aug 20, 2013, at 14:41, ivo welch ivo.we...@anderson.ucla.edu wrote:

 A second enhancement would be a smart string, which knows that
 everything inside {{...}} should be evaluated. 

I think one the HTML templating libraries (whisker or mustache or some such) 
provides something not unlike this. Perhaps take a look. 

 
  stopifnot( is.matrix(m), m is not a matrix, but a {{class(m)}} )
 
 
 my own programming variant looks even nicer,
 
   is.matrix(m) %or% m is not a matrix but a {{class(m)}}
 
 but requesting base R to add the %and% and %or% (or, better yet, 'and'
 and 'or') operators by default would be pushing my luck.

Does %or% throw an error or is this wrapped in something else?

The former seems rather perl-ish, but the latter might suggest you look into 
the || and  operators if you only know their single counterparts. 

Michael

 
 /iaw
 
 
 
 Ivo Welch (ivo.we...@gmail.com)
 
 __
 R-devel@r-project.org mailing list
 https://stat.ethz.ch/mailman/listinfo/r-devel

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread Peter Langfelder
On Tue, Aug 20, 2013 at 11:41 AM, ivo welch ivo.we...@anderson.ucla.edu wrote:
 I am using a variant of stopifnot a lot.  can I suggest that base R
 extends its functionality?  I know how to do this for myself.  this is
 a suggestion for beginners and students.  I don't think it would break
 anything.

 first, I think it would be more useful if it had an optional character
 string, so users could write

   stopifnot( is.matrix(m), m is not a matrix )

 this would mean that stopifnot would have to detect whether the last
 argument is a string.  (I think stopifnot should have had only one
 condition, and one should have used all() to test multiple conditions,
 but this is a bridge that was already crossed.)  upon failure,
 stopifnot should print the character string.  that's it.


 A second enhancement would be a smart string, which knows that
 everything inside {{...}} should be evaluated.

   stopifnot( is.matrix(m), m is not a matrix, but a {{class(m)}} )

I think using a function (in this case paste) is cleaner:

paste(m is not a matrix, but a, class(m))

It avoids adding a new convention (evaluate everything between {{
}}) and has additional arguments.



 my own programming variant looks even nicer,

is.matrix(m) %or% m is not a matrix but a {{class(m)}}

In R you can write it as

is.matrix(m) || stop(m is not a matrix but a , class(m))

Examples:

m = 1
 is.matrix(m) || stop(m is not a matrix but a , class(m))
Error: m is not a matrix but a numeric

 m = matrix(0,2,2)
 is.matrix(m) || stop(m is not a matrix but a , class(m))
[1] TRUE

But the construct

if (!is.matrix(m)) stop(m is not a matrix but a , class(m))

is more readable for people not used to Pearl.

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread Brian Rowe
If all you care about is emulating static type checking, then you can also 
accomplish the same thing with lambda.r using type constraints on function 
definitions.

e.g.
 f(m) %::% matrix : matrix
 f(m) %as% { m }

 f(as.data.frame(matrix(rnorm(12),nrow=3)))
Error in UseFunction(f, ...) : No valid function for 'f(data.frame)'

 f(1)
Error in UseFunction(f, ...) : No valid function for 'f(1)'

 f
function
[[1]]
f(m) %::% matrix:matrix
f(m) %as% …



On Aug 20, 2013, at 4:36 PM, Peter Langfelder peter.langfel...@gmail.com 
wrote:

 On Tue, Aug 20, 2013 at 11:41 AM, ivo welch ivo.we...@anderson.ucla.edu 
 wrote:
 I am using a variant of stopifnot a lot.  can I suggest that base R
 extends its functionality?  I know how to do this for myself.  this is
 a suggestion for beginners and students.  I don't think it would break
 anything.
 
 first, I think it would be more useful if it had an optional character
 string, so users could write
 
  stopifnot( is.matrix(m), m is not a matrix )
 
 this would mean that stopifnot would have to detect whether the last
 argument is a string.  (I think stopifnot should have had only one
 condition, and one should have used all() to test multiple conditions,
 but this is a bridge that was already crossed.)  upon failure,
 stopifnot should print the character string.  that's it.
 
 
 A second enhancement would be a smart string, which knows that
 everything inside {{...}} should be evaluated.
 
  stopifnot( is.matrix(m), m is not a matrix, but a {{class(m)}} )
 
 I think using a function (in this case paste) is cleaner:
 
 paste(m is not a matrix, but a, class(m))
 
 It avoids adding a new convention (evaluate everything between {{
 }}) and has additional arguments.
 
 
 
 my own programming variant looks even nicer,
 
   is.matrix(m) %or% m is not a matrix but a {{class(m)}}
 
 In R you can write it as
 
 is.matrix(m) || stop(m is not a matrix but a , class(m))
 
 Examples:
 
 m = 1
 is.matrix(m) || stop(m is not a matrix but a , class(m))
 Error: m is not a matrix but a numeric
 
 m = matrix(0,2,2)
 is.matrix(m) || stop(m is not a matrix but a , class(m))
 [1] TRUE
 
 But the construct
 
 if (!is.matrix(m)) stop(m is not a matrix but a , class(m))
 
 is more readable for people not used to Pearl.
 
 __
 R-devel@r-project.org mailing list
 https://stat.ethz.ch/mailman/listinfo/r-devel

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread ivo welch
thx, deepayan:  how is stopifnot better than
if (!all(...)) stop()
given that we have stopifnot() and I have seen it used often, I think
my two suggestions would make it better.

thx, michael:  the %and% and %or% constructs are indeed relics of my
perl background.  my own definition is

`%and%` - function(e1, e2) {  if (e1) { if (is.character(e2))
abort.estring(e2) else eval(e2) } }

it's syntactic sugar.  my abort.estring() function prints the
character as n estring() [extended string, see below] and exits.  it
can probably be written a lot better.  remember, I am not an expert.

thx, peter: the estring has the advantage of having it all in one
string, which allows me to say, e.g.,
   (x) %or% x is not true but {{x}}
the comma here does not work.  it basically becomes an interpolated
string, just like the construct x is $x in perl.

thx, bill: ensureThat() is not a base R function.  uggh---I think you
are right on precedence.  I always use parens around my conditions.
old C habit from decades ago, so I never ran into this problem.  if()
is good enough.  my main suggestion was adding an optional message at
the end of stopifnot(), and possibly extended (interpolated) strings.

thx, brian:  I think of lambda.r as being more heavyweight and
requiring a modestly steeper learning curve.  if it was standard in
base R, I would definitely switch to it.  I think we want a system
that my students are taught to use from day 1.


in sum, I agree that one accomplish the functionality in base R.  my
initial suggestion was very simple and small: (1) adding an optional
character string at the end of an existing function, stopifnot().  (2)
I think estrings (that behave like characters but are interpolated
before printout) are useful in the same way perl interpolated strings
are useful.  this would be a bigger change.  some people would like
it.  others don't see the advantage.  I think the benefits would
outweigh the costs.  (3) I just mentioned %and% and %or% as an
aside.  it this is definitely a bigger change, where we can all
agree to disagree whether we like this in code or not.  just ignore
#3.

best,

/iaw


estring - function(e2, N.UP =2) {

  rx - (?=\\{\\{).*?(?=\\}\\})

  match - gregexpr(rx, e2, perl=TRUE)

  syntax - regmatches(e2, match)[[1]]
  syntax - lapply(syntax, parse, file=, n=NULL)
##  syntax-lapply(syntax, eval.parent, n=N.UP)
  r - tryCatch( syntax-lapply(syntax, eval.parent, n=N.UP), error=
function(e) NULL )
  if (is.null(r)) r - tryCatch( syntax-lapply(syntax, eval.parent,
n=N.UP+1), error= function(e) NULL )
  if (is.null(r)) r - tryCatch( syntax-lapply(syntax, eval.parent,
n=N.UP-1), error= function(e) NULL )
  if (is.null(r)) r - tryCatch( syntax-lapply(syntax, eval.parent,
n=N.UP-2), error= function(e) unknown variable )
  ## the return is now ignored.  if we cannot recognize the syntax, we
just leave it.

  s- unlist(sys.calls())
  if (length(s)1) cat(Function ',
as.character(s[[length(s)-N.UP+1]]), ':\n\t, sep=) else
cat([GlobalEnv]:\t)
  regmatches(e2, match) - %s

  do.call(sprintf, c(fmt=e2, '...'=syntax) )
}

Ivo Welch (ivo.we...@gmail.com)
http://www.ivo-welch.info/
J. Fred Weston Professor of Finance
Anderson School at UCLA, C519
Director, UCLA Anderson Fink Center for Finance and Investments
Free Finance Textbook, http://book.ivo-welch.info/
Editor, Critical Finance Review, http://www.critical-finance-review.org/



On Tue, Aug 20, 2013 at 2:14 PM, Brian Rowe r...@muxspace.com wrote:
 If all you care about is emulating static type checking, then you can also 
 accomplish the same thing with lambda.r using type constraints on function 
 definitions.

 e.g.
 f(m) %::% matrix : matrix
 f(m) %as% { m }

 f(as.data.frame(matrix(rnorm(12),nrow=3)))
 Error in UseFunction(f, ...) : No valid function for 'f(data.frame)'

 f(1)
 Error in UseFunction(f, ...) : No valid function for 'f(1)'

 f
 function
 [[1]]
 f(m) %::% matrix:matrix
 f(m) %as% …



 On Aug 20, 2013, at 4:36 PM, Peter Langfelder peter.langfel...@gmail.com 
 wrote:

 On Tue, Aug 20, 2013 at 11:41 AM, ivo welch ivo.we...@anderson.ucla.edu 
 wrote:
 I am using a variant of stopifnot a lot.  can I suggest that base R
 extends its functionality?  I know how to do this for myself.  this is
 a suggestion for beginners and students.  I don't think it would break
 anything.

 first, I think it would be more useful if it had an optional character
 string, so users could write

  stopifnot( is.matrix(m), m is not a matrix )

 this would mean that stopifnot would have to detect whether the last
 argument is a string.  (I think stopifnot should have had only one
 condition, and one should have used all() to test multiple conditions,
 but this is a bridge that was already crossed.)  upon failure,
 stopifnot should print the character string.  that's it.


 A second enhancement would be a smart string, which knows that
 everything inside {{...}} should be evaluated.

  stopifnot( is.matrix(m), m is not a matrix, but a {{class(m)}} )

 

Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread Gabor Grothendieck
On Tue, Aug 20, 2013 at 6:00 PM, ivo welch ivo.we...@gmail.com wrote:
 character string at the end of an existing function, stopifnot().  (2)
 I think estrings (that behave like characters but are interpolated
 before printout) are useful in the same way perl interpolated strings
 are useful.

The gsubfn package has string interpolation somewhat like perl.
Preface a function call with fn$ and then back ticks and $ are
interpolated.

library(gsubfn)
fn$identity(pi is $pi)

library(sqldf)
fn$sqldf(select * from BOD where Time  $pi)

fn$stop(class is `class(pi)`)

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread ivo welch
functionality is nice.  syntax is weird.  I think I would have
preferred an interpolate function call.
stop( i(class is `class(pi)` and $pi) )
three typing letters, too, and more logical.  most importantly, I wish
we had some form of this in base R from the outset--whatever it is--so
that my students get used to using the standard from the outset.

[the {{...}} had the advantage of being unlikely to break anything.
perl has it nicely done---  is interpolated, ' is not.  but this is a
bridge that we crossed long ago in R.  it would break too much.]

best,

/iaw

Ivo Welch (ivo.we...@gmail.com)
http://www.ivo-welch.info/
J. Fred Weston Professor of Finance
Anderson School at UCLA, C519
Director, UCLA Anderson Fink Center for Finance and Investments
Free Finance Textbook, http://book.ivo-welch.info/
Editor, Critical Finance Review, http://www.critical-finance-review.org/



On Tue, Aug 20, 2013 at 3:28 PM, Gabor Grothendieck
ggrothendi...@gmail.com wrote:
 On Tue, Aug 20, 2013 at 6:00 PM, ivo welch ivo.we...@gmail.com wrote:
 character string at the end of an existing function, stopifnot().  (2)
 I think estrings (that behave like characters but are interpolated
 before printout) are useful in the same way perl interpolated strings
 are useful.

 The gsubfn package has string interpolation somewhat like perl.
 Preface a function call with fn$ and then back ticks and $ are
 interpolated.

 library(gsubfn)
 fn$identity(pi is $pi)

 library(sqldf)
 fn$sqldf(select * from BOD where Time  $pi)

 fn$stop(class is `class(pi)`)

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread Hadley Wickham
 first, I think it would be more useful if it had an optional character
 string, so users could write

   stopifnot( is.matrix(m), m is not a matrix )


Another option is to just generate better error messages automatically, e.g.:

 library(assertthat)
 x - 1:10
 assert_that(is.matrix(x))
Error: x is not a matrix

Hadley

-- 
Chief Scientist, RStudio
http://had.co.nz/

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Extending suggestion for stopifnot

2013-08-20 Thread Martin Morgan

On 08/20/2013 11:41 AM, ivo welch wrote:

A second enhancement would be a smart string, which knows that
everything inside {{...}} should be evaluated.

   stopifnot( is.matrix(m), m is not a matrix, but a {{class(m)}} )


a variant with more traditional syntax might be

  if (!is.matrix(m))
  stopf(m is not a matrix, but a '%s', class(m))
or

  stopifnotf(is.matrix(m), m is not a matrix, but a '%s', class(m))

where stopf is analogous to sprintf but signalling the corresponding condition 
(perhaps taking the opportunity to strwrap to getOption(width)). This would 
work well with gettextf to allow for translation. An imperfect implementation 
(call. is incorrect, for example) is


.msg -
function(fmt, ..., domain=NULL, width=getOption(width))
## Use this helper to format all error / warning / message text
{
txt - strwrap(gettextf(fmt, ..., domain=domain), width=width,
   exdent=2)
paste(txt, collapse=\n)
}

stopf -
function(..., call.=FALSE)
{
stop(.msg(...), call.=call.)
}

stopifnotf -
function(test, fmt, ...)
{
if (!test)
stopf(fmt, ...)
}

One might also wish to expose the condition class system, along the lines of

.textf - ## a variant of .makeMessage
function(fmt, ..., width = getOption(width), domain = NULL,
 appendLF = FALSE)
{
txt - gettextf(fmt, ..., domain = domain)
msg - paste(strwrap(txt, width = width, indent = 2, exdent = 2),
 collapse=\n)
if (appendLF)
paste0(msg, \n)
else msg
}

.condition -
function(fmt, ..., class, call = NULL)
{
msg - .textf(fmt, ...)
if (is.null(call))
msg - paste0(\n, msg)
class - c(class, condition)
structure(list(message=msg, call = call), class=class)
}

stopf -
function(fmt, ..., class. = simpleError, call. = TRUE, domain = NULL)
{
call. - if (is.logical(call.)  1L == length(call.)  call.)
sys.call(-1)
else NULL
cond - .condition(fmt, ..., domain = domain,
   class = c(class., error), call = call.)
stop(cond)
}

warnf -
function(fmt, ..., class. = simpleWarning, call. = TRUE, domain = NULL)
{
## does not support immediate., but options(warn=1) supported
call. - if (is.logical(call.)  1L == length(call.)  call.)
sys.call(-1)
else NULL
cond - .condition(fmt, ..., domain = domain,
   class = c(class., warning ), call = call.)
warning(cond)
}

messagef -
function(fmt, ..., class. = simpleMessage, domain = NULL,
 appendLF = TRUE)
{
cond - .condition(fmt, ..., domain = domain, appendLF = appendLF,
   class = c(class., message))
message(cond)
}


--
Computational Biology / Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N.
PO Box 19024 Seattle, WA 98109

Location: Arnold Building M1 B861
Phone: (206) 667-2793

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel