[IronPython] New clr.ImportExtensions (LINQ) Syntax
Dave Wald
davew252 at tx.rr.com
Sat Apr 9 05:04:37 CEST 2011
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)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20110408/2a53f9b2/attachment.html>
More information about the Ironpython-users
mailing list