Extract function name from a function - c#

How can I create a function called getFuncName that takes a function of type (unit -> 'a) and returns its name.
I was talking to one of the C# devs and they said you could use the .Method property on a Func type as shown in an example here.
I tried to convert this to F# :
for example convert (unit -> 'a) to a type Func<_> then call the property on it but it always returns the string "Invoke".
let getFuncName f =
let fFunc = System.Func<_>(fun _ -> f())
fFunc.Method.Name
let customFunc() = 1.0
// Returns "Invoke" but I want it to return "customFunc"
getFuncName customFunc
A bit of background to this problem is:
I have created an array of functions of type (unit -> Deedle.Frame). I now want to cycle through those functions invoking them and saving them to csv with the csv name having the same name as the function. Some hypothetical code is below:
let generators : (unit -> Frame<int, string>) array = ...
generators
|> Array.iter (fun generator -> generator().SaveCsv(sprintf "%s\%s.csv" __SOURCE_DIRECTORY__ (getFuncName generator)))
This is being used in a scripting sense rather than as application code.

Not sure how you searched for information, but the first query to the search engine gave me this response:
let getFuncName f =
let type' = f.GetType()
let method' = type'.GetMethods() |> Array.find (fun m -> m.Name="Invoke")
let il = method'.GetMethodBody().GetILAsByteArray()
let methodCodes = [byte OpCodes.Call.Value;byte OpCodes.Callvirt.Value]
let position = il |> Array.findIndex(fun x -> methodCodes |> List.exists ((=)x))
let metadataToken = BitConverter.ToInt32(il, position+1)
let actualMethod = type'.Module.ResolveMethod metadataToken
actualMethod.Name
Unfortunately, this code only works when F# compiler does not inline function body into calling method.
Taken from here
Although there may be a more simple way.

Related

C# - F# interoperability, how to get result instead of FSharpFunc

I'm learning F# and would like to write simple F# library which can be consumed from C# application. It works as expected for trivial F# functions e.g.
let Square x = x * x
From C# I can consume it and get the expected value:
var sqaredNumber = MyFSharpLibrary.Square(5);
However when I use a Sequence / IEnumerable<T> as function parameter I got FSharpFunc object instead of the result.
Here is my function:
let FilterEvenNumbers input = Seq.filter(fun x -> x % 2 = 0)
And this is how I try to use it from C# code:
var numbers = new int[] { 1, 2, 3, 4 };
var filteredNumbers = MyFSharpLibrary.FilterEvenNumbers(numbers);
Instead of value filteredNumbers contains FSharpFunc object. I could use method Invoke on that object but would like to avoid extra complexity.
How can I achieve that ?
This is because your function declaration returns a function. If you enter it into dotnet fsi you'll see the signature:
val FilterEvenNumbers: input: 'a -> (seq<int> -> seq<int>)
See the parentheses? That means a single FSharpFunc object is returned, and it is the function that you call with input.
As you can see, input isn't passed to the filtering function, nor is its type associated at all with the inferred parameterized types for Seq.
To fix this, you need to pass input to Seq.filter.

Methods for dynamically creating an array in C#

First, I don't have much experience in .Net - especially within the last 7 years.
I'm trying to develop an application and would to incorporate another library (https://github.com/Giorgi/Math-Expression-Evaluator)
That library allows me to evaluate math expressions like Evaluate("a+b", a: 1,b: 1). The method signature is public decimal Evaluate(string expression, object argument = null)
I would like to understand better how .Net translates comma-separated arguments into a single "argument".
I'm not sure how to create that argument dynamically.. for example, iterating through a list of values and creating an object that will match the appropriate argument for that signature.
I'm really just looking for pointers for documentation and more information.. Thanks for anything.
EDIT: Sorry.. purposely left it broad because I wasn't looking for people to do my work for me.. just can't seem to find a starting point to do my own research.
The method is called like
dynamic engine = new ExpressionEvaluator() ;
engine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6)) ;
In the body of Evalute() is this code (which turns that argument into a Dictionary of String, Decimal pairs.
if (argument == null)
{
return new Dictionary<string, decimal>();
}
var argumentType = argument.GetType();
var properties = argumentType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && IsNumeric(p.PropertyType));
var arguments = properties.ToDictionary(property => property.Name,
property => Convert.ToDecimal(property.GetValue(argument, null)));
return arguments;
What I'd like to be able to do is parse a String like "a:1,b:2" and turn it into an object that matches that Evaluate() signature.
That library is using high level magic... Very high level :-)
The trick is that the class is declared as:
public class ExpressionEvaluator : DynamicObject
So it is a class that implements the dynamic magic introduced in .NET 4.0
Now... In the class there are two Evaluate methods:
public decimal Evaluate(string expression, object argument = null)
and
private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
The only method normally visible and usable is the first one. It is used like:
engine.Evaluate("a + b + c", new { a = 1, b = 2, c = 3 });
The new { ... } creates an anonymous object, that is then "unpacked" here through the use of reflection to a Dictionary<string, decimal> to be fed to the private Evaluate().
If you try to use the other notation, the one like:
engine.Evaluate("a + b + c", a: 1, b: 2, c: 3 });
then the .NET can't match the method to the public Evaluate() that is present, but the class, being a subclass of DynamicObject, causes the C# compiler to write some "magic" code that launches this method (that is still implemented by the ExpressionEvaluator):
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
That first checks that we want to call Evaluate:
if (nameof(Evaluate) != binder.Name)
and if we are trying to call Evaluate, it unpacks the parameters to a new Dictionary<string, decimal>() and then calls the private Evaluate().
As a sidenote, to use the "dynamic" way of writing Evaluate you have to declare the engine variable like;
dynamic dynamicEngine = new ExpressionEvaluator();
So using the dynamic variable type.
Now... As the library is written you can:
Use an anonymous object, with the problem that anonymous objects must have their "shape" defined at compile time (so at compile time you must know that you will need a a, a b and a c. You can't need a d at runtime if you didn't create a new { a, b, c, d } at compile time). See for example a response I gave three years ago about how to create dynamic anonymous types at runtime. One of the reasons I gave for that block of code was:
there are parts of the .NET framework that heavily use reflection to render objects (for example all the various datagrids). These parts are incompatible with dynamic objects and often don't support object[]. A solution is often to encapsulate the data in a DataTable... or you can use this :-)
Note that in one of the comments to that response there is a link to a modified version of my code used by one of the many implementations of Dynamic.Linq.
Use a non-anonymous object (a new Foo { a = 1, b = 2 c = 3 }). The library doesn't make distinctions between anonymous and non-anonymous objects. So same limitation as before, because at compile time you need a Foo class with the right number of parameters
Use the dynamic notation. Sadly even that is quite static. You can't easily add new parameters, that for the number and name of the "variables" must be defined at compile time.
A possible solution is to modify the source code (it is a single file) and make public this method:
private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
then you can easily and dynamically populate the Dictionary<string, decimal> arguments

