let tag:String = "+1"
for str in readFile do
let feature = str.Split [|' '; '\t'|]
if feature.[8] = "0" then
tag = "-1"
else
tag = "+1"
printf "\n%s %s\n" feature.[8] tag
The code changes tries to change the value of tag to "-1" if feature.[8] is 0, or "+1" otherwise. However the tag variable value remains "+1" throughout, irrespective of whatever the value feature.[8] is.
How does one deal with simple value changes based on conditional statement in F#?
#John Palmer has your answer, but I'll add a bit to it...
Note that the reason why your code compiles but does not work as you expect is because the = operator used in the context of tag = "-1" and tag = "+1" is the equality operator. So those expressions are valid but return a bool value. However, you should be receiving the following warning:
This expression should have type 'unit', but has type 'bool'. Use
'ignore' to discard the result of the expression, or 'let' to bind the
result to a name.
It would serve you well to heed that warning in your F# coding adventures.
Also note that you can write your algorithm in a purely functional way (without mutable variables) using Seq.fold (among other alternative functional approaches):
let tag =
readFile
|> Seq.fold
//we use the wild card match _ here because don't need the
//tag state from the previous call
(fun _ (str:string) ->
let feature = str.Split [|' '; '\t'|]
//return "-1" or "+1" from the if / then expression,
//which will become the state value in the next call
//to this function (though we don't use it)
if feature.[8] = "0" then
"-1"
else
"+1")
("+1") //the initial value of your "tag"
You need to use a mutable variable - by default variables in F# are constant. Also, <- is the assignment operator.
let mutable tag:String = "+1"
for str in readFile do
let feature = str.Split [|' '; '\t'|]
if feature.[8] = "0" then
tag <- "-1"
else
tag <- "+1"
printf "\n%s %s\n" feature.[8] tag
for str in readFile do
let feature = str.Split [|' '; '\t'|]
let tag = if feature.[8] = "0" then "-1" else "+1"
printf "\n%s %s\n" feature.[8] tag
Related
i'm trying to develop the algorithm W in f# for type inference, but i would like to understand how to write the function for generating fresh variables properly.
Actually my function is
let counter = ref -1
let generate_fresh_variable () : string =
let list_variables = ['a' .. 'z'] |> List.map string
counter.Value <- !counter + 1
list_variables.Item(!counter)
but i'm not satisfy with this solution, someone can give me other better ideas?
If you really want to do this with an impure function, I would write it like this:
let mutable counter = -1
let generate_fresh_variable () =
counter <- counter + 1
counter + int 'a'
|> char
|> string
Notes:
Reference cells are obsolete. If you need impurity, use mutable variables instead. (Alternatively, if you really want to stick with a reference cell, the canonical way to update it is with :=, rather than assigning directly to the underlying Value.)
There's no need to maintain a list of potential variable names (and there's especially no need to rebuild the entire list each time you generate a fresh variable).
What happens if you need more than 26 variables?
If you wanted to use some more sophisticated F# tricks, you could create an inifinte sequence of names using a sequence expression (which makes it very easy to handle the looping and dealing with >26 names):
let names = seq {
for i in Seq.initInfinite id do
for c in 'a' .. 'z' do
if i = 0 then yield string c
else yield string c + string i }
A function to get the fresh name would then pick the next name from the sequence. You need to do this using the underlying enumerator. Another nice trick is to hide the state in a local variable and return a function using lambda:
let freshName =
let en = names.GetEnumerator()
fun () ->
ignore(en.MoveNext())
en.Current
Then just call freshName() as many times as you need.
I was taught, that data, by default, is immutable in F#.
When we reassign value to some variable, what really happens is that it rebinds the value of variable, but setting a new value is different thing.
Rebinding is called Shadowing whilst setting new value is impossible if we don't say explicitly, that value of the variable is mutable.
Can anyone explain to me this concept in a bit more details?
What is the difference between shadowing (rebinding):
let var = "new_value"
and setting a new value, as:
var <- "new_value"
Is this a moment, that during rebinding we create another object and we assign that object's address to the variable, whereas in the second example we change the value itself? I brought that from heap/stack concept.. but I may be wrong.
Thanks.
Shadowing is when you create a new binding that uses the same name as a previous binding. This "shadows" the original name, which hides it but doesn't change or replace it. Try this in FSI to see:
let foo = 42
let printFoo () =
printfn "%i" foo
printFoo() ;;
This will print:
42
val foo : int = 42
val printFoo : unit -> unit
val it : unit = ()
Then add:
// ... more code
let foo = 24
printfn "%i" foo // prints 24
printFoo ();;
This will print:
24
42
val foo : int = 24
val it : unit = ()
Note that it still prints 42 when you call printFoo() - the function sees the original (unshadowed) binding, but the new print shows the new value.
Using <- to mutate a value requires a mutable binding:
let mutable bar = 42
let printBar () =
printfn "%i" bar
printBar ();;
This, like above, prints 42. Note that you override the default immutable behavior here with the mutable keyword.
You then change the value within the mutable binding:
bar <- 24
printfn "%i" bar
printBar ();;
This will print 24 twice, since, unlike the shadowed version, the mutation changes the original binding. If you leave mutable off in the original binding, you'll get an error when using <-.
To add on Reed Copsey's excellent answer, if you're writing a loop where you change the value of an accumulator of some sort, you'd set the original value as mutable. For example, you can do this.
let mutable acc = 0 // declaration
for i in 1..100 do
acc <- acc + i // assignment
This is more or less equivalent to the C# code :
var acc = 0;
for (int i = 1; i <= 100; i++)
{
acc = acc + i; // assignment
// Another way to write this:
// acc += i;
}
However, in Shadowing, as in this F# snippet:
let acc = 0 // declaration
for i in 1..100 do
let acc = acc + i // another declaration only within the loop
You're not actually doing anything useful!! The second declaration has scope only within the for loop, and it doesn't change the value of the original acc.
A rough C# equivalent would be this:
var acc = 0; // declaration
for (int i = 1; i <= 100; i++)
{
var acc2 = acc + i; // another declaration only within the loop
}
Note that using acc (instead of acc2) for the inside variable wouldn't compile in C#, as it doesn't have Shadowing in this context.
The use of shadowing is that, it prevents from using the original variant in a block of code where you don't want it. So there is one less variable to worry about.
Whenever I wonder what actually is happening I use tools like ILSpy
For example:
let f () =
let x = Dictionary<int, string> ()
let mutable x = ResizeArray<int> 16
x <- ResizeArray<int> 16
Using ILSpy to decompile it in C# code it becomes:
public static void f()
{
Dictionary<int, string> x = new Dictionary<int, string>();
List<int> x2 = new List<int>(16);
x2 = new List<int>(16);
}
Here it's more obvious what the difference between shadowing and setting.
Shadowing x creates a new variable with name x2.
Setting is normal assignment.
I am trying to set the message formatter for a message in F#. In C# I can have:
foreach (System.Messaging.Message message in messages)
{
message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
string body = message.Body.ToString();
Console.WriteLine(body);
}
which works just fine. I now want to do the same thing in F# and have:
let mList = messageQueue.GetAllMessages()
let xt = [| "System.String,mscorlib" |]
for m in mList do
m.Formatter = XmlMessageFormatter(xt)
which causes this error at compile time:
Error 2 This expression was expected to have type
IMessageFormatter
but here has type
XmlMessageFormatter
I suspect I am missing a basic concept in F#. What am I doing wrong?
--EDIT--
latkin's answer worked perfectly. Just in case anyone else is interested, here is the full working program in F#:
open System.Messaging
[<EntryPoint>]
let main argv =
printfn "%A" argv
let messageQueue = new MessageQueue(".\private$\Twitter")
messageQueue.MessageReadPropertyFilter.SetAll();
let mList = messageQueue.GetAllMessages()
let xt = [| "System.String,mscorlib" |]
for m in mList do
m.Formatter <- XmlMessageFormatter(xt)
printfn "%s " (m.Body.ToString())
0 // return an integer exit code
When you are assigning a mutable value, the operator is <-, not =. In F# = is only used for initial bindings, otherwise it's used as the Boolean equality operator (like C-family ==). Some docs here.
You want
let mList = messageQueue.GetAllMessages()
let xt = [| "System.String,mscorlib" |]
for m in mList do
m.Formatter <- XmlMessageFormatter(xt)
No casting is needed in this case.
The error comes up because the compiler thinks you are trying to compare a IMessageFormatter to a XmlMessageFormatter.
F# doesn't have implicit casts like C# does, so it doesn't automatically upcast your XmlMessageFormatter to the IMessageFormatter used by the Formatter property.
There was a similar question a couple of days ago with more information about this:
F# return ICollection
let i = ref 123
let j = ref 123
i = j // true
Similarly:
let i = box 123
let j = box 123
i = j // true
Presumably, i and j are not actually pointing to the same exact place in memory...??
I get around this (odd?) behavior in the second case by doing:
obj.ReferenceEquals (i, j) // false
What is the proper equality test for the first case?
EDIT:
I see that calling obj.ReferenceEquals works in the first case, as well.
Can someone out there explain to me why I have to call this function, though? Why can't I just use the = operator?
The (=) operator calls GenericEqualityObj. It first checks the types of the args (for arrays, assignability to IStructuralEquatable, and a few other special cases) and the final case calls obj.Equals. Equals is overridden by ValueType (which int derives) to do bit comparison. That explains why (box 123) = (box 123) is true.
Ref cells are represented using records, by default records are structurally comparable\equatable
What would be an elegant way to implement the functionality of this nested class in F#?
private class Aliaser {
private int _count;
internal Aliaser() { }
internal string GetNextAlias() {
return "t" + (_count++).ToString();
}
}
This was my first attempt, but it feels like there should be a sexy one-liner for this:
let aliases = (Seq.initInfinite (sprintf "t%d")).GetEnumerator()
let getNextAlias() =
aliases.MoveNext() |> ignore
aliases.Current
The usual way of writing is to create a function with local state captured in a closure:
let getNextAlias =
let count = ref 0
(fun () ->
count := !count + 1;
sprintf "t%d" (!count))
The type of getNextAlias is simply unit -> string and when you call it repeatedly, it returns strings "t1", "t2", ... This relies on mutable state, but the mutable state is hidden from the user.
Regarding whether you can do this without mutable state - the simple answer is NO, because when you call a purely functional function with the same parameter twice, it must return the same result. Thus, you'd have to write something with the following structure:
let alias, state1 = getNextAlias state0
printf "first alias %s" alias
let alias, state2 = getNextAlias state1
printf "second alias %s" alias
// ...
As you can see, you'd need to keep some state and maintain it through the whole code. In F#, the standard way of dealing with this is to use mutable state. In Haskell, you could use State monad, which allows you to hide the passing of the state. Using the implementation from this question, you could write something like:
let getNextAlias = state {
let! n = getState
do! setState (n + 1)
return sprintf "t%d" n }
let program =
state {
let! alias1 = getNextAlias()
let! alias2 = getNextAlias()
// ...
}
execute progam 0 // execute with initial state
This is quite similar to other computations such as lazy or seq, actually - computations in the state { .. } block have some state and you can execute them by providing initial value of the state. However, unless you have good reasons for requiring purely functional solution, I'd prefer the first version for practical F# programming.
Here is the quick and dirty translation
type Aliaser () =
let mutable _count = 0
member x.GetNextAlias() =
let value = _count.ToString()
_count <- _count + 1
"t" + value
A more functional approach without state is to use continuations.
let createAliaser callWithValue =
let rec inner count =
let value = "t" + (count.ToString())
callWithValue value (fun () -> inner (count + 1))
inner 1
This is a declaration which will call the function callWithValue with both the value and the function to execute to repeat with the next value.
And here's an example using it
let main () =
let inner value (next : unit -> unit )=
printfn "Value: %s" value
let input = System.Console.ReadLine()
if input <> "quit" then next()
createAliaser inner
main()
I would use Seq.unfold : (('a -> ('b * 'a) option) -> 'a -> seq<'b>) to generate the aliases.
Implemented as:
let alias =
Seq.unfold (fun count -> Some(sprintf "t%i" count, count+1)) 0