[Rd] On the mechanics of function evaluation and argument matching

2013-07-17 Thread Brian Rowe
Hello,

Section 4.3.2 of the R language definition [1] states that argument matching to 
formal arguments is a 3-pass process to match arguments to a function. An error 
is generated if any (supplied) arguments are left unmatched. Interestingly the 
opposite is not true as any unmatched formals does not generate an error.

> f <- function(x,y,z) x
> f(2)
[1] 2
> f(2,3)
[1] 2

Since R is lazily evaluated, I understand that it is not an error for an unused 
argument to be unassigned. However, it is surprising to me that a function need 
not be called with all its required arguments. I guess in this situation 
technically "required arguments" means required and referenced arguments. 

> f()
Error in f() : argument "x" is missing, with no default

Can anyone shed light on the reasoning for this design choice?

Warm Regards,
Brian Rowe


[1] 
http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Argument-matching


[[alternative HTML version deleted]]

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


Re: [Rd] On the mechanics of function evaluation and argument matching

2013-07-17 Thread Brian Rowe
Thanks for the lead. Given the example in ?missing though, wouldn't it be safer 
to explicitly define a default value of NULL:

myplot <- function(x, y=NULL) {
  if(is.null(y)) {
y <- x
x <- 1:length(y)
  }
  plot(x, y)
}



On Jul 17, 2013, at 11:05 AM, "R. Michael Weylandt" 
 wrote:

> On Wed, Jul 17, 2013 at 9:58 AM, Brian Rowe  wrote:
>> Hello,
>> 
>> Section 4.3.2 of the R language definition [1] states that argument matching 
>> to formal arguments is a 3-pass process to match arguments to a function. An 
>> error is generated if any (supplied) arguments are left unmatched. 
>> Interestingly the opposite is not true as any unmatched formals does not 
>> generate an error.
>> 
>>> f <- function(x,y,z) x
>>> f(2)
>> [1] 2
>>> f(2,3)
>> [1] 2
>> 
>> Since R is lazily evaluated, I understand that it is not an error for an 
>> unused argument to be unassigned. However, it is surprising to me that a 
>> function need not be called with all its required arguments. I guess in this 
>> situation technically "required arguments" means required and referenced 
>> arguments.
>> 
>>> f()
>> Error in f() : argument "x" is missing, with no default
>> 
>> Can anyone shed light on the reasoning for this design choice?
> 
> I'm not sure I can, but I'd look around at how the missing() function is used.
> 
> Cheers,
> MW

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


Re: [Rd] On the mechanics of function evaluation and argument matching

2013-07-17 Thread Brian Rowe
I agree that failing fast is a good principle. My initial point led the other 
way though, i.e. any unmatched formal arguments without default values should 
be handled in one of two ways:

1. Fail the function call. This is what most non-functional languages do e.g. 
Python
>>> def f(x,y,z): x
...
>>> f(2)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: f() takes exactly 3 arguments (1 given)

2. Perform partial application, like some functional languages e.g. Haskell
f :: Int -> Int -> Int -> Int
f x y z = x

*Main> let a = f 2
*Main> :t a
a :: Int -> Int -> Int

Otherwise if an argument is truly optional, I don't see why a default value 
cannot be assigned to the formal argument when defining the function (excepting 
the edge cases you pointed out earlier).

Brian


On Jul 17, 2013, at 2:35 PM, Peter Meilstrup  wrote:

