New clr.ImportExtensions (LINQ) Syntax

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

New clr.ImportExtensions (LINQ) Syntax

Dave Wald
Hi all - I've been experimenting with with the new extension method import facility and so far it is working well, more or less as I expected, except that I'm getting an error message when I try to chain Linq method calls. I don't know whether this should be considered a bug or not. It seems the dynamic code cannot pass the intermediate enumerable (iterator/generator?) object between method calls. I have to wrap it in a list(...) call for it to work. And I would have thought .ToList() would work, but it blows too.
I don't know enough about the internals to judge whether it's even possible for the DLR to do this. The exception seems to be coming from DLR code.
Would be nice if the chained syntax could be made to work, tho. But even as it is, it still allows much cleaner code style than my homebrew module did.
Ideas? Enlightenment?

Thanks

Here's the code:

import clr
clr.AddReference("System.Core")
import System
from System import Linq

clr.ImportExtensions(Linq)

class Product(object):
    def __init__(self, cat, id, qtyOnHand ):
        self.Cat = cat
        self.ID = id
        self.QtyOnHand = qtyOnHand
        self.Q = self.QtyOnHand
       
def runit():
    products = [Product(prod[0], prod[1], prod[2]) for prod in
        ('DrillRod', 'DR123', 45), ('Flange', 'F423', 12), ('Gizmo', 'G9872', 214), ('Sprocket', 'S534', 42)]
       
    # pd = products.Where(lambda prod: prod.Q < 40).Select(lambda prod: (prod.Cat, prod.ID) )
    # blows: "Type System.Collections.Generic.IEnumerable`1[TSource] contains generic parameters"
   
    # pd = products.Where(lambda prod: prod.Q < 40).AsEnumerable().Select(lambda prod: (prod.Cat, prod.ID) )
    #blows, same exception
   
    pd = products.Where(lambda prod: prod.Q < 40)               #ok
    for prod in pd: print prod.Cat, prod.ID, prod.Q                     #==> Flange F423 12
       
    # pd2 = pd.Select(lambda prod: (prod.Cat, prod.ID) )        #blows, same exception - note source (pd) is not a list at this point - it's a ...+WhereEnumerator... object
   
    pd2 = products.Select(lambda prod: (prod.Cat, prod.ID) )    #ok
    for prod in pd2: print "Cat: {0}, ID: {1}".format(prod[0], prod[1])         #==> Cat: DrillRod, ID: DR123 ...
   
    pd2 = list(pd).Select(lambda prod: (prod.Cat, prod.ID) )    #ok                Wrapping it in a list
    for prod in pd2: print "Cat: {0}, ID: {1}".format(prod[0], prod[1])         #==> Cat: Flange, ID: F423
      
    # pd = products.Where(lambda prod: prod.Q < 30).ToList()    #blows, same exception

    pd = list( products.Where(lambda prod: prod.Q < 30) )       #ok
    for prod in pd2: print "Cat: {0}, ID: {1}".format(prod[0], prod[1])         #==> Cat: Flange, ID: F423

    # ok
    pd = list( products.Where(lambda prod: prod.Q < 40) ).Select(lambda prod: "Cat: {0}, ID: {1}, Qty: {2}".format(prod.Cat, prod.ID, prod.Q))
    for prod in pd: print prod      #==> Cat: Flange, ID: F423, Qty: 12
   
    # ok
    pd = ( list(products.Where(lambda prod: prod.Q < 40))
            .Select(lambda prod: "Cat: {0}, ID: {1}, Qty: {2}".format(prod.Cat, prod.ID, prod.Q)) )
    for prod in pd: print prod      #==> Cat: Flange, ID: F423, Qty: 12

if __name__ == "__main__":
    runit()
-------------------------------------------------------------------------------------------------------------------------

Here's the barf:

