If a override ToString in a type
type TestMe ()=
override __.ToString() = null
and then I output it through the "%A" specifier
printfn "*%A*" (TestMe())
why does it throw a System.NullReferenceException?
I would have expected it to behave like
printfn "*%A*" null
which simply prints <null> without any exceptions.
This issue got fixed in F# 4.1, which now explicitly handles the case where ToString() returns null. Before that fix, the null would travel up the stack and eventually be dereferenced.
Upgrading your FSharp.Core version will fix the issue for you.
Having said that, I'd like to point out that returning null from ToString is a generally a big no-no. Even MSDN docs have a specific warning about it.
Are you sure?
I get the following output:
type TestMe ()=
override __.ToString() = null
TestMe()
//val it : TestMe =
printfn "%A" (TestMe())
//val it : unit = ()
There is a slight difference as I assume reflection is doing some translation between unit and null but it doesn't show an exception. Why do you need the stars in "*%A*"?
Related
I'm trying to mock the .NET HttpClient with Moq in F#. I currently have the following code:
open System.Net.Http
open Foq
[<Fact>]
let ``Some test`` () =
Mock<HttpClient>.With
(fun client ->
<# client.GetStringAsync("foo")
--> task { return "bar" } #>)
|> ignore
Upon running the test I get the following error.
System.Reflection.TargetParameterCountException : Parameter count mismatch.
How can I fix this?
I know there are many similar questions, but they are all for C#. They mention that either there are arguments missing somewhere or something with a callback should be added. But I can't figure out what arguments are missing, or how to add the callback to my example.
I looked into this a bit and it seems to be caused by an underlying problem with F# quotations, rather something that can be addressed within Foq. For example, the following code throws the same unhandled exception:
<# task { return "bar" } #>
|> FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation
|> printfn "%A"
I reported this as an issue in the F# core repository.
I am trying to add a F#-style interface to a type, that has a byref return method.
Here's the code:
type IPool<'P, 'T when 'T: struct> =
abstract member GetReference: ITypedPointer<'P, 'T> -> byref<'T>
let Ref<'TPool, 'P, 'T when 'TPool :> IPool<'P, 'T>> (pool: 'TPool) pointer =
pool.GetReference pointer
Now to my surprise, a similar thing worked fine until I introduced IPool interface. Before that Ref itself contained an implementation like &pool.data.[idx], and worked fine.
I tried installing nightly build of F# Tools, cause latest release does not officially support byref returns, and PR to introduce them was recently completed: https://github.com/Microsoft/visualfsharp/pull/4888
However, I still get error FS3209: The address of the variable 'copyOfStruct' cannot be used at this point. A method or function may not return the address of this local value. in Visual Studio. Type outref<T> still does not seem to be available either. Am I missing something?
I also tried to drop the pointer parameter, and just return pool.GetReference to only get a different error message.
Addition: the ultimate goal is to be able to do
let aref = Ref pool ptr
let bref = Ref pool ptr
aref <- 42
assert(aref = bref)
e.g. give caller a direct reference to an internal memory, usually backed by an array, similar to Span<T>. I am making this for performance reasons, so it is not OK to allocate on every call to Ref.
For some reason, reducing generalization helped to get rid of the error:
let Ref<'P, 'T when 'T: struct> (pool: IPool<'P, 'T>) pointer = pool.GetReference pointer
Solution provided by
https://github.com/Microsoft/visualfsharp/issues/5366#issuecomment-407521220
Though it does not explain why the original code does not compile.
I don't think it's standard practice to return a byref type. This type is really meant for method parameters, mostly for C# interop with out or ref parameters. Take a look at this StackOverflow question for a good explanation.
What you can do is change the method on your interface to take a tuple of ITypedPointer<'P,'T> and byref<'T> (usage of byref is not allowed with curried parameters) and return unit instead. Then you can call GetReference like any standard .NET method with an out parameter in C#. That would look something like this:
type ITypedPointer<'P, 'T> = interface end
type IPool<'P, 'T when 'T: struct> =
abstract member GetReference: ITypedPointer<'P, 'T> * byref<'T> -> unit
let Ref<'TPool, 'P, 'T when 'TPool :> IPool<'P, 'T>> (pool: 'TPool) pointer =
let mutable value = Unchecked.defaultof<'T>
pool.GetReference(pointer, &value)
value
I have the following code:
open NSubstitute
type MyClass()=
let myObject = Substitute.For<IMyInterface>()
do myObject.MyProperty.Returns(true)
do myObject.MyMethod().Returns(true)
On "Returns" (both) I get the error that is not defined. The equivalent C# code works without issue. Adding |> ignore at the end of the do lines does not help. Am I missing something there?
I know you wrote that adding |> ignore at the end doesn't help, but this compiles on my machine:
type IMyInterface =
abstract MyProperty : bool with get, set
abstract member MyMethod : unit -> bool
open NSubstitute
type MyClass() =
let myObject = Substitute.For<IMyInterface>()
do myObject.MyProperty.Returns(true) |> ignore
do myObject.MyMethod().Returns(true) |> ignore
I attempted to infer the definition of IMyInterface from the question; did I get it wrong?
So after I tried the code (Mark Seemann's, as to avoid my C# class) on VS2012, fsi, through direct compilation with fsc and on VS2013, the issue is clearly a VS2012 problem. The code works correctly with the other three.
Not sure yet if it is using a different version of F#. Will need further investigation. But at least, for now, on VS2012 I can use:
do SubstituteExtensions.Returns(myObject.MyProperty, true) |> ignore
It works as well when I need to pass parameters to methods.
In F# its a big deal that they do not have null values and do not want to support it. Still the programmer has to make cases for None similar to C# programmers having to check != null.
Is None really less evil than null?
The problem with null is that you have the possibility to use it almost everywhere, i.e. introduce invalid states where this is neither intended nor makes sense.
Having an 'a option is always an explicit thing. You state that an operation can either produce Some meaningful value or None, which the compiler can enforce to be checked and processed correctly.
By discouraging null in favor of an 'a option-type, you basically have the guarantee that any value in your program is somehow meaningful. If some code is designed to work with these values, you cannot simply pass invalid ones, and if there is a function of option-type, you will have to cover all possibilities.
Of course it is less evil!
If you don't check against None, then it most cases you'll have a type error in your application, meaning that it won't compile, therefore it cannot crash with a NullReferenceException (since None translates to null).
For example:
let myObject : option<_> = getObjectToUse() // you get a Some<'T>, added explicit typing for clarity
match myObject with
| Some o -> o.DoSomething()
| None -> ... // you have to explicitly handle this case
It is still possible to achieve C#-like behavior, but it is less intuitive, as you have to explicitly say "ignore that this can be None":
let o = myObject.Value // throws NullReferenceException if myObject = None
In C#, you're not forced to consider the case of your variable being null, so it is possible that you simply forget to make a check. Same example as above:
var myObject = GetObjectToUse(); // you get back a nullable type
myObject.DoSomething() // no type error, but a runtime error
Edit: Stephen Swensen is absolutely right, my example code had some flaws, was writing it in a hurry. Fixed. Thank you!
Let's say I show you a function definition like this:
val getPersonByName : (name : string) -> Person
What do you think happens when you pass in a name of a person who doesn't exist in the data store?
Does the function throw a NotFound exception?
Does it return null?
Does it create the person if they don't exist?
Short of reading the code (if you have access to it), reading the documentation (if someone was kindly enough to write it), or just calling the function, you have no way of knowing. And that's basically the problem with null values: they look and act just like non-null values, at least until runtime.
Now let's say you have a function with this signature instead:
val getPersonByName : (name : string) -> option<Person>
This definition makes it very explicit what happens: you'll either get a person back or you won't, and this sort of information is communicated in the function's data type. Usually, you have a better guarantee of handling both cases of a option type than a potentially null value.
I'd say option types are much more benevolent than nulls.
In F# its a big deal that they do not have null values and do not want to support it. Still the programmer has to make cases for None similar to C# programmers having to check != null.
Is None really less evil than null?
Whereas null introduces potential sources of run-time error (NullRefereceException) every time you dereference an object in C#, None forces you to make the sources of run-time error explicit in F#.
For example, invoking GetHashCode on a given object causes C# to silently inject a source of run-time error:
class Foo {
int m;
Foo(int n) { m=n; }
int Hash() { return m; }
static int hash(Foo o) { return o.Hash(); }
};
In contrast, the equivalent code in F# is expected to be null free:
type Foo =
{ m: int }
member foo.Hash() = foo.m
let hash (o: Foo) = o.Hash()
If you really wanted an optional value in F# then you would use the option type and you must handle it explicitly or the compiler will give a warning or error:
let maybeHash (o: Foo option) =
match o with
| None -> 0
| Some o -> o.Hash()
You can still get NullReferenceException in F# by circumventing the type system (which is required for interop):
> hash (box null |> unbox);;
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.UnboxGeneric[T](Object source)
at <StartupCode$FSI_0021>.$FSI_0021.main#()
Stopped due to error
I was playing around with F# (Visual Studio 2010 beta 1), and I wrote a little console script that asked the user to input 2 numbers and an operator and then executed it.
It works fine, apart from a tiny, but annoying thing: sometimes my printfn instructions are ignored. I placed breakpoints in the code to see that's indeed the case.
The code snippet:
let convert (source : string) =
try System.Int32.Parse(source)
with :? System.FormatException ->
printfn "'%s' is not a number!" source;
waitForExitKey();
exit 1
let read =
printfn "Please enter a number.";
System.Console.ReadLine
let num1 : int = read() |> convert // the printfn in the read function is run...
let num2 : int = read() |> convert // ... but here is ignored
This is not the complete source of course, but I think that'll be enough. If you need the complete source just let me know.
So my question is pretty simple: what causes this issue with printfn? Am I doing something wrong?
Thanks in advance,
ShdNx
This page has a partial explanation of what's going on, but the short and sweet version is that F# will execute any value on declaration if it doesn't take parameters.
let read =
printfn "Please enter a number."
System.Console.ReadLine
Since read doesn't take any parameters, its executed immediately on declaration and binds the return value of the function to the identifier read.
Incidentally, your return value happens to be a function with the type (unit -> string). This results because F# automatically curries functions if they aren't passed all of their parameters. ReadLine expects one unit parameter, but since it isn't passed on, you actually bind read to the ReadLine function itself.
The solution is as follows:
let read() = // read takes one unit parameter
printfn "Please enter a number."
System.Console.ReadLine() // pass paramter to ReadLine method
Since read takes one parameter, its re-evaluated each time its called. Additionally, we're passing a parameter to ReadLine, otherwise we'll just return the ReadLine function as a value.
I understand that this can be confusing. In your example, printfn runs earlier than you think. It will actually execute even without the call to read(), i.e., comment out the last two lines and you will still see a message being printed.
I think your intention is something like this:
let read() =
printfn "Please enter a number.";
System.Console.ReadLine()
This will create a "reusable" function instead of binding a function to an identifier as in your original example.
As a sidenote, the use of semi-colons here is optional so you can just write:
let read() =
printfn "Please enter a number."
System.Console.ReadLine()