0

I am trying to use the put method of the ContentValues class in the Android API from Scala, but I can't figure out a way to make Scala narrow down the type of list elements. For example :

val a: List[(String, Any)](...)
val cv = new ContentValues
for ((k,v) <- a) cv.put(k,v)

...yields an error that roughly says it can't resolve the "overloaded put method with alternatives put(String, String), put(String, Int),...".

My intuition is telling me I should probably use reflection, but I can't figure out how to do it exactly. Any pointer?

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
F.X.
  • 6,809
  • 3
  • 49
  • 71
  • my answer should warn you that there is a major flaw in your design when you encounter these problems. Can you clarify where does the List [(String,Any)] come from? – Edmondo Apr 03 '13 at 08:53

2 Answers2

1

The type of your list is too imprecise. ContentValues.put has overloads for a number of types, but they are all specific (Integer, Float, etc.), and no alternative for Object.

You can:

  • make the list type more precise, in case the list has only elements of one type (say, Int).
  • use an HList, but beware of type wizardry. It may be overkill in this case
  • as a last resort, do a type test:

    for ((k, v) <- a) v match {
      case n: Int => cv.put(k, v)
      case d: Double => cv.put(k, d)
      //...
    }
    
Iulian Dragos
  • 5,692
  • 23
  • 31
  • So you're saying there's no way (some kind of `resolve` method) I can use to narrow down the type of an `Any` object? Ah, well, nice tip for the type test though, I didn't think about that! – F.X. Apr 03 '13 at 08:40
  • You can always use a cast. But it may fail at runtime. The type system only knows as much as you tell it. – Iulian Dragos Apr 16 '13 at 21:50
  • Yes, if I wanted to use a cast I'd go back to Java. I wanted to solve this the Scala way. Well, no matter for now, I solved the issue in another way. – F.X. Apr 17 '13 at 06:55
1

This is a very famous and common problem in Scala. The type system works correctly, and developers are simply not used to it.

In strongly typed programming languages the compiler verifies rules on the types you are using and this prevents painful runtime errors. If you use reflection or casts you are allowed to force the type system and this can produce unexpected errors and problems at runtime.

Why would you want to break the rules which you largely benefit from ? A good reason is when you are designing a library and you know exactly what is going to happen in your internals (see scala collections).

When you end up using types such as Any or AnyRef you should be worried and ask yourself:

  • why I am going so up in the hierarchy ?
  • Am I probably using an anti pattern or a bad constructor for a strongly typed programming language?

In fact I guess you are, and I propose we further investigate together why you have a List[(String,Any)]. Let's assume you had no problems in putting data into the ContentValues , what if later you would need to extract something from there? How would you know if it was an Int, a Double, a Float?

Edmondo
  • 19,559
  • 13
  • 62
  • 115
  • `ContentValues` have a couple of `getAsString`, `getAsFloat`,... methods, so there "shouldn't be any issues" (famous last words, I know!). But that's an interesting point you make, I might have to rethink what I am doing, the fault might lie with my use of Java reflection and trying to force the type system. Which, as you rightfully point out, is bad practice. @Iulian's answer is a great practical solution in the meantime, but I'll look a little more into it! – F.X. Apr 03 '13 at 09:02
  • The problem is, for a given key, how do you get it back from the ContentValues? How do you know if you should call getAsString, getAsFloat, etc? – Edmondo Apr 03 '13 at 09:19
  • Mostly this was just me trying to learn Scala, so I didn't think that far away. I'm trying to figure out a way to do that better with full-Scala reflection ;) – F.X. Apr 03 '13 at 09:28
  • Even better, this is an excellent use case for Scala implicits. What you need is an implicit adapter :))) – Edmondo Apr 03 '13 at 09:42
  • Hm, I can't see how implicits would help me in that case. How would you do it? – F.X. Apr 03 '13 at 09:48