C# warns for unused variables that are compile-time constants:
static void Main(string[] args)
{
var unused = "hey"; //CS0219 The variable 'unused' is assigned but its value is never used
Console.WriteLine("Hello World!");
}
But the F# compiler does not, even though the editor now does pick it up:
If it covered not just compile-time constants but all let bindings, this would have caught a real bug in production caused by a trivial mistake, something like
let callApiXyz connectionInfo = async {
let fullUrl = sprintf "%s..." connectionInfo.Url
...
let! result = httpGet connectionInfo // fail, didn't use the modified url
// Should have been:
// let! result = httpGet { connectionInfo with Url = fullUrl }
...
}
Is there any reason not to have this (other than "features are not free")? I feel this should be more important in a functional-first language where expressions tend not to have side-effects, than in C#.
For those of us that don't have Visual Studio and edit the fsproj by hand, the way to implement Tomas's answer is
<PropertyGroup>
<OtherFlags>$(OtherFlags) --warnon:1182</OtherFlags>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
As an example, see the project file of FSharp.Core itself.
You can enable warning for unused bindings via the warnon compiler option. If you want to be strict, you can even use warnaserror+ to turn it into an error.
The warning number is 1182 and it is turned off by default as documented in the compiler options page in the F# documentation.
fsc --warnaserror+:1182 --warnon:1182 Program.fs
How to do this will depend on your editor. In Visual Studio, you can do this by specifying "Other flags" and "Treat warnings as errors" in project properties.
Related
I'm using the following code snippet in a WPF / FsXaml application:
let groupSelected(e: SelectionChangedEventArgs) =
e.AddedItems
|> Seq.cast<string>
|> Seq.head
|> SelectedGroupChanged
let GroupSelected = groupSelected
When I mouse-over groupSelected, Visual Studio shows the following:
val groupSelected: e:SelectionChangedEventArgs -> ClientGroupEvent
It is slightly different for GroupSelected:
val GroupSelected: (SelectionChangedEventArgs -> ClientGroupEvent)
I have noticed this difference before in other contexts and never thought much of it. If I want to invoke either one, the syntax in my code is the same... groupSelected(e) and GroupSelected(e) both compile fine.
However, when I try to use these two from XAML only this works:
{x:Static local:EventConverters.GroupSelected}
This does not work:
{x:Static local:EventConverters.groupSelected}
What is the difference between those two such that XAML Static extension only works with the second? I would have (mistakenly?) thought they were the same thing.
This is one of the areas where simple functional ideas are made a bit more complicated by living in the .NET framework world. F# indeed compiles your groupSelected and GroupSelected in two different ways.
The IntelliSense does tell you this. Most of the time, this is not something you need to worry about, and it is quite sensible to see the following two as the same thing (and, as far as F# itself is concerned, they are):
val groupSelected: e:SelectionChangedEventArgs -> ClientGroupEvent
val GroupSelected: (SelectionChangedEventArgs -> ClientGroupEvent)
The key difference is that the two will be compiled diferently. The first one as a method and the second one as a property that returns a function value. Using C# notation:
// groupSelected is compiled as a method:
ClientGroupEvent groupSelected(SelectionChangedEventArgs e);
// GroupSelected is compiled as a property:
FSharpFunc<SelectionChangedEventArgs, ClientGroupEvent> GroupSelected { get; }
I'm making a project where there are separate source files/modules that add functions to a single Dictionary contained in a higher level file. However, I find that nothing in these source files evaluates on its own, even functions that take no arguments/code that isn't even inside a function.
As a result nothing is being added to the Dictionary. Is there a way to forcibly evaluate complete function calls in a module automatically? I'll give an example of what I'm trying to do:
Registry.fs:
let private functions = Dictionary<string, MessageHandler>()
let add type handler =
functions.Add(type, handler)
Handler1.fs:
Registry.add "type1" (fun m -> ....
)
Handler2.fs:
Registry.add "type2" (fun m -> ....
)
I believe you need to see this relevant topic. Loose method calls would get compiled as method calls inside of a static constructor for the enclosing type/module, when the F# code gets compiled to IL. This would roughly be equivalent to the following C# code, just to see the picture:
static class Handler1 {
static Handler1() {
// this is the static constructor
Registry.add "type1" ....
}
}
In .NET static constructors are not eagerly initialized1. This means, if you want to cause the .NET runtime to call the Handler1 static constructor, you need to access a static member of the type Handler1.
An example of using the type in a static context would be to
Expose a sufficiently accessible static member/method:
module Handler1 =
[<Literal>]
let Name = "Handler1"
Access that static member from your code, such as the main method:
[<EntryPoint>]
let main args =
printf Handler1.Name
The above line will force the .NET runtime to load the Handler1 type's static context, which will result in invoking the static constructor if the type is encoutered by your code for the first time. If your code never encounters a given type's static context (any static member or method), then it will never be initialized -- the static constructors will never get called.
This behaviour is by design of the .NET framework (and that is regardless of the chosen language -- C#, F#, VB, others -- they all compile to similar IL). The point is to not allocate unnecessary resources by types that are never actually used.
1 Until .NET 4, static type context was initialized when the given type was first encountered by the executing code, regardless if the user code is interacting with instace or static members of that type. After .NET 4, this slightly changed -- the static context is initialized only when the user code interacts with static members of the type.
I need to use System.Timers.Timer in an F# PCL library.
I'm currently targeting framework 4.5 and using Profile7 (I used the VS template) and it doesn't allow access to System.Timer.
According to this SO answer it's a known issue and is solved in 4.5.1.
I created a 4.5.1 C# PCL and checked its .csproj. It targets framework 4.6 and uses Profile32.
Is there a way to target the same in an F# project? I naively tried to update the .fsproj with the C# values, but it broke everything. :)
Thanks very much!
The System.Timers.Timer (and System.Threading.Timer) classes don't work in the main F# PCL profiles. Given that normal F# async is supported, you can easily work around this by writing your own "timer" type. For example, the following (while a bit ugly) should mimic the Timer class functionality reasonably well:
type PclTimer(interval, callback) =
let mb = new MailboxProcessor<bool>(fun inbox ->
async {
let stop = ref false
while not !stop do
// Sleep for our interval time
do! Async.Sleep interval
// Timers raise on threadpool threads - mimic that behavior here
do! Async.SwitchToThreadPool()
callback()
// Check for our stop message
let! msg = inbox.TryReceive(1)
stop := defaultArg msg false
})
member __.Start() = mb.Start()
member __.Stop() = mb.Post true
In dart, when developing a web application, if I invoke a method with a wrong number of arguments, the editor shows a warning message, the javascript compilation however runs successfully, and an error is only raised runtime. This is also the case for example if I refer and unexistent variable, or I pass a method argument of the wrong type.
I ask, if the editor already know that things won't work, why is the compilation successful? Why do we have types if they are not checked at compile time? I guess this behaviour has a reason, but I couldn't find it explained anywhere.
In Dart, many programming errors are warnings.
This is for two reasons.
The primary reason is that it allows you to run your program while you are developing it. If some of your code isn't complete yet, or it's only half refactored and still uses the old variable names, you can still test the other half. If you weren't allowed to run the program before it was perfect, that would not be possible.
The other reason is that warnings represent only static type checking, which doesn't know everything about your program, It might be that your program will work, it's just impossible for the analyser to determine.
Example:
class C {
int foo(int x) => x;
}
class D implements C {
num foo(num x, [num defaultValue]) => x == null ? defaultValue : x;
}
void bar(C c) => print(c.foo(4.1, 42)); // Static warning: wrong argument count, bad type.
main() { bar(new D()); } // Program runs fine.
If your program works, it shouldn't be stopped by a pedantic analyser that only knows half the truth. You should still look at the warnings, and consider whether there is something to worry about, but it is perfectly fine to decide that you actually know better than the compiler.
There is no compilation stage. What you see is warning based on type. For example:
This code will have warning:
void main() {
var foo = "";
foo.baz();
}
but this one won't:
void main() {
var foo;
foo.baz();
}
because code analyzer cant deduct the type of foo
I just want somehow to say "I want all methods in this project use [JavaScript]"
Manually annotation every method is annoying
F# 3 lets you mark a module with the ReflectedDefinition attribute (aka [JavaScript] in WebSharper) which marks all the methods underneath.
See More About F# 3.0 Language Features:
(Speaking of uncommon attributes, in F# 3.0, the
[< ReflectedDefinition >] attribute can now be placed on modules and
type definitions, as a shorthand way to apply it to each individual
member of the module/type.)
I think Phil's answer is the way to go - when you can mark an entire module or type, it does not add too much noise and it also allows you to distinguish between server-side and client-side code in WebSharper.
Just for the record, the F# compiler is open-source and so someone (who finds this issue important) could easily create branch that would add an additional command line attribute to override the setting. I think this is just a matter of adding the parameter and then setting the default value of the reflect flag in check.fs (here is the source on GitHub).
At the moment, the main F# repository does not accept contributions that add new features (see the discussion here), but it is certainly a good way to send a feature request to the F# team :-)
If you annotate all your code with the JavaScript attribute, the WebSharper compiler will try to translate everything to JavaScript. A rule of thumb in WebSharper development is to separate server-side and client-side code, so you can simply annotate the module/class containing client-side code instead of every function/member if you're targeting .NET 4.5.
namespace Website
open IntelliFactory.WebSharper
module HelloWorld =
module private Server =
[<Rpc>]
let main() = async { return "World" }
[<JavaScript>] // or [<ReflectedDefinition>]
module Client =
open IntelliFactory.WebSharper.Html
let sayHello() =
async {
let! world = Server.main()
JavaScript.Alert <| "Hello " + world
}
let btn =
Button [Text "Click Me"]
|>! OnClick (fun _ _ ->
async {
do! sayHello()
} |> Async.Start)
let main() = Div [btn]
type Control() =
inherit Web.Control()
[<JavaScript>]
override __.Body = Client.main() :> _