How storage methods are stored without re-creating each call method

I have a Scala class where methods use a lot of regular expressions. Each class method uses some regular expression patterns. Taking a look at the modularity of the code, I have to keep these templates in a method:

class Bar {
    def foo() {
        val patt1 = "[ab]+".r
        val patt2 = "[cd]+".r
        /*...*/
    }
}

      

But this approach is rather ineffective. The templates are recompiled each time the method is called. I could move them directly to the class:

class Bar {
    val fooPatt1 = "[ab]+".r
    val fooPatt2 = "[cd]+".r
    /*...*/
}

      

but in case I have 30 methods it looks ugly.

I ended up with some hybrid solution using val and an anonymous function:

val z = {
    val patt1 = "[ab]+".r
    val patt2 = "[cd]+".r
    () => { /* ... */ }
}

      

but I'm not sure if using the val function for storage has some disadvantages compared to def. Maybe there is another clean solution for storing method constants without polluting the class?

+3


source to share


3 answers


Usage is val

excellent. There may be (very) little success, but in most (99.9%) applications this is not a problem.

You can also create a class for the method

// The extends is not needed, although you might want to hide the Foo type
class Foo extends (() => ...) {
  val patt1 = "[ab]+".r
  val patt2 = "[cd]+".r

  def apply() = {
    ...
  }
}

      

Then in the class:



class Bar {
  val foo = new Foo
}

      

Another solution uses traits

trait Foo {
  private lazy val patt1 = "[ab]+".r
  private lazy val patt2 = "[cd]+".r

  def foo() = ...
}

class Bar extends Foo with ...

      

Please note that if you have different methods like this in the same class, this may mean that the single responsibility principle is violated. Moving them to their own class (or property) can also be a solution to this problem.

+2


source


I would put each method with the required regex in its own Trait:

class Bar extends AMethod with BMethod

trait AMethod {
  private val aPattern = """\d+""".r   
  def aMethod(s: String) = aPattern.findFirstIn(s)
}

trait BMethod {
  private val bPattern = """\w+""".r
  def bMethod(s: String) = bPattern.findFirstIn(s)
}

      



  • clean
  • detached
  • easy to check (AMethodSpec object extends properties ("AMethod") with AMethod ...)
+1


source


I took into account Chris's comment. Putting templates on a companion object is perhaps the most efficient approach, but very impure when we have more methods. The EECOLOR solution is less effective but cleaner. Traits prevent templates from being recreated on every method call. Unfortunately scala does not use the same compiled template for multiple class instances:

(new X).patt1==(new X).patt1 // would be false.

      

I combined the two approaches and used objects instead.

object X {
  object method1 {
    val patt1 = "a".r
  }
  object method2 {
    val patt1 = "a".r
  }
}
class X {
  def method1 = {
    import X.method1._
    patt1
  }
  def method2 = {
    import X.method2._
    patt1
  }
}

(new X).method1 == (new X).method1 // true
(new X).method2 == (new X).method2 // true

      

While this approach works, I think scala should provide some solution for this problem out of the box. Samples are the simplest example. We could have other immutable objects that are much more expensive to initialize. Extracting inside a method inside is unclear. It would be nice to do it like with lazy waltzes. Adding one modifier should ensure that the value is instantiated only once for all instances and methods. It would be like this:

def method1 {
 static val  x = new VeryExpensiveObject
}

      

0


source







All Articles