> On Wed, Jul 17, 2013 at 10:20 AM, Ben Bolker  wrote:
> 
>> Brian Rowe  muxspace.com> writes:
>> 
>>> 
>>> Thanks for the lead. Given the example in ?missing though,
>>> wouldn't it be safer to explicitly define a
>>> default value of NULL:
>>> 
>>> myplot <- function(x, y=NULL) {
>>>  if(is.null(y)) {
>>>y <- x
>>>x <- 1:length(y)
>>>  }
>>>  plot(x, y)
>>> }
>>> 
>> 
>> [snip]
>> 
>> In my opinion the missing() functionality can indeed be
>> fragile (for example, I don't know how I can manipulate an
>> existing call to make an argument be 'missing' when it was
>> previously 'non-empty')
> 
> 
> Like so:
> 
>> thecall <- quote(x[i,j])
>> thecall[[3]] <- quote(expr=)
>> thecall
> x[, j]
> 
> 
>> and using an explicit NULL is often
>> a good idea.  This makes the documentation a tiny bit less
>> wieldy if you have lots of parameters ...
> 
> 
> I could certainly imagine a variant of R in which missing and NULL are
> unified, and NULL is the default for any binding that exists but was not
> given a value. I would probably prefer it on the grounds of being smaller
> and more consistent.  (At the C implementation level, R_MissingArg and
> R_NilValue are just two parallel uses of the null object pattern with
> different behavior, which is a bit silly)
> 
> But one advantage the missing value behavior can have is that it "fails
> early", i.e. it generates an error closer to where a function wants to use
> a value it was not provided, rather than "failing late," where a NULL
> propagates though your data and you have to do more debugging work to find
> out where it came from. This kind of fragility can be a good thing as it's
> easier to debug problems that happen closer to the point of failure.
> 
> For instance,
> 
>> myplot <- function(y, x=1:length(y)) plot(x,y)
>> myplot()
> Error in plot(x, y) (from #1) :
>  error in evaluating the argument 'x' in selecting a method for function
> 'plot': Error in length(y) (from #1) : 'y' is missing
> 
> I didn't think about what myplot should do with no arguments. As it turns
> out it is an error, as R refuses to pass a missing value along to length()
> or plot(), which is reasonable.
> 
> Compare with a default-NULL version.
>> myplot <- function(y=NULL, x=1:length(y)) plot(x,y)
>> myplot()
> 
> Instead of failing early and generating a stack trace pointing you at the
> problem, myplot() now generates a graph with points at (0,0) and (1,1) --
> most surprising! This is because R happily forwards NULL to length() and
> plot() where it refused to earlier. In more complicated code nulls can pass
> along several layers before causing problems, making those problems more of
> a headache to debug.
> 
> Peter
> 
>   [[alternative HTML version deleted]]
> 
> __
> 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 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

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



On Aug 20, 2013, at 4:36 PM, Peter Langfelder  
wrote:

> On Tue, Aug 20, 2013 at 11:41 AM, ivo welch  
> 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] legitimate use of :::

2013-08-22 Thread Brian Rowe
Another point to consider is that copying someone else's code forces you to 
become a maintainer of the copied code. If there are any bug 
fixes/enhancements/what-have-you in the original you won't get those updates. 
So now you own the copied code and need to consider the cost of the codebase 
diverging (from the original).

On Aug 22, 2013, at 5:03 PM, Hadley Wickham  wrote:

>> To avoid the NOTEs (which often triggers a 'pls fix' upon submission to
>> CRAN), I simply copied/pasted these functions to my package, but this seems
>> wasteful.
> 
> Wasteful of disk space, but disk space is cheap. It's less wasteful of
> your time, if the referenced code breaks in an unexpected time.  Your
> time is much more valuable than disk space.
> 
> A gigabyte of disk space costs about $0.10, so even if you value your
> time at a very conservative rate of $100 / hour, you should only spend
> an hour of your time reducing package size if it saves at least 1 TB
> of disk space. That's a lot of copies of a function!
> 
> Hadley
> 
> -- 
> Chief Scientist, RStudio
> http://had.co.nz/
> 
> __
> 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] Type annotations for R function parameters.

2013-08-30 Thread Brian Rowe
The type constraints in lambda.r make this relatively easy. The idea is to add 
a declaration before a function that provides static typing on the function 
arguments. The type constraint also specifies the return type, so it would be 
straightforward to construct a graph. Where a type variable is used, then there 
would need to be a run-time determination for the actual types as happens in 
Haskell. Obviously to have a complete graph of a program would require the 
whole program to be written using lambda.r.

For example you can decorate two separate function clauses each with their own 
type constraint.

slice(x, pivot, inclusive) %::% a : numeric : logical : list
slice(x, pivot, inclusive=FALSE) %as% {
  left <- x[1:pivot]
  right <- x[(pivot+as.numeric(!inclusive)):length(x)]
  list(left, right)
}

slice(x, expression) %::% a : logical : list
slice(x, expression) %as% {
  left <- x[expression]
  right <- x[!expression]
  list(left, right)
}

This calls the first clause since the second argument is numeric.
> x <- rnorm(10)
> slice(x, 4)
[[1]]
[1]  1.2468112 -0.2795106  0.5775026  1.0521653

[[2]]
[1] -1.0493246 -2.0634126  0.0368455 -1.8431248 -0.3630197  0.1015901


This calls the second clause since x < 0 is logical.
> slice(x, x < 0)
[[1]]
[1] -0.2795106 -1.0493246 -2.0634126 -1.8431248 -0.3630197

[[2]]
[1] 1.2468112 0.5775026 1.0521653 0.0368455 0.1015901


This fails since no clause of the function accepts a character as the second 
argument.
> slice(x, 'a')
Error in UseFunction(slice, "slice", ...) :
  No valid function for 