Pattern matching F# type in a C# code

Suppose there is a F# definitions:
type Either<'a,'b> = | Left of 'a | Right of 'b
let f (i : int) : Either<int, string> =
if i > 0
then Left i
else Right "nothing"
Function f is used in C# code:
var a = Library.f(5);
How the result value a could be pattern matched for data constructors? Something like:
/*
(if a is Left x)
do something with x
(if a is Right y)
do something with y
*/
Using F# discriminated unions from C# is a bit inelegant, because of how they are compiled.
I think the best approach is to define some members (on the F# side) that will simplify using the types from C#. There are multiple options, but the one I prefer is to define TryLeft and TryRight methods that behave similarly to Int32.TryParse (and so they should be familiar to C# developers using your F# API):
open System.Runtime.InteropServices
type Either<'a,'b> =
| Left of 'a
| Right of 'b
member x.TryLeft([<Out>] a:byref<'a>) =
match x with Left v -> a <- v; true | _ -> false
member x.TryRight([<Out>] b:byref<'b>) =
match x with Right v -> b <- v; true | _ -> false
Then you can use the type from C# as follows:
int a;
string s;
if (v.TryLeft(out a)) Console.WriteLine("Number: {0}", a);
else if (v.TryRight(out s)) Console.WriteLine("String: {0}", s);
You lose some of the F# safety by doing this, but that's expected in a language without pattern matching. But the good thing is that anybody familiar with .NET should be able to use the API implemented in F#.
Another alternative would be to define member Match that takes Func<'a> and Func<'b> delegates and invokes the right delegate with the value carried by left/right case. This is a bit nicer from the functional perspective, but it might be less obvious to C# callers.
I'd define a Match member taking the delegates to execute in each scenario. In F# you'd do it like this (but you could do something equivalent in a C# extension method, if desired):
type Either<'a,'b> = | Left of 'a | Right of 'b
with
member this.Match<'t>(ifLeft:System.Func<'a,'t>, ifRight:System.Func<'b,'t>) =
match this with
| Left a -> ifLeft.Invoke a
| Right b -> ifRight.Invoke b
Now you should be able to do something like this in C#:
var result = a.Match(ifLeft: x => x + 1, ifRight: y => 2 * y);
From the 3.0 spec:
8.5.4 Compiled Form of Union Types for Use from Other CLI Languages
A compiled union type U has:
One CLI static getter property U.C for each null union case C. This property gets a singleton object that represents each such case.
One CLI nested type U.C for each non-null union case C. This type has instance properties Item1, Item2.... for each field of the union
case, or a single instance property Item if there is only one field.
However, a compiled union type that has only one case does not have a
nested type. Instead, the union type itself plays the role of the case
type.
One CLI static method U.NewC for each non-null union case C. This method constructs an object for that case.
One CLI instance property U.IsC for each case C. This property returns true or false for the case.
One CLI instance property U.Tag for each case C. This property fetches or computes an integer tag corresponding to the case.
If U has more than one case, it has one CLI nested type U.Tags. The U.Tags typecontains one integer literal for each case, in increasing
order starting from zero.
A compiled union type has the methods that are required to implement its auto-generated interfaces, in addition to any
user-defined properties or methods.
These methods and properties may not be used directly from F#.
However, these types have user-facing List.Empty, List.Cons,
Option.None, and Option.Some properties and/or methods.
A compiled union type may not be used as a base type in another CLI
language, because it has at least one assembly-private constructor and
no public constructors.
If you can't change the F# api, using points 2 and 4 above you could do it something like this:
C#
class Program
{
static void Main(string[] args)
{
PrintToConsole("5");
PrintToConsole("test");
}
static void PrintToConsole(string value)
{
var result = test.getResult(value);
if (result.IsIntValue) Console.WriteLine("Is Int: " + ((test.DUForCSharp.IntValue)result).Item);
else Console.WriteLine("Is Not Int: " + ((test.DUForCSharp.StringValue)result).Item);
}
}
F#
namespace Library1
module test =
open System
type DUForCSharp =
| IntValue of int
| StringValue of string
let getResult x =
match Int32.TryParse x with
| true, value -> IntValue(value)
| _ -> StringValue(x)
This solution is convenient in that it also handles tuple DU cases by creating a new property for each item in the tuple.

F# discriminated unions versus C# class hierarchies

I have the following code:
public abstract class A ...
public class B : A ...
public class C : A ...
void my_fct(A x) {
if (x is B) { block_1 }
else if (x is C) { block_2 }
else { block_3 }
}
and I wonder if it is a good translation from F#
type a = B | C
let my_fct x =
match x with
| B -> ( block_1 )
| C -> ( block_2 )
| _ -> ( block_3 )
??
F# discriminated unions correspond to OO class hierarchies quite closely, so this is probably the best option. The most notable difference is that you cannot add new cases to a discriminated union without modifying the type declaration. On the other hand, you can easily add new functions that work with the type (which roughly corresponds to adding new virtual methods in C#).
So, if you don't expect to add new inherited classes (cases), then this is the best option. Otherwise, you may use F# object types (or other options, depending on the scenario).
One more point regarding your code - since you cannot add new cases, F# compiler knows that the only cases you need are for B and C. As a result, the block_3 can never be executed, which means that you can write just:
let my_fct x =
match x with
| B -> ( block_1 )
| C -> ( block_2 )
yes this is more or less the same as F# does anyhow.
In this case (no values added) - F# seems to translate this into a classs for "a" and some Tags (enumeration). The class for "a" just has some static properties for B and C, and some methods to check if an object of type "a" is "B" or "C" (see below)
But you don't need the "_ -> (block_3)" case, because this can never be matched (F# knows all the possible cases and will warn you).
I think it's better if you throw an exception in C# for this "else" case.

FSharpChoice in C#

I am trying to use FSharpChoice type in a C# project. I have created a choice like so
var a = FSharpChoice<T1,T2,T3>.NewChoice1Of3(instofT1);
now how do I get instofT1 out of the choice type.
I see I can do a IsChoice1Of3 but how do i get to the value in the choice object?
I probably wouldn't use the type directly from C# - you can do that, but the resulting code won't be very nice. I'd probably declare my own Choice type that would look like this:
type Choice<'T1, 'T2> private (opt1, opt2) =
member x.TryGetChoice1Of2(arg:byref<'T1>) = //'
match opt1 with
| Some v -> arg <- v; true
| _ -> false
// Similar code for 'TryGetChoice2Of2'
type Choice = // static methods for creating (Choice1Of2, ...)
This uses byref parameters which appear as out parameters in C#, so you could write:
int num;
string str;
if (choice.TryGetChoice1Of2(out num)) // ...
else if (choice.TryGetChoice2Of2(out str)) // ...
else // assert(false)
This is definitely more pleasant way of working with the type from C# (and it uses pattern familiar from, for example, working with Int32.TryParse).
Cast the value to FSharpChoice<T1,T2,T3>.Choice1Of3 and use the Item property.
See Compiled Form of Union Types for Use from Other CLI Languages in the F# spec for more information about how discriminated unions are represented.
I recently started a project to make a "compatibility layer" so that FSharp.Core can be more easily consumed from C#. In particular, it makes generic discriminated unions usable from C#, for example:
var choice = Choice.New1Of3<int,string,string>(100);
int r = choice.Match(i => i + 21, s => s.Length + 1, s => s.Length + 5);
This does pattern matching on the discriminated union, similarly to how you would do it in F#, except there are no names.

Categories

Resources