[IronPython] LINQ from IronPython

Dino Viehland dinov at microsoft.com
Tue Dec 22 22:39:57 CET 2009


Jeff wrote:
> I would guess that most of those lambdas are going to be fairly
> simple, and hopefully easy to type-infer. For ones that aren't
> inferable, the best option would be to give an error.
> 
> Given:
>     id = 1
>     customers.Where(lambda c: c.Id == id)
> 
> Would IronPython be able to know that the type of `id` is `int` at the
> appropriate stage of the compiler? Presumably, because it would have
> to know the type of `customers` (and thus `c`) to even apply the
> extension methods. Would it even have to know the type of `id` to
> construct the proper expression tree, given that it knows the type of
> `c`?
> 
> This rabbit hole goes surprisingly deep! No wonder you haven't tackled
> it yet.

We would know customers when we bind the GetMember and find the extension
method.  That'd give us a method Where which is actually:

Queryable.Where[Customer](IQueryable[Customer], Expression<Func<Customer, bool>>)

Then when we invoke that we would know what we're converting the lambda to and 
that its signature needs to take a Customer.  That's when any type inference over
the lambda would kick in.  I think our existing type inference would be pretty close
to getting that right, we just need to look for Expression<T> in addition to
delegate types.  

So that gives us c.Id's type and you could imagine that we then require the 
LHS & RHS types for equality to line up.  Another option is that we might 
be able to generate code that looks something like:

	if (id is int) {	
		return c.Id == (int)id;
	} else {
		return Expression.Equal(c.Id, id, PythonOps.EqualRetBool(c.Id, id));
 	}

The equality here is something that might pass over the wire fine as this is
a pattern that existed in expression trees V1.  All of the dynamic stuff would
be hidden in the EqualRetBool call and hopefully we'd just never hit that
code path.  But even if we did it might just get interpreted as equality instead
of a method call.

The really interesting thing to me is that this is a closure - either id is in
a nested function scope or it's in a global scope.  I'm not sure how that gets
transmitted across the wire.  Do closures work in LINQ in C# going across to
a database?



More information about the Ironpython-users mailing list