Re: [Rd] Extending suggestion for stopifnot
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
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
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
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
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
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
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
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
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
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
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
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