1
votes

I have heard that R is a functional programming language, so I decided to try it out for statistical computing. I am familiar with functional programming paradigms in Scala and F#, and in each of those languages, there is a neat feature called "pattern matching" where you can do things like this:

object Matcher extends App {

  class A
  class B extends A
  class C extends A

  class D(one: A, two: A) {

    def work {
      (one, two) match {
        case (o: B, t: B) => println("B")
        case (o: B, t: C) => println("C")
        case _ =>
      }
    }
  }

  val d1 = new D(new B, new B)
  val d2 = new D(new B, new C)

  d1.work
  //B
  d2.work
  //C
}

I was wondering if R had such a feature. Pattern matching in scala and F# can get more complicated and do type checks, checks on tuples, conditional checks, and more. But whenever I do a search for "pattern matching in R," all I get are regular expression type results. Does R, a functional language, not have this feature, or do I just not know what it's called?

2
I was going to say switch, but then I looked up pattern matching vs switch, so instead I'll say: no, I don't think R has that. Though switch could work for the example you give. - Gregor Thomas
@Swapnil grep* are for regular expression (ie. strictly text) pattern matching. This is a different construct: (non regular expression) pattern matching, as in this question, is a language-level feature that is often used for or involving structured decomposition of sequences/types. - user2864740
Try the lambda.r R package on CRAN and also the book by that package's author ( cartesianfaith.files.wordpress.com/2013/09/… ) and relevant articles on the author's blog: ( cartesianfaith.com/category/functional-programming ) The rscala package on CRAN may also be of interest. - G. Grothendieck

2 Answers

5
votes

You can get some of the behavior you're after with the switch function. However, R does not have sum types like the ones you're used to in Scala and F#.

R is a dynamic language, a lot like scheme and lisp but with different syntax. You're going to have to make a few adjustments if you're coming from a strongly typed language like F# or Scala. You lose the benefits of strong types, but you gain the benefits of dynamic ones.

It turns out that for data analysis, dynamic typing is often a better fit.

1
votes

R is... very different. To do something like that, you would use S4 Generics and Method Dispatch, which use a signature to access methods. It would essentially reproduce the behavior inside your Matcher object. Here is the sample code:

#- Typical R OO code uses the concept of Generic function dispatch. To use "work" as a
#- method, I need to set the generic function, from which all other methods will be
#- dispatched from. Normally, R does this by default, but it is always nicer to declare it
#- directly, as it shows that you *own* said generic. This is the example for S4 methods, 
#- so the dispatching might look weird at first (?).

require("methods")
setGeneric("work", function(one, two) print("Default"))

#- Now that we have a generic, we can create your classes and use method
#- dispatch to produce a similar effect to your pattern matcher.
setClass("A")
setClass("B", contains = "A")
setClass("C", contains = "A")


# Now, the equivalent for your "cases" in R...
setMethod("work", c(one = "B", two = "B"), function(one, two) print("B"))
setMethod("work", c(one = "B", two = "C"), function(one, two) print("C"))

work(new("B"), new("B"))
# B

work(new("B"), new("C"))
# C

#- Just an additional print call to make it obvious
work()
# Default

Note that I could have just as well defined it for independent classes "B" and "C", and it would have worked. Secondly, encapsulating this code inside an object as you did would be very tedious (e.g. using R6/Reference classes or something like that), and highlights the difference with R. Functions just love to live outside objects in R, and so it is easier to dispatch them with the object you intend to use them in as an additional argument for the signature, rather than placing them inside a particular object structure.