Pages

Wednesday, August 22, 2012

F# Add Reference Addon

Recently we got a customer request to add reference to FSI. I get this feature working and another feature added. A "Scripts" folder is created which contains several .fsx files. See the screen shot below. These script files are generated to help to load the project references and project. Typically there are only Debug and Release configuration, if there is other configuration, a new set of files are generated. Auto update happens after each build. The content of these file are updated automatically. It can be download it from visual studio gallery.




c:\MyProjects\MyProject\Scripts\load-refs.fsx:

  #r "System.dll”
  #r "System.Xml.dll”
  #r @"c:\MyProjects\OtherProject\bin\Debug\OtherProject.dll”

c:\MyProjects\MyProject\Scripts\load-refs-release.fsx:

  #r "System.dll”
  #r "System.Xml.dll”
  #r @"c:\MyProjects\OtherProject\bin\Release\OtherProject.dll”

c:\MyProjects\MyProject\Scripts\load-proj.fsx:

  #load @"c:\MyProjects\MyProject\Scripts\load-refs.fsx”
  #r @"c:\MyProjects\MyProject\Debug\bin\MyProject.dll”

c:\MyProjects\MyProject\Scripts\load-proj-release.fsx:

  #load @"c:\MyProjects\MyProject\Scripts\load-refs-release.fsx”
  #r @"c:\MyProjects\MyProject\Release\bin\MyProject.dll”



Sunday, August 19, 2012

F# Extension Methods

The F# extension method is one of my favorite feature in F#.

F# method and property to be used inside F#

F# extension methods for F# is like 
[ < AutoOpen > ]
module ExtensionMethodsOnlyInFSharp =
    type System.String with
        member this.IsFSharp() = this = "F#"
        member this.``IsF#`` with get() = this = "F#"
And it can be invoked like:
    printfn "equal to F#? %A" ("F#".IsFSharp())
    printfn "equal to F#? %A" ("F#".``IsF#``)
The IsF# is a property. So F# can define extension property! 

F# method to be used in C#

The extension method needs for C# needs an attribute. [ < System.Runtime.CompilerServices.ExtensionAttribute > ]

The extension method defined in the F# can be used in C# is like:

[< System.Runtime.CompilerServices.ExtensionAttribute >]
[< AutoOpen >]
module ExtensionMethodForCSharp = 
    [< System.Runtime.CompilerServices.ExtensionAttribute >]
    let IsFSharp(str:string) = str = "F#"

    // not possible to access from C# IDE
    [< System.Runtime.CompilerServices.ExtensionAttribute >]
    let ``IsF#``(str:string) = IsFSharp str

F# extension methods on Array

F# can define the extension method on array generic (without specifying the concrete type for 'T). It is NOT possible to declare extension method for concrete array ,such as float [].

type 'T ``[]`` with
        member this.MyExtension with get() = "my extension"

I just added code snippet support for the extension method. You can find at the codeplex project.

Friday, August 10, 2012

Use Space in F# Namespace and Module

It is Friday's afternoon and sun finally decide to visit Seattle. I decide to have some fun with F#. I tried to use  space in the variable name with ``. It works perfectly and then  I decide to add space to other components like namespace and module.

Result: both namespace and module name can contains space.

But there are some limitation. The C# IDE does not support namespace contains space. As a result, the C# cannot reference the F# function inside a namespace which contains space. Because F# support space, so you can reference function inside F# code.

In File1.fs

namespace A.``My Space``
type MyClass() = class end
In File2.fs, the following code compiles.

module File2
open A.``My Space``
let c = MyClass()
let d = A.``My Space``.MyClass()
Not sure if somebody wants to use this feature to hide the code from C#, but it is do-able.. :-)

Sunday, August 5, 2012

Self Note: Yahoo Finance Tags

Sample to use the following tags:

http://finance.yahoo.com/d/quotes.csv?s=GE+PTR+MSFT&f=snd1l1yr

aAska2Average Daily Volumea5Ask Size
bBidb2Ask (Real-time)b3Bid (Real-time)
b4Book Valueb6Bid SizecChange & Percent Change
c1Changec3Commissionc6Change (Real-time)
c8After Hours Change (Real-time)dDividend/Shared1Last Trade Date
d2Trade DateeEarnings/Sharee1Error Indication (returned for symbol changed / invalid)
e7EPS Estimate Current Yeare8EPS Estimate Next Yeare9EPS Estimate Next Quarter
f6Float SharesgDay’s LowhDay’s High
j52-week Lowk52-week Highg1Holdings Gain Percent
g3Annualized Gaing4Holdings Gaing5Holdings Gain Percent (Real-time)
g6Holdings Gain (Real-time)iMore Infoi5Order Book (Real-time)
j1Market Capitalizationj3Market Cap (Real-time)j4EBITDA
j5Change From 52-week Lowj6Percent Change From 52-week Lowk1Last Trade (Real-time) With Time
k2Change Percent (Real-time)k3Last Trade Sizek4Change From 52-week High
k5Percebt Change From 52-week HighlLast Trade (With Time)l1Last Trade (Price Only)
l2High Limitl3Low LimitmDay’s Range
m2Day’s Range (Real-time)m350-day Moving Averagem4200-day Moving Average
m5Change From 200-day Moving Averagem6Percent Change From 200-day Moving Averagem7Change From 50-day Moving Average
m8Percent Change From 50-day Moving AveragenNamen4Notes
oOpenpPrevious Closep1Price Paid
p2Change in Percentp5Price/Salesp6Price/Book
qEx-Dividend DaterP/E Ratior1Dividend Pay Date
r2P/E Ratio (Real-time)r5PEG Ratior6Price/EPS Estimate Current Year
r7Price/EPS Estimate Next YearsSymbols1Shares Owned
s7Short Ratiot1Last Trade Timet6Trade Links
t7Ticker Trendt81 yr Target PricevVolume
v1Holdings Valuev7Holdings Value (Real-time)w52-week Range
w1Day’s Value Changew4Day’s Value Change (Real-time)xStock Exchange
yDividend Yield

Saturday, August 4, 2012

Type Provider Sample to Perform the Design Time Validation

Let us continue from the type provider samples from the previous post.

If you have not noticed the type provider is actually a design-time feature, the sample here is to highlight this feature. The production code requires the XML meet certain criteria. In this sample, the XML's start value <= end value.

There are several ways to prevent this kind of error:

  1. use schema
  2. use test case
  3. or, leave this to run-time crash.. ;-)

