Being as how I am new to F#, this may seem like some kind of elementary question. But here goes. I have a class with a constructor using the following code:
new () = {
_index = 0; _inputString = "";
_tokens = new Dictionary<string, string>() {
{"key", "value"}
}
}
Everything works except F# doesn't seem to allow me to add tokens to my dictionary. I can initialize it with a new Dictionary<> object, but if I try to populate, it throws an error. I also can't do it with the.Add member. I have seen examples of F# constructors initializing field values, but is there no way to execute other code maybe?
Because Dictionary
has a constructor taking an IDictionary
instance , you can use the built-in dict
function to help you here:
open System.Collections.Generic
type Foo =
val _index : int
val _inputString : string
val _tokens : Dictionary<string, string>
new () =
{
_index = 0
_inputString = ""
_tokens = Dictionary(dict [("fooKey", "fooValue")])
}
However, it's also possible to execute non-trivial code before or after your constructor's object initializer:
type Bar =
val _index : int
val _inputString : string
val _tokens : Dictionary<string, string>
new () =
let tokens = Dictionary()
tokens.Add ("barKey", "barValue")
{
_index = 0
_inputString = ""
_tokens = tokens
}
type Baz =
val _index : int
val _inputString : string
val _tokens : Dictionary<string, string>
new () as this =
{
_index = 0
_inputString = ""
_tokens = Dictionary()
} then
this._tokens.Add ("bazKey", "bazValue")
Ildjarn already answered your question, but let me just add a note about coding style - I think that most of the F# programs these days prefer the implicit constructor syntax, where you define one implicit constructor as part of the type
declaration. This usually makes code a lot simpler. You could write something like:
type Bah() =
let index = 0
let inputString = ""
let tokens = new Dictionary<string, string>()
do tokens.Add("bazKey", "barValue")
member x.Foo = "!"
This defines a parameter-less constructor and private fields (eg index
). In your sample, this doesn't make much sense (because all fields are immutable, so index
will always be zero). I suppose you probably have other constructor, in which case you can write something like:
type Baf(index:int, inputString:string, tokens:Dictionary<string, string>) =
new() =
let tokens = new Dictionary<string, string>()
tokens.Add("bazKey", "barValue")
Baf(0, "", tokens)
Here, you get two constructors - one parameter-less and one that takes three parameters. You can also make the implicit constructor private and expose only more specific cases:
type Baf private (index:int, inputString:string, tokens:Dictionary<string, string>) =
// (...)
As a side-note, I also changed the naming from _index
to index
, because I don't think that F# guidelines recommend using underscores (although, it may make sense for fields declared using val
)
In F#, everything is an expression, so you can initialize _tokens
like so:
open System.Collections.Generic
type Foo =
val _index : int
val _inputString : string
val _tokens : Dictionary<string, string>
new () =
{
_index = 0
_inputString = ""
_tokens =
let _tokens = Dictionary()
_tokens.Add ("key", "value")
_tokens
}
The light syntax can trick you into thinking that let bindings and sequential expressions are statements, but if we write out the full verbose syntax for those expressions it's clear:
...
_tokens = let _tokens = Dictionary() in _tokens.Add ("key", "value") ; _tokens
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.