[Rd] "if" function in pure R?

2019-05-26 Thread Alexandre Courtiol
Hi all,

Could anyone refer to me to a good source to learn how to program a simple
control-flow construct* in R, or provide me with a simple example?

Control-flow constructs are programmed as primitives, but I would like to
be able to do that (if possible) in pure R.

The general context is that those functions are a mystery to me. The
motivating example is that I would like to create a function that behave
similarly to base::`if` with an extra argument to the function (e.g. to
include an error rate on the condition).

Many thanks,

Alex

* control-flow constructs are functions such as if, for, while... that
allow for call of the form fn(x) expr to work (see ?Control).

-- 
Alexandre Courtiol

http://sites.google.com/site/alexandrecourtiol/home

*"Science is the belief in the ignorance of experts"*, R. Feynman

[[alternative HTML version deleted]]

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


Re: [Rd] rbind has confusing result for custom sub-class (possible bug?)

2019-05-26 Thread Michael Chirico
Have finally managed to come up with a fix after checking out sys.calls()
from within the as.Date.IDate debugger, which shows something like:

[[1]] rbind(DF, DF)
[[2]] rbind(deparse.level, ...)
[[3]] `[<-`(`*tmp*`, ri, value = 18042L)
[[4]] `[<-.Date`(`*tmp*`, ri, value = 18042L)
[[5]] as.Date(value)
[[6]] as.Date.IDate(value)

