New to Scala, but experienced in C++ I’m trying to implement (possibly misguidedly) a small library on top of the sqlite4java library to allow me to auto-fill tuples of abritrary type from query rows (rows whose column types are each compatible with the respective tuple element type).
In C++ I normally implement this using boost::tuples and compile-time template recursion (terminated using template specialisation as shown below). Boost tuples are implemented very similarly to Haskell HLists. The pattern would be (assuming, for simplicity that the query is returned as vector of strings):
template<typename T1, typename T2>
void populateTuple( boost::tuples::cons<T1, T2>& tupleRec, int index, const std::vector<std::string>& vals )
{
tupleRec.head = boost::lexical_cast<T1>( vals[index] );
populateTuple( tupleRec.tail, index+1, vals );
}
template<typename T>
void populateTuple( boost::tuples::cons<T, boost::tuples::null_type>& tupleRec, int index, const std::vector<std::string>& vals )
{
tupleRec.head = boost::lexical_cast<T>( vals[index] );
}
(Apologies – I’ve not run the above through a compiler, but am hoping it shows what I mean)
I’d love to be able to do something similar with Scala. I can recurse over a general Tuple type via the Product trait – and get the type of each element at run time using pattern matching (for the small number of column types I support). However I haven’t found a way to assign Tuple elements via the product trait. And to be honest, I’m not convinced that this is a particularly nice or idiomatic way to do what I require anyway.
But something like:
val returnedFromQuery = List[String]( "Hello", "4", "6.0" )
val rowAsTuples = interpretListAsTuple[(String, Int, Float)]( returnedFromQuery )
Where rowAsTuples has type (String, Int, Float). Again, please excuse any syntax errors.
Anyone have any thoughts? Or alternative suggestions? In advance – I’m not interested in any higher-level SQL query libraries. I’m happy with sqlite4java but want to wrap it with a simple more abstract interface.
I think you should try using pattern-matching instead of interpretation. First, we need something that will pull out our types from strings using
unapply:Now we can use them in pattern matches:
Note that if you do it this way, you (1) don’t have to return tuples if you don’t want to; (2) have access to all the parsed out variables right away; (3) have automatic error checking built in (with options).