3

I was wondering if there is an elegant way of calling "self" in a R function. An easy example would be the modification of a date, let's say a is a date in a int format (like when you read from excel).

a = 41557
a = as.Date(a, origin = "1899-12-30")

Then "a" is updated with the proper format. Obviously this example is very simple, but in a context of long variable or more complicated procedure one would like to use something like "self". Does something like this exist in R. Self simply meaning take the variable at the left part of the = sign.

a = 41557
a = as.Date(self, origin = "1899-12-30") # what to use for self. 

As a first hint I found out (I think) that some functions are able to call "self" somehow using the "<-" operator for example:

"minc<-" <- function(x, value){x*value}

Gives :

a = 2
a = minc(12)
# a = 24, which is basically : a = self*12

I don't know if such a keyword exist in R, but it would definitely helps in the readability of most of my codes.

As always, thanks for your help !

Romain.

Romain
  • 839
  • 10
  • 24
  • I don't follow. What is `self`. Perhaps you want `Recall`. – Thomas Nov 14 '14 at 15:59
  • You would call with `minc(a) <- 12` – James Nov 14 '14 at 16:08
  • @Thomas, self is just a way of saying "use the object before the = operator as an argument " I will give a shot to Recall never used it. – Romain Nov 14 '14 at 16:31
  • @James, I tried with minc(a) = 12, it works too, but it would also work with <- 12 – Romain Nov 14 '14 at 16:31
  • 2
    What is it you want to do that can't be achieved by `foo<-some_function(foo)` ? My suspicion is that you're trying to apply the syntax of some other language to `R`, rather than trying to translate the functionality you want. – Carl Witthoft Nov 14 '14 at 16:36
  • 1
    @CarlWitthoft you're right it can be achieved directly by `foo<-some_function(foo)`, which is what I explained in the inital post (the first code part). "self" is simply a key word in any object oriented language. I am simply looking for an elegant way of doing the process, because If the variable has a long name (let's say for eg. it is far in a nested list), then the code becomes hard to read. – Romain Nov 14 '14 at 17:45
  • *`self`* is not used in *all* OO languages (e.g. Java uses `this`). On the other hand, I agree with Carl Witthoft: Don't simply try to write the same code between languages, but translate it appropriately (remember, R is not really a "general purpose" language, it's more specialized) – Barranka Nov 14 '14 at 18:44
  • R is my main programming language. I was just trying to see if improvement was possible, and if there was something I did not know. I am not the only one who found that it would be nice to have such a feature (http://stackoverflow.com/questions/7768686/r-self-reference). I don't understand why we immediately assume that I am not approaching in a proper way the problem and give me negative mark for that. – Romain Nov 14 '14 at 19:46
  • Definitely worth looking into, this looks good. – Romain Nov 14 '14 at 21:25
  • @Gregor tried the package, it is close to what I intend. but still not on it. The closer I could get was : `a <- a %<% as.Date(., origin = "1899-12-30")`. Which has the same issue which is to repeat the a variable. If only it could understand that it has to overlap the "a". Would a different sign do the trick %<>% did not work. – Romain Nov 15 '14 at 23:24
  • @Gregor, you're right, the CRAN did not contain the %<>% sign. I just used it and it works like a charm. Can you post your answer in a proper way so I can check it ? Thanks again !! – Romain Nov 17 '14 at 15:54

2 Answers2

2

The functionality you're looking for is implemented in the fantastic magrittr package. The version on CRAN introduces a piping operator, %>%, which passes what precedes is as the first argument of what follows it (by default), or replaces a . with the preceding statement.

More to the point of your question, the version on Github introduces many piping variants, including %<>% which works just like the regular pipe, but includes an overwrite assignment.

The following statements are equivalent (with magrittr version >= 1.1.0, as available on Github, devtools::install_github("smbache/magrittr")):

a = as.Date(a, origin = "1899-12-30")
a = a %>% as.Date(origin = "1899-12-30")
a %<>% as.Date(., origin = "1899-12-30")
a %<>% as.Date(origin = "1899-12-30")
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
1

Replacement functions can be used like this:

1) as.Date

"as.Date<-" <- function(x, value) as.Date(x, origin = value)

Now test it:

a <- 41557
as.Date(a) <- "1899-12-30"
a
## [1] 2013-10-10

2) minc

"minc<-" <- function(x, value) x * value

Now test it:

a <- 2
minc(a) <- 12
a
## [1] 24

Note: You can use self in place of x if you like:

"as.Date<-" <- function(self, value) as.Date(self, origin = value)
"minc" <- function(self, value) self * value
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • Thanks, this is helping a little, I was looking for something that would allow me not to modify the initial function. I guess it does not exist. If I don't get any answer by the end of the week. I will check yours as a solution. Thanks for your help ! – Romain Nov 14 '14 at 19:48
  • 1
    Its not pretty but you can write a function that modifies its first argument like this: `minc <- function(self, x, env = parent.frame()) assign(deparse(substitute(self)), self * x, env); a <- 2; minc(a, 12); print(a)` . – G. Grothendieck Nov 14 '14 at 19:53