I'm not sure why [<- is called, I guess the implementation is to assign to
the output block by block? Anyway, we didn't have a [<- method. And
[<-.Date looks like:

value <- unclass(as.Date(value)) # <- converts to double
.Date(NextMethod(.Generic), oldClass(x)) # <- restores 'IDate' class

So we can fix our bug by defining a [<- class; the question that I still
don't see answered in documentation or source code is, why/where is [<-
called, exactly?

Mike C

On Sun, May 26, 2019 at 1:16 PM Michael Chirico 
wrote:

> Debugging this issue:
>
> https://github.com/Rdatatable/data.table/issues/2008
>
> We have custom class 'IDate' which inherits from 'Date' (it just forces
> integer storage for efficiency, hence, I).
>
> The concatenation done by rbind, however, breaks this and returns a double:
>
> library(data.table)
> DF = data.frame(date = as.IDate(Sys.Date()))
> storage.mode(rbind(DF, DF)$date)
> # [1] "double"
>
> This is specific to base::rbind (data.table's rbind returns an integer as
> expected); in ?rbind we see:
>
> The method dispatching is not done via UseMethod(), but by C-internal
> dispatching. Therefore there is no need for, e.g., rbind.default.
> The dispatch algorithm is described in the source file
> (ā€˜.../src/main/bind.c’) as
> 1. For each argument we get the list of possible class memberships from
> the class attribute.
> 2. *We inspect each class in turn to see if there is an applicable
> method.*
> 3. If we find an applicable method we make sure that it is identical to
> any method determined for prior arguments. If it is identical, we proceed,
> otherwise we immediately drop through to the default code.
>
> It's not clear what #2 means -- an applicable method *for what*? Glancing
> at the source code would suggest it's looking for rbind.IDate:
>
> https://github.com/wch/r-source/blob/trunk/src/main/bind.c#L1051-L1063
>
> const char *generic = ((PRIMVAL(op) == 1) ? "cbind" : "rbind"); // should
> be rbind here
> const char *s = translateChar(STRING_ELT(classlist, i)); // iterating over
> the classes, should get to IDate first
> sprintf(buf, "%s.%s", generic, s); // should be rbind.IDate
>
> but adding this method (or even exporting it) is no help [ simply defining
> rbind.IDate = function(...) as.IDate(NextMethod()) ]
>
> Lastly, it appears that as.Date.IDate is called, which is causing the type
> conversion:
>
> debug(data.table:::as.Date.IDate)
> rbind(DF, DF) # launches debugger
> x
> # [1] "2019-05-26" <-- singleton, so apparently applied to DF$date, not
> c(DF$date, DF$date)
> undebug(data.table:::as.Date.IDate)
>
> I can't really wrap my head around why as.Date is being called here, and
> even allowing that, why the end result is still the original class [
> class(rbind(DF, DF)$date) == c('IDate', 'Date') ]
>
> So, I'm beginning to think this might be a bug. Am I missing something?
>

[[alternative HTML version deleted]]

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


Re: [Rd] rbind has confusing result for custom sub-class (possible bug?)

2019-05-26 Thread Joshua Ulrich
On Sun, May 26, 2019 at 4:06 AM Michael Chirico
 wrote:
>
> Have finally managed to come up with a fix after checking out sys.calls()
> from within the as.Date.IDate debugger, which shows something like:
>
> [[1]] rbind(DF, DF)
> [[2]] rbind(deparse.level, ...)
> [[3]] `[<-`(`*tmp*`, ri, value = 18042L)
> [[4]] `[<-.Date`(`*tmp*`, ri, value = 18042L)
> [[5]] as.Date(value)
> [[6]] as.Date.IDate(value)
>
> I'm not sure why [<- is called, I guess the implementation is to assign to
> the output block by block? Anyway, we didn't have a [<- method. And
> [<-.Date looks like:
>
> value <- unclass(as.Date(value)) # <- converts to double
> .Date(NextMethod(.Generic), oldClass(x)) # <- restores 'IDate' class
>
> So we can fix our bug by defining a [<- class; the question that I still
> don't see answered in documentation or source code is, why/where is [<-
> called, exactly?
>
Your rbind(DF, DF) call dispatches to base::rbind.data.frame().  The
`[<-` call is this line:
value[[jj]][ri] <- if (is.factor(xij)) as.vector(xij) else xij

That's where the storage.mode changes from integer to double.

debug: value[[jj]][ri] <- if (is.factor(xij)) as.vector(xij) else xij
Browse[2]>
debug: xij
Browse[2]> storage.mode(xij)
[1] "integer"
Browse[2]> value[[jj]][ri]
[1] "2019-05-26"
Browse[2]> storage.mode(value[[jj]][ri])
[1] "integer"
Browse[2]>
debug: if (!is.null(nm <- names(xij))) names(value[[jj]])[ri] <- nm
Browse[2]> storage.mode(value[[jj]][ri])
[1] "double"


> Mike C
>
> On Sun, May 26, 2019 at 1:16 PM Michael Chirico 
> wrote:
>
> > Debugging this issue:
> >
> > https://github.com/Rdatatable/data.table/issues/2008
> >
> > We have custom class 'IDate' which inherits from 'Date' (it just forces
> > integer storage for efficiency, hence, I).
> >
> > The concatenation done by rbind, however, breaks this and returns a double:
> >
> > library(data.table)
> > DF = data.frame(date = as.IDate(Sys.Date()))
> > storage.mode(rbind(DF, DF)$date)
> > # [1] "double"
> >
> > This is specific to base::rbind (data.table's rbind returns an integer as
> > expected); in ?rbind we see:
> >
> > The method dispatching is not done via UseMethod(), but by C-internal
> > dispatching. Therefore there is no need for, e.g., rbind.default.
> > The dispatch algorithm is described in the source file
> > (ā€˜.../src/main/bind.c’) as
> > 1. For each argument we get the list of possible class memberships from
> > the class attribute.
> > 2. *We inspect each class in turn to see if there is an applicable
> > method.*
> > 3. If we find an applicable method we make sure that it is identical to
> > any method determined for prior arguments. If it is identical, we proceed,
> > otherwise we immediately drop through to the default code.
> >
> > It's not clear what #2 means -- an applicable method *for what*? Glancing
> > at the source code would suggest it's looking for rbind.IDate:
> >
> > https://github.com/wch/r-source/blob/trunk/src/main/bind.c#L1051-L1063
> >
> > const char *generic = ((PRIMVAL(op) == 1) ? "cbind" : "rbind"); // should
> > be rbind here
> > const char *s = translateChar(STRING_ELT(classlist, i)); // iterating over
> > the classes, should get to IDate first
> > sprintf(buf, "%s.%s", generic, s); // should be rbind.IDate
> >
> > but adding this method (or even exporting it) is no help [ simply defining
> > rbind.IDate = function(...) as.IDate(NextMethod()) ]
> >
> > Lastly, it appears that as.Date.IDate is called, which is causing the type
> > conversion:
> >
> > debug(data.table:::as.Date.IDate)
> > rbind(DF, DF) # launches debugger
> > x
> > # [1] "2019-05-26" <-- singleton, so apparently applied to DF$date, not
> > c(DF$date, DF$date)
> > undebug(data.table:::as.Date.IDate)
> >
> > I can't really wrap my head around why as.Date is being called here, and
> > even allowing that, why the end result is still the original class [
> > class(rbind(DF, DF)$date) == c('IDate', 'Date') ]
> >
> > So, I'm beginning to think this might be a bug. Am I missing something?
> >
>
> [[alternative HTML version deleted]]
>
> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



-- 
Joshua Ulrich  |  about.me/joshuaulrich
FOSS Trading  |  www.fosstrading.com
R/Finance 2019 | www.rinfinance.com

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


Re: [Rd] "if" function in pure R?

2019-05-26 Thread King Jiefei
Hi Alexandre,

I'm not an R expert so this is only my personal thought:

I don't think you can achieve what you want exactly. A possible solution
would be defining a binary operator %*%, where you can replace the asterisk
with any function name you want. The function %*% is special since it has
two arguments, left operand and right operand respectively. You then
can call the `substitute` function to get its function arguments in an
expression format and proceed to do what you want. Here is an example to
show the idea.

*Code:*

`%myOperator%` <- function(x, y) {
  x = substitute(x)
  y = substitute(y)
  return(list(x, y))
}


myIf(i == 1, arg1) %myOperator% {
  doSomeThing
}


*Results:*

[[1]]
myIf(i == 1, arg1)

[[2]]
{
doSomeThing
}

I hope that helps.

Best,
Jiefei

On Sun, May 26, 2019 at 4:45 AM Alexandre Courtiol <
alexandre.court...@gmail.com> wrote:

> Hi all,
>
> Could anyone refer to me to a good source to learn how to program a simple
> control-flow construct* in R, or provide me with a simple example?
>
> Control-flow constructs are programmed as primitives, but I would like to
> be able to do that (if possible) in pure R.
>
> The general context is that those functions are a mystery to me. The
> motivating example is that I would like to create a function that behave
> similarly to base::`if` with an extra argument to the function (e.g. to
> include an error rate on the condition).
>
> Many thanks,
>
> Alex
>
> * control-flow constructs are functions such as if, for, while... that
> allow for call of the form fn(x) expr to work (see ?Control).
>
> --
> Alexandre Courtiol
>
> http://sites.google.com/site/alexandrecourtiol/home
>
> *"Science is the belief in the ignorance of experts"*, R. Feynman
>
> [[alternative HTML version deleted]]
>
> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

[[alternative HTML version deleted]]

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


Re: [Rd] "if" function in pure R?

2019-05-26 Thread Alexandre Courtiol
Thanks a lot Jiefei,

I had thought of defining a binary operator (inspired by pipes) or simply
using an additional condition in the if() calls [e.g. if(foo & fn(bar))
doSomeThing; with fn(bar) returning a logical], but both are workaround
that I do not find as elegant as a proper control-flow construct.

Thus two questions remain:
- is it possible to create a control-flow construct in pure R?
- if yes, how?

Anyone with more insights?
Thanks

On Mon, 27 May 2019 at 04:27, King Jiefei  wrote:

> Hi Alexandre,
>
> I'm not an R expert so this is only my personal thought:
>
> I don't think you can achieve what you want exactly. A possible solution
> would be defining a binary operator %*%, where you can replace the asterisk
> with any function name you want. The function %*% is special since it has
> two arguments, left operand and right operand respectively. You then
> can call the `substitute` function to get its function arguments in an
> expression format and proceed to do what you want. Here is an example to
> show the idea.
>
> *Code:*
>
> `%myOperator%` <- function(x, y) {
>   x = substitute(x)
>   y = substitute(y)
>   return(list(x, y))
> }
>
>
> myIf(i == 1, arg1) %myOperator% {
>   doSomeThing
> }
>
>
> *Results:*
>
> [[1]]
> myIf(i == 1, arg1)
>
> [[2]]
> {
> doSomeThing
> }
>
> I hope that helps.
>
> Best,
> Jiefei
>
> On Sun, May 26, 2019 at 4:45 AM Alexandre Courtiol <
> alexandre.court...@gmail.com> wrote:
>
>> Hi all,
>>
>> Could anyone refer to me to a good source to learn how to program a simple
>> control-flow construct* in R, or provide me with a simple example?
>>
>> Control-flow constructs are programmed as primitives, but I would like to
>> be able to do that (if possible) in pure R.
>>
>> The general context is that those functions are a mystery to me. The
>> motivating example is that I would like to create a function that behave
>> similarly to base::`if` with an extra argument to the function (e.g. to
>> include an error rate on the condition).
>>
>> Many thanks,
>>
>> Alex
>>
>> * control-flow constructs are functions such as if, for, while... that
>> allow for call of the form fn(x) expr to work (see ?Control).
>>
>> --
>> Alexandre Courtiol
>>
>> http://sites.google.com/site/alexandrecourtiol/home
>>
>> *"Science is the belief in the ignorance of experts"*, R. Feynman
>>
>> [[alternative HTML version deleted]]
>>
>> __
>> R-devel@r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>

-- 
Alexandre Courtiol

http://sites.google.com/site/alexandrecourtiol/home

*"Science is the belief in the ignorance of experts"*, R. Feynman

[[alternative HTML version deleted]]

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