2

I'm trying to code a new operator, a double tilde ~~, to denote a different kind of formula to be passed onto another function (e.g., mirroring the functionality of ~~ in the lavaan package lavaan syntax).

The issue is y ~~ x returns y ~ ~x, where the second ~ is returned with the predictors.

I am at a total loss here. It seems ~ is a primitive function .Primitive("~") with no methods, unlike, say, +. So existing tutorials for S3 methods are useless.

Is this a dead end and am I doing something really against the programming language? Or is there an easy solution I am missing?

Community
  • 1
  • 1
jslefche
  • 4,379
  • 7
  • 39
  • 50
  • 4
    The same reason you cannot use `-` in variable names (`my-var`) is the reason you cannot use `~`. But you can use `´%~%´` for example: `´%~%´` `<- function (e1, e2) {e1*e2}` and use `3 %~% 4` ` – Drey Feb 24 '17 at 13:49
  • 1
    Rather than trying to fight with the parser, you are probably better off taking the formula as a string and parsing the syntax, as `lavaan` does with `lavParseModelString`. – nrussell Feb 24 '17 at 14:04
  • @Drey sounds like the best option, thanks! – jslefche Feb 25 '17 at 14:29

1 Answers1

1

I guess, if you accept the comment, I can make an answer out of it:

~ is an operator in R like +,-, /,*. Although it is possible to use many kinds of characters for your variables using ticks `xxx` and qoute "xxx" you also need to access them with ticks (see ?Reserved). (I'm gonna use quotes instead of ticks here, but consider using ticks for a more accepted style guide.)

R is a functional programming language and therefore you can access every single language statement as a function, e.g. a + b is the same as "+"(a, b). When you write a + b it is just syntactic sugar - language-wise it is translated into a primitive function call with two arguments.

To complicate things, there is an order of evaluation. So if you write a~~b it gets translated into "~"(a, ~b). It is because ~ is a primitive operator desiged as a sigle character. You still can define the function "~~" <- function(a,b) {a + b}, but you can only call it by "~~"(a,b) directly for it to work.

On the other hand, you need to be able to specify how a binary operator looks like. Having defined a function "asdf" <- function(a,b) {a + b} is not enough and this will not work: a asdf b

R has something to define binary operators (R: What are operators like %in% called and how can I learn about them?), see large portion of binary operators used like in magrittr's %>% or doParallel's %dopar%. Thus it is better to stick to the binary operator syntax using %, i.e. <tick>%~~%<tick> <- function(a,b) {a+b}. Then you can easily access it by using syntactic sugar a %~~% b.

Strange stuff, I agree. As for magic tricks: try this at home "for"(a, 1:10, {print(a)}). Bonus question: why is a visible in the parent frame ?

Community
  • 1
  • 1
Drey
  • 3,314
  • 2
  • 21
  • 26
  • Ok, one follow-up. If I do `%~~% <- function(e1, e2) paste(e1, e2, sep = "~~")` and supply, say, `x %~~% y` then the R environment is look for objects `x` and `y`. Can I have the input *not* be characters, e.g., `"x" %~~% "y"`? – jslefche Feb 27 '17 at 15:11
  • `%~~% <- function(e1, e2) paste(deparse(substitute(e1)), "~~", deparse(substitute(e2)))` and then: `a %~~% b` – jslefche Feb 27 '17 at 15:15
  • I assume your solution works as intended? Otherwise I don't get the question. – Drey Feb 27 '17 at 15:28