views:

221

answers:

3

I have some class C:

class C (...) { ... }

I want to use it to index an efficient map. The most efficient map is an Array. So I add a "global" "static" counter in companion object to give each object unique id:

object C {
  var id_counter = 0
}

In primary constructor of C, with each creation of C I want to remember global counter value and increase it.
Question 1: How to do it?

Now I can use id in C objects as perfect hash to index array. But array does not preserve type information like map would, that a given array is indexed by C's id.

Question 2: Is it possible to have it with type safety?

Update:
Type safety in question 2 concerns type of index of map, to avoid mixing two not related ints. The value of course is (type) safe..

Question 1 asks how to increment a variable in default contructor?
Ie: Where to put?

id_counter += 1
+1  A: 

I don't see the problem. I would probably make the counter private so code outside class and object C cannot alter it. Incrementing a var of type Int is trivial:

idCounter += 1

Arrays are type-safe in Scala, since they are implemented directly by JVM arrays (starting in 2.8).

I suspect I've not really understood your questions...

Update:

Increment the counter in the constructor, presumably.

As for creating an actual perfect hash function, I don't think you're really on the right track. (You've just pushed the mapping from whatever your actual keys are into your own code.) You should read up on techniques for creating minimal and / or perfect hash functions.

Randall Schulz
Is incrementing the counter in the constructor thread safe?
Jeb
I believe so, providing you don't publish the value before the constructor(s) have (all) returned.
Randall Schulz
+1  A: 

Answer to your question 2:

case class C_Id(val asInt: Int)

object C {
  private var list: ArrayBuffer[C] 
  // resizable array in scala.collection.mutable
  // you can also use ArrayList

  def apply(id: C_Id) = list(id.asInt) // only accepts an id of C
  ...
}

class C (...) {
  // in constructor:
  list += this
}

To edited question 1: The default constructor is just the body of the type, except the definitions of methods and other constructors.

Alexey Romanov
Looks ok, but I need more than apply. Can't I inherit from Array or Seq?
Łukasz Lew
You can't inherit from Array, just like in Java. Just make your methods call corresponding methods on `list`, like `apply` does.
Alexey Romanov
Can implicits help me here? In a manner similar to RichString?
Łukasz Lew
If I understand you correctly, no.
Alexey Romanov
No. They are useful when you want to add a method to _every_ instance of a given type. Here you deal with a single instance of `C` companion object, and a single instance of `ArrayBuffer[C]`.
Alexey Romanov
A: 

Could you make the default constructor of C private, and provide a factory method in the companion object (which could easily handle updating the counter)?

pdbartlett