> Hi,
>
> I try to make a smale helper api in Yeti for mongo-db (http://
> www.mongodb.org/). What I tried is to load a data item
> (com.mongodb.DBObject) and convert it (untyped) into a
> yeti.lang.GenericStruct and than cast this struct to the right type.
> Ie:
>
>> dbo is ~com.mongodb.DBObject = //somehow query the database
>> conv is ~yeti.lang.GenericStruct = fromDBObject dbo; //helper method to convert the mongo DBObject to a ~Struct
>> customer = conv unsafely_as {name is string, age is number ...} //casting the struct to what is expected.
>
> I have two questions:
> 1.) Generally do you think this is a viable approach (making a
> GenericStruct and than requiring the user to cast it)
Well... possible, but it isn't the prettiest one. ;)
One thing - fromDBObject could return 'a (unsafely_as 'a),
at least the code would be nicer.
Alternative would be creating a wrapper that don't pretend knowing the
underlying type statically, similarly to peekObject. It would be
more verbose, but I think also more honest about it's nature.
customer = fromDBObject dbo;
name = customer.str 'name';
age = customer.num 'age';
Possibly unrelated - I have really old unimplemented idea about inbuilt
operator `struct`, that would create yeti structure wrapper for java-bean
like object. Like:
class X {
String getFoo();
}
---
x = new X();
y = struct x;
println y.foo;
> 2.) The compiler throws a "java.lang.RuntimeException: No className
> for Z" when compiling my "fromDBObject" function:
...
> Code: (using the mongo-db driver 2.0 rc 4 and the latest yeti from
> git)
...
> );
> //this is realy bad
> fa = array ( map do x: false done [0 .. hMap#size() - 1]);
> new GenericStruct(hMap, fa);
Seems that the stupid thing doesn't know how to convert array<boolean>
into ~boolean[] (Z is JVM notation for boolean).
I'll look into it, but few workarounds:
fa = new boolean[hMap#size()];
new GenericStruct(hMap, fa);
or...
new GenericStruct(hMap, ());
Also, \false is shorthand for do x: false done.
> For performance reasons I don't know wheter I should use a wrapper or
> straight functions, because the wrapper gets quite big. It has 20
> functions: 5 functions for the base values (str, num etc) and three
> times five functions for list, maybe and map (ie listStr, listNum,
> maybeStr, maybeNum, mapStr etc). So I currenlty use plain functins ie:
> bsonStr name dbObject.
You have kind of middle ground - use accessors that create the function
value only when asked.
$ yeti -e 'obj y = { get f () x = x + y }; (obj 1).f 2'
3
The compiler always generates a specialized class for structures
containing accessors - and then tries to inline the accessor functions
into it. The y captured by accessor closure will be stored in the
structure, but it will be shared by different accessors.
The function closure construction gets lifted from structure instance
creation time to the time when field value is asked (and it will be
recreated again each time the field is accessed). From performance view
point it's a tradeoff - some code will be faster this way, and some
slower.