System.ArgumentException was unhandled by user code
  Message=Type System.Collections.Generic.IEnumerable`1[TSource] contains generic parameters
  Source=System.Core
  StackTrace:
       at System.Dynamic.Utils.TypeUtils.ValidateType(Type type)
       at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
       at Microsoft.Scripting.Ast.Utils.Convert(Expression expression, Type type)
       at IronPython.Runtime.Binding.MetaBuiltinFunction.GetInstance(Expression instance, Type testType)
       at IronPython.Runtime.Binding.MetaBuiltinFunction.MakeSelfCall(DynamicMetaObjectBinder call, Expression codeContext, DynamicMetaObject[] args)
       at IronPython.Runtime.Binding.MetaBuiltinFunction.InvokeWorker(DynamicMetaObjectBinder call, Expression codeContext, DynamicMetaObject[] args)
       at IronPython.Runtime.Binding.MetaBuiltinFunction.Invoke(PythonInvokeBinder pythonInvoke, Expression codeContext, DynamicMetaObject target, DynamicMetaObject[] args)
       at IronPython.Runtime.Binding.PythonInvokeBinder.BindWorker(DynamicMetaObject context, DynamicMetaObject target, DynamicMetaObject[] args)
       at IronPython.Runtime.Binding.PythonInvokeBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args)
       at Microsoft.Scripting.Utils.DynamicUtils.GenericInterpretedBinder`1.Bind(DynamicMetaObjectBinder binder, Int32 compilationThreshold, Object[] args)
       at Microsoft.Scripting.Utils.DynamicUtils.LightBind[T](DynamicMetaObjectBinder binder, Object[] args, Int32 compilationThreshold)
       at IronPython.Runtime.Types.BuiltinFunction.IronPython.Runtime.Binding.IFastInvokable.MakeInvokeBinding[T](CallSite`1 site, PythonInvokeBinder binder, CodeContext state, Object[] args)
       at IronPython.Runtime.Binding.PythonInvokeBinder.BindDelegate[T](CallSite`1 site, Object[] args)
       at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
       at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
       at Test_CLR_ImportExtensions$2.runit$80(PythonFunction $function) in C:\IPy27_Projects\IPy_LINQ1\IPy_LINQ1\Test_CLR_ImportExtensions.py:line 131
       at IronPython.Runtime.PythonFunction.FunctionCaller.Call0(CallSite site, CodeContext context, Object func)
       at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
       at __main__$1.__main__(FunctionCode $functionCode) in C:\IPy27_Projects\IPy_LINQ1\IPy_LINQ1\Main.py:line 21
       at IronPython.Compiler.RuntimeScriptCode.InvokeTarget(Scope scope)
       at IronPython.Compiler.RuntimeScriptCode.Run(Scope scope)
       at IronPython.Hosting.PythonCommandLine.RunFileWorker(String fileName)
       at IronPython.Hosting.PythonCommandLine.RunFile(String fileName)
  InnerException:  (nothing after this)







_______________________________________________
Users mailing list
[hidden email]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
Reply | Threaded
Open this post in threaded view
|

Re: New clr.ImportExtensions (LINQ) Syntax

Dave Wald
Okay. Never mind. There's already an open bug for this I just found.

http://ironpython.codeplex.com/workitem/30379

_______________________________________________
Users mailing list
[hidden email]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
Reply | Threaded
Open this post in threaded view
|

Re: New clr.ImportExtensions (LINQ) Syntax

Dino Viehland
Dave wrote:
> Okay. Never mind. There's already an open bug for this I just found.
>
> http://ironpython.codeplex.com/workitem/30379

I've assigned this bug to myself.  I'll take a look and fix it, my guess is
there's something wrong with extension method support on generic
classes (e.g. class Foo<T> : IEnumerable<T>) that needs to be fixed in our
type inferer.


_______________________________________________
Users mailing list
[hidden email]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
Reply | Threaded
Open this post in threaded view
|

Re: New clr.ImportExtensions (LINQ) Syntax

Dave Wald
Very good. Thanks so much Dino!

On 4/11/2011 9:25 PM, Dino Viehland wrote:

> Dave wrote:
>> Okay. Never mind. There's already an open bug for this I just found.
>>
>> http://ironpython.codeplex.com/workitem/30379
> I've assigned this bug to myself.  I'll take a look and fix it, my guess is
> there's something wrong with extension method support on generic
> classes (e.g. class Foo<T>  : IEnumerable<T>) that needs to be fixed in our
> type inferer.
>
>
> _______________________________________________
> Users mailing list
> [hidden email]
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>

_______________________________________________
Users mailing list
[hidden email]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com