In this case, it is not easy to define this requirement in a schema file. The test case can check this kind error in a brute-force way. Even I do not invoke the code, the test case still runs. I want this kind of validation only happens when the method is used. The ideal situation is to let Visual Studio to tell there is something wrong with the  XML file and prevent you from a successful compilation. I want to bring this kind of run-time error to design time. The production code is listed below.

type MyProductionCode() = class
    member this.Work() =
        let xml = XDocument.Load("XmlFile1.xml")
        let start = xml.Descendants(XName.Get("Start")) | > Seq.head
        let end' = xml.Descendants(XName.Get("End")) | > Seq.head
     
        // if start >= end, something bad will happen
        if Convert.ToInt32(start.Value) >= Convert.ToInt32(end'.Value) then
            failwith "report illegal parameter from runtime"
end

The way to get this done is to put code in the InvokeCode property in the ProvidedMethod. The InvokeCode returns an code quotation and this code quotation is something will be executed at run-time, other code which is not embedded in the code quotation will only executed at design time and it is the place where can play the tricks.

let m = ProvidedMethod(
                            methodName = "Work",
                            parameters = [],
                            returnType = typeof,
                            IsStaticMethod = false,
                            InvokeCode = fun args ->
                                test.Test1(xmlFileName)      //executed at design time to validate the XML file                      
                                < @@ (%%args.[0]:MyProductionCode).Work() @@ >                                  
                            )

The Test1 method will check the XML file and throw exception if the XML is invalid. As a result, a red line will be under the function call in the Visual Studio. An interesting thing for the type provider version versus the test case is that the error only happens the method appears in the code. If user does not intend to invoke the code, there will be no error.

If you can combine this sample with the wrapper sample, you can have a more general version. We are working on the new release of our F# sample pack and eventually all type provider samples will be there.

I will be moving to cloud and data analysis stuff from next week where F# shows more muscle. Please stay tuned.. :-)

Friday, August 3, 2012

Self Note: Type Provider parameters


in the type provider static parameter, if you do:


let name = parameterValues.[1] :?> string;
let name2 = parameterValues.[2] :?> string;
let nameXXX = [| name; name2 |]


and use the NameXXX it works, but


let name = parameterValues.[1] :?> string;
let name2 = parameterValues.[2] :?> string;
let nameXXX = [| parameterValues.[1] :?> string; parameterValues.[2] :?> string |]


does not work and the error message confusing too. The error message says it does not support constant type string[]. It is pretty bad, but you can only get it work using the variable.

[Important] fixed in the recent check in and need latest type provider template.