Most information about this topic can be found by looking at the code generated by the F# compiler, using tools like ILDASM or Reflector. Also the F# from C# section of the F# 1.1.12 documentation is very helpful.
FSharp.Code library
In order to call some F# basic functionality we need to add a reference to
FSharp.Core
.Python
import clr
clr.AddReference('FSharp.Core')
Type parameters
IronPython provides a way to specify type parameters to methods and classes by using square brackets followed by the names of the types to be used. This mechanism can be used to create F# constructs that require them.
The following example shows how to create an F# list:
Python
>>> import clr
>>> clr.AddReference('FSharp.Core')
>>> from Microsoft.FSharp.Collections import List
>>> l1 = List[str].Cons('World',List[str].Empty)
>>> l2 = List[str].Cons('Hello',l1)
>>> " ".join(l2)
'Hello World'
Type parameters, for methods that require them, also can be specified using the same syntax. For example the following code shows the use of
Seq.length
with an Python sequence.Python
print Seq.length[int]([45,234,52,345,2,346,657])
Tuples
Tuples in F# are instances of the
Microsoft.FSharp.Core.Tuple
class (with several definitions with depending on the number of arguments). A tuple instance contains properties Item#
where # is the position of the element.The following example shows how to use a tuple created in F# from IronPython.
F#
module MyFunctions = begin
...
let numberEvenTest x = x,x % 2 = 0
...
end
Python
print MyFunctions.numberEvenTest(46)
print MyFunctions.numberEvenTest(46).Item1
print MyFunctions.numberEvenTest(46).Item2
This program will print:
(46,True)
46
True
To create a tuple inside IronPython the
Tuple[type1,type2,...](value1,value2,...)
constructor must be used. For example to given the following definition:
F#
module MyFunctions = begin
...
let movePoints points xdistance ydistance =
Seq.map (fun (x,y) -> (x+xdistance,y+ydistance)) points
...
end
We can used from IronPython like this:
Python
from Microsoft.FSharp.Core import Tuple
...
points = [ Tuple[int,int](1,2), Tuple[int,int](5,3) ]
for p in MyFunctions.movePoints(points,20,40):
print p
It is tempting to use the Python syntax for assigning a list of variables to the values of the tuples. For example:
x,y,z = 2,3,5
However this is not possible since F# tuples are not compatible with IronPython sequences.
Operators
F# operators are created using the same conventions as the C# operators. Thus they can be used directly in IronPython.
For example the following F# definition:
type Complex(real:double,img:double) = class
member this.real with get() = real
member this.img with get() = img
static member (+) (c1:Complex,c2:Complex) =
Complex(c1.real+c2.real,c1.img+c2.img)
override this.ToString() = sprintf "%f + %fi" real img
end
Can be used in IronPython:
Python
c1 = Complex(20,234)
c2 = Complex(34.35,32.2)
c3 = (c1+c2)
Discriminated unions
Discriminated unions in F# provide a compact way to define data structures. The following example shows the definition of simple math expressions that include addition, subtraction and numeric literals.
F#
type MathExpr =
| Addition of MathExpr * MathExpr
| Subtraction of MathExpr * MathExpr
| Literal of double
The following code snippet shows how to create instance of these math expression elements from IronPython.
Python
expr = MathExpr.Addition(MathExpr.Literal(10),\
MathExpr.Subtraction(\
MathExpr.Literal(40), \
MathExpr.Literal(24)))
A instance of the discriminated union has methods IsXXXX to verify the kind. Also properties a generated with the name of the constructor followed by a number (for example Addition1) to access values given to the constructor.
The following example shows how to evaluate a math expression.
Python
def evalExpr(expr):
if expr.IsAddition():
return evalExpr(expr.Addition1) + evalExpr(expr.Addition2)
elif expr.IsSubtraction():
return evalExpr(expr.Subtraction1) - evalExpr(expr.Subtraction2)
else:
return expr.Literal1
Functions
Functions passed as parameters need to be converted to a special F# element that represent them. In order to do this the FuncConvert.ToFastFunc function is used.
For example the following code shows how to call
Seq.iter
to print all the elements of a Python list.
from Microsoft.FSharp.Core import FuncConvert
...
aList = [5,3,42,6]
def foo(x):
print(x)
Seq.iter[int](FuncConvert.ToFastFunc[int]( foo),aList)
Since IronPython and F# use IEnumerable<T> types to represent collections and sequences we can use F# functions to manipulate IronPython collections.
For example given the following definition of a Python generator for Fibonacci numbers:
def fibo():
last1 = 0
last2 = 1
while True:
yield last1
next = last1+last2
last2 = last1
last1 = next
We can call F# functions to process values generated by
fibo
. For example the following IronPython code prints the first 15 squared Fibonacci numbers.
for n in Seq.map[int,int]( FuncConvert.ToFastFunc[int,int](lambda x: x*x) ,\
Seq.take[int](15,fibo())):
print n
Code for this post was created using IronPython 2.0 and F# 1.9.6.2 .