1

I was reading the documentation of the Rust language, and I was immediately interested in Scala Native, thinking about mature libraries and insanely optimized algorithms. I've two questions here

  1. Is it possible to have zero-cost abstractions in Scala Native (similar to Rust)?
  2. Can we do away with the BOEHM GC which is nevertheless present in all Scala Native installations, so it is usable on embedded systems?
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
srinivas
  • 11
  • 2

1 Answers1

1

for Q1: if by "zero cost abstractions" you are referring to smth analogue to type classes and compile time dispatch, I would answer this: yes, Scala does provide type classes, implemented using implicit parameters and compile time dispatch of typeclass functions (ie the implicit object holding the type class functions is identified at compile time and passed in automatically to all functions using the typeclass), and just reasoning out loud, since scala-native it emits llvm from the same internal representation as the standard scalac compiler, the runtime mechanism should be pretty similar, types may also be erased as in the JVM target (unless LLVM is super intelligent and manages to re-infer types and to do its own dispatch but I doubt it).

object Main extends App {

  // the typeclass
  trait M[A] {
    def zero: A
    def add(a1: A, a2: A): A
  }

  // the typeclass instance for Boolean
  implicit object BooleanM extends M[Boolean] {
    def zero: Boolean = false
    def add(a1: Boolean, a2: Boolean): Boolean = a1 || a2
  }
  // the typeclass instance for Int
  implicit object IntM extends M[Int] {
    def zero: Int = 0
    def add(a1: Int, a2: Int): Int = {
      require(a1 >= 0 && a2 >=0)
      a1 + a2
    }
  }
  // the typeclass instance for String
  implicit object StringM extends M[String] {
    def zero: String = ""
    def add(a1: String, a2: String): String = a1 + a2
  }

  // a generic method that uses the typeclass
  def justDoingMyThang[A: M](a1: A, a2:A): A = {
    val tc = implicitly[M[A]]
    tc.add(tc.zero, tc.add(a1, a2))
  }

  // the generic method used on types for which it is defined
  println( justDoingMyThang(false, true).toString )
  println( justDoingMyThang(1, 2).toString )
  println( justDoingMyThang("foo", "bar").toString )
}

still, the generic method that uses the typeclass is not specialized at all and calling it on either type involves first getting the implicit object using "implicitly" (a method call), and then calling a typeclass method on the implicit object (hence perhaps some V-table inspection ?).

So, there is no hardwired function call here, there some degree of indirection so the cost might be close to zero but not exactly zero.

I guess we can use @specialized as follows to get even more compile time specialization

 def justDoingMyThang[@specialized(Boolean,Int) A: M](a1: A, a2:A): A = {
    val tc = implicitly[M[A]]
    tc.add(tc.zero, tc.add(a1, a2))
  }

but any call on a non-value type will somehow use the generic version of the method. I should look at the generated code to be sure but I'm too lazy tonight...

  • for Q2: I saw in the documentation of scala-native that the GC config flag "none" was scheduled for inclusion in v.0.2.x, so perhaps we can hope for static allocation and more embedded friendliness.
remi
  • 566
  • 3
  • 13