'slice(c(1.24681120969809,-0.279510617209735,0.577502630574721,1.05216534148533,
 ...),a)'


Warm Regards,
Brian



On Aug 30, 2013, at 5:19 AM, Оботуров Артем  wrote:

> Hello.
> 
> One of my clients asked if it would be possible to have an IDE which could
> use type discovery for R functions to make flow-like construction of an R
> program. Something like a LabView graphical composition of processing
> elements.
> 
> They called this type of program composition a "workflow".
> 
> I looked at some of this programs, like:
> * Orange http://orange.biolab.si/
> * RedR http://www.red-r.org/
> * Rattle http://rattle.togaware.com/
> * Rpad https://code.google.com/p/rpad/
> 
> and all of them did type introspection (they made mapping between R
> functions and their IDE's visual framework) by hand for each function of
> supported packages which is time and resource consuming.
> 
> So, to reduce an amount of code to be written for adapters between R and
> IDE some kind of annotations could be introduced over parameters and return
> values. Those could be optional and will help to discover type information
> for support of dynamic composition of programs.
> 
> Do you have any suggestions on the topic?
> 
> Best regards,
> 
> Artem Oboturov
> 
>   [[alternative HTML version deleted]]
> 
> __
> 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] declaring package dependencies

2013-09-15 Thread Brian Rowe
Something that might be of use to you guys is crant 
(https://github.com/muxspace/crant), which is a set of scripts to make package 
development and testing simpler. With crant you can build out multiple R 
instances (release, patch, devel) and then run the build chain against each 
one. It's compatible with devtools, and we're working on a few other 
conveniences, like testing all the the reverse depends to understand whether a 
change to a package breaks downstream dependencies. I've certainly bitten 
myself and incurred the wrath of CRAN a few times because I didn't check this 
sort of thing thoroughly enough. Running this on a virtual machine ensures that 
the environment is clean for building/testing. 

Of course, it doesn't address the communication issues (which I find somewhat 
amusing because the CRAN maintainers always seem to be in absentia during these 
discussions), but assuming that the CRAN checks are added to the devel branch, 
it shouldn't matter insomuch as detecting them prior to submission. 
Understanding the rationale for the change is a different matter.

Brian


On Sep 15, 2013, at 2:05 PM, Paul Gilbert  wrote:
> On 13-09-14 07:20 PM, Duncan Murdoch wrote:
>> On 13-09-14 12:19 PM, Paul Gilbert wrote:
>> 
>> I many not fully understand how much of the response to
>>> package submission gets done automatically, but I do get the sense that
>>> there is a fairly large amount of actual human time spent dealing with
>>> just my submissions alone. If that is representative of all developers,
>>> then CRAN maintainers don't have time to do much else. (The fact that
>>> they do much more suggests I may not be representative.)
>>> 
>>> Two specific points have already been mentioned implicitly. CRAN
>>> submission testing is often done at a higher/newer level using the
>>> latest devel version. This results in lots of rejections for things that
>>> I would fix before submission, if I knew about them.
>> 
>> Then why don't you test against R-devel before submitting?
> 
> I have been relying on R-forge to provide that testing. One practical 
> suggestion in this thread (Matthew Dowle) was to test with win-builder 
> R-devel. This needs to be amplified. I had thought of win-builder as a 
> mechanism to test on Windows, since I rarely work on that platform. Following 
> the CRAN submission guidelines I test on win-builder if I am not doing the 
> Windows testing on my own machine and the R-forge results are not available. 
> (I think for a single package they are equivalent when R-forge is working.) 
> But on win-builder I have usually used the R-release directory. Using the 
> R-devel directory has the advantage that it gives an as-cran test that is 
> almost up-to-date with the one against which the package is tested when it is 
> submitted.  Another feature of win-builder that I had not recognized is that 
> submitted packages are available in its library for a short time, so packages 
> with version dependencies can be tested there, whereas they cannot be tested 
> on R-forge.
>> 
>>  If the tests were
>>> rolled out with R, and only later incorporated into CRAN submission
>>> testing, I think there would be a lot less work for the CRAN
>>> maintainers.
>> 
>> I am an R core member, not a member of CRAN.  If I make a change to R,
>> I'd like to know the effect it has on the corpus of CRAN and
>> Bioconductor packages, but I don't have the computing resources to run
>> it against all of those in a reasonable amount of time.  We have heard
>> from various corporate users of R (Revolution Computing and Google are
>> two) that they would like to contribute to the project, but we don't
>> actually see useful contributions from them.
>> 
>> I don't know if you personally have influence with anyone who has such
>> resources,
> 
> As far as I know I don't have any influence with anybody, but I like this 
> suggestion.
> 
> Paul
> 
>> but surely some on this list do.  So why don't they write to
>> me and tell me how to use their computing resources to run proposed
>> changes against all published packages?  I think it's because it's
>> easier to do nothing than to do something.  It's certainly easier to say
>> that it's the CRAN maintainers' fault for poor communication than it is
>> to identify and address the problems.
>> 
>> Duncan Murdoch
>> 
>> 
>>  (This is ignoring the possibility that CRAN submission is
>>> really the testing ground for the tests, and to prove the tests requires
>>> a fair amount of manual involvement. I'm happy to continue contributing
>>> to this -- I've often felt my many contribution is an endless supply of
>>> bugs for the checkers to catch.)
>>> 
>>> The second point is that a facility like R-forge that runs the latest
>>> checks, on many platforms, is really useful in order to reduce work for
>>> both package developers and CRAN maintainers. With R-forge broken, the
>>> implication for additional work for CRAN maintainers seems enormous. But
>>> even with it working, not

