[Ironpython-users] Passing an IronPython function to C#

Doug Blank doug.blank at gmail.com
Sun Mar 18 01:16:19 CET 2012


On Sat, Mar 17, 2012 at 6:51 PM, Dino Viehland <dinov at microsoft.com> wrote:
>
>
> Jeff wrote:
>> IronPython's conversion code is, um, interesting -- Dino might understand it all,
>> but I don't know if anyone else does -- so it's possible two different sets of
>> conversions are being chosen. Now, this
>> *shouldn't* be the case, but it's my hypothesis.
>
> Ha!  Overload resolution is like Conway's game of life, you can know the rules,
> but knowing the behavior is another time entirely...  Luckily this doesn't so much deal with
> that rather than how our IList<T> wrapper is implemented in ConversionWrappers.cs.
> The indexer is just doing a C# cast from the value to the T type.  That could easily
> be changed to do a full Python conversion.
>
> I think doing an is check first and only doing the conversion if it's not already the proper
> type would be an alright change.  But it could be a little surprising in that sometimes you
> could get a new instance each time you access an element (e.g. a new delegate could be
> created each time).

Thanks for the hints! I was able to get the functionality I was
seeking. Here is the relevant code I ended up with:

	public static List doTogether (IList<dynamic> functions)
	{
		foreach (dynamic function in functions) {
			Func<object> func =
IronPython.Runtime.Converter.Convert<Func<object>>(function);
        ...

I need to do some more testing to make sure that this will always do
the right thing. For example, I would want this function to be able to
take, say, an IronRuby function and coerce it into the correct type as
well.

It does seem like these two functions should behave similarly:

public void function1(params Func<object> [] functions) {
    foreach (Func<object> function in functions) {
        function();
    }
}
public void function2(IList<Func<object>> functions) {
    foreach (Func<object> function in functions) {
        function();
    }
}

[I'll put that in the issue tracker and y'all can decide what the best
thing to do is.]

FYI, the interface I was working on was an easy way for users to run
code in parallel (using Threads from behind). The function
doTogether() (based on an Alice block of the same name) now allows the
following:

doTogether(f1, f2, ...): will run f1(), f2() at the same time and
return their results in a list
doTogether([f1, f2, ...], arg): will run f1(arg), f2(arg) at the same
and return their results in a list
doTogether(f1, [arg1, arg2, ...]): will run f1(arg1), f1(arg2) at the
same time and return their results in a list
doTogether([f1, arg1, ...], [f2, arg2, ...], ...): will run f1(arg1),
f2(arg2) at the same time and return their results in a list

I've used this in class to compose music (each function is an
instrument), robot dancing (each argument is a robot), and parallel
computation, among other mundane uses (such as initialize a bunch of
serial ports in parallel). (The last example there would look better
with lambdas (making a "thunk" in Scheme lingo) and then using the
first example, but we're trying to allow some flexibility in when we
must introduce additional concepts.) Full code available in the Myro
library [1].

Thanks again!

-Doug

[1] - http://svn.cs.brynmawr.edu/viewvc/Calico/trunk/modules/Myro/Myro.cs


More information about the Ironpython-users mailing list