Re: [Rd] declaring package dependencies

2013-09-15 Thread Brian Rowe
That reminds me: I once made a suggestion on how to automate some of the CRAN 
deployment process, but it was shot down as not being useful to them. I do 
recall a quote that was along the lines of "as long as you don't need help, do 
whatever you want", so one thought is to just set up a build server that does 
the building across the three versions of R, checks dependencies, rebuilds when 
release, patch, or devel are updated, etc. This would ease the burden on 
package maintainers and would just happen to make the CRAN folks' lives easier 
by catching a lot of bad builds. A proof of concept on AWS connecting to github 
or rforge could probably be finished on a six-pack. Speak up if anyone thinks 
this would be useful.


On Sep 15, 2013, at 9:58 PM, Yihui Xie  wrote:

> I've been watching this thread closely and trying not to chime in,
> because as Brian Rowe mentioned about CRAN's mysterious absence in a
> previous reply. CRAN is like a ghost in r-devel (or any other mailing
> lists) -- everybody is discussing about it, and nobody has ever seen
> it. Perhaps one day useRs will realize that the rings of Saturn are
> actually composed of the lost discussions about CRAN. (Just kidding.
> No offence. I swear I appreciate the great work of CRAN, and
> rep("thank you, CRAN", 1e6).)
> 
> Although this discussion may also contribute to the rings of Saturn, I
> want to emphasize one final point: requests from package authors do
> not necessarily mean more work for CRAN.
> 
> Regards,
> Yihui
> --
> Yihui Xie 
> Web: http://yihui.name
> Department of Statistics, Iowa State University
> 2215 Snedecor Hall, Ames, IA
> 
> 
> On Sun, Sep 15, 2013 at 6:11 PM, Ben Bolker  wrote:
>> Matthew Dowle  mdowle.plus.com> writes:
>> 
>>> 
>>> 
>>> I'm a little surprised by this thread.
>>> 
>>> I subscribe to the RSS feeds of changes to NEWS (as Dirk mentioned) and
>>> that's been pretty informative in the past :
>>> http://developer.r-project.org/RSSfeeds.html
>>> 
>>> Mainly though, I submit to winbuilder before submitting to CRAN, as the
>>> CRAN policies advise.  winbuilder's R-devel seems to be built daily,
>>> saving me the time. Since I don't have Windows it kills two birds with
>>> one stone.  It has caught many problems for me before submitting to CRAN
>>> and I can't remember it ever not responding in a reasonable time.
>>> http://win-builder.r-project.org/upload.aspx
>>> 
>>> I've suggested before that winbuilder could be the mechanism to submit
>>> to CRAN rather than an ftp upload to incoming.  Only if winbuilder
>>> passed OK on R-devel could it then go to a human.   But iirc there was a
>>> technical difficulty preventing this.
>>> 
>>> Matthew
>> 
>>  I was planning to write a careful e-mail to CRAN suggesting
>> essentially this, and I may yet do so, but for now I'll just chime in
>> and "+1" this.  Yihui Xie made a very similar suggestion sometime
>> last year (I think).  It would seem so much easier for everyone,
>> package maintainers *and* CRAN maintainers, to have an automatic
>> filter of this sort, and I can't figure out any downside other than
>> needing slightly more computer power (which surely must be a reasonable
>> tradeoff for fewer human resources!), *if* having the
>> auto-filter made people sloppier about checking before submitting.
>>   Do you happen to remember what the technical difficulty was?
>> If I were a CRAN maintainer (thank goodness I'm not!), overcoming
>> it would be one of my top priorities ...
>> 
>>  Ben Bolker
> 
> __
> 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