How do I print an entire list in F#? - f#

When I use Console.WriteLine to print a list, it defaults to only showing the first three elements. How do I get it to print the entire contents of the list?

You can use the %A format specifier along with printf to get a 'beautified' list printout, but like Console.WriteLine (which calls .ToString()) on the object, it will not necessarily show all the elements. To get them all, iterate over the whole list. The code below shows a few different alternatives.
let smallList = [1; 2; 3; 4]
printfn "%A" smallList // often useful
let bigList = [1..200]
printfn "%A" bigList // pretty, but not all
printfn "Another way"
for x in bigList do
printf "%d " x
printfn ""
printfn "Yet another way"
bigList |> List.iter (printf "%d ")
printfn ""

You can iterate over the it, using the List.iter function, and print each element:
let list = [1;2;3;4]
list |> List.iter (fun x -> printf "%d " x)
More info:
Lists in F# (MSDN)

Here's simple alternative that uses String.Join:
open System
let xs = [1; 2; 3; 4]
let s = "[" + String.Join("; ", xs) + "]"
printfn "%A" s

Related

F# Writing to file changes behavior on return type

I have the following function that convert csv files to a specific txt schema (expected by CNTKTextFormat Reader):
open System.IO
open FSharp.Data;
open Deedle;
let convert (inFileName : string) =
let data = Frame.ReadCsv(inFileName)
let outFileName = inFileName.Substring(0, (inFileName.Length - 4)) + ".txt"
use outFile = new StreamWriter(outFileName, false)
data.Rows.Observations
|> Seq.map(fun kvp ->
let row = kvp.Value |> Series.observations |> Seq.map(fun (k,v) -> v) |> Seq.toList
match row with
| label::data ->
let body = data |> List.map string |> String.concat " "
outFile.WriteLine(sprintf "|labels %A |features %s" label body)
printf "%A" label
| _ ->
failwith "Bad data."
)
|> ignore
Strangely, the output file is empty after running in the F# interactive panel and that printf yields no printing at all.
If I remove the ignore to make sure that there are actual rows being processed (evidenced by returning a seq of nulls), instead of an empty file I get:
val it : seq<unit> = Error: Cannot write to a closed TextWriter.
Before, I was declaring the StreamWriter using let and disposing it manually, but I also generated empty files or just a few lines (say 5 out of thousands).
What is happening here? Also, how to fix the file writing?
Seq.map returns a lazy sequence which is not evaluated until it is iterated over. You are not currently iterating over it within convert so no rows are processed. If you return a Seq<unit> and iterate over it outside convert, outFile will already be closed which is why you see the exception.
You should use Seq.iter instead:
data.Rows.Observations
|> Seq.iter (fun kvp -> ...)
Apart from the solutions already mentioned, you could also avoid the StreamWriter altogether, and use one of the standard .Net functions, File.WriteAllLines. You would prepare a sequence of converted lines, and then write that to the file:
let convert (inFileName : string) =
let lines =
Frame.ReadCsv(inFileName).Rows.Observations
|> Seq.map(fun kvp ->
let row = kvp.Value |> Series.observations |> Seq.map snd |> Seq.toList
match row with
| label::data ->
let body = data |> List.map string |> String.concat " "
printf "%A" label
sprintf "|labels %A |features %s" label body
| _ ->
failwith "Bad data."
)
let outFileName = inFileName.Substring(0, (inFileName.Length - 4)) + ".txt"
File.WriteAllLines(outFileName, lines)
Update based on the discussion in the comments: Here's a solution that avoids Deedle altogether. I'm making some assumptions about your input file format here, based on another question you posted today: Label is in column 1, features follow.
let lines =
File.ReadLines inFileName
|> Seq.map (fun line ->
match Seq.toList(line.Split ',') with
| label::data ->
let body = data |> List.map string |> String.concat " "
printf "%A" label
sprintf "|labels %A |features %s" label body
| _ ->
failwith "Bad data."
)
As Lee already mentioned, Seq.map is lazy. And that's also why you were getting "Cannot write to a closed TextWriter": the use keyword disposes of its IDisposable when it goes out of scope. In this case, that's at the end of your function. Since Seq.map is lazy, your function was returning an unevaluated sequence object, which had closed over the StreamWriter in your use statement -- but by the time you evaluated that sequence (in whatever part of your code checked for the Seq of nulls, or in the F# Interactive window), the StreamWriter had already been disposed by going out of scope.
Change Seq.map to Seq.iter and both of your problems will be solved.

Second to last item in a list in F#

This is what my initial thought was and there were no issues until it was called; What is wrong with this exactly?
let SecLastItem myList=
List.rev myList
|>printfn myList.[1]
How do I rectify the problem here? What is the best way to find the 2nd to last item of a list?
printfn expects a format first printfn "%A" arg
But there is more, functional programming favors immutability so List.rev returns a new list without modifying mylist
So printing the second item in myList won't give the second to last just the second from start (if it exists otherwise it'll crash)
That said you should separate function doing something and logging/printing that' better for reuse and composability.
// trySecLastItem : 'a list -> 'a option
let trySecLastItem = List.rev >> List.tryItem 2
// usage
printfn "%d" (trySecLastItem someList) // ex Some 42 or None
Now as trySecLastItem returns an option you have to take care of that (using defaultArg for example)
// maybeSecLast : int option
let maybeSecLast = trySecLastItem someList
printfn "%d" (defaultArg maybeSecLast 42)
What is the best way to find the 2nd to last item of a list?
If you do not want to reverse the list, you can use pattern matching and return an option if the list is not long enough for a 'second to last item'. Something like this.
let rec secondToLast ls =
match ls with
| [] -> None
| h :: ht :: [] -> Some(h)
| h :: t -> secondToLast t
test with
printfn "%A" (secondToLast [1; 2; 3; 4])
You need to have a formatter with printfn
let SecLastItem myList=
let revList = List.rev myList
printfn "%A" revList.[1]

Feeding tuple into function such as printfn

I want to give a tuple to a printf function:
let tuple = ("Hello", "world")
do printfn "%s %s" tuple
This, of course, does not work, compiler first says, that it needs string instead of string*string. I write it as follows:
let tuple = ("Hello", "world")
do printfn "%s %s" <| fst tuple
Then compiler reasonably notes that now I have function value of type string -> unit. Makes sense. I can write
let tuple = ("Hello", "world")
do printfn "%s %s" <| fst tuple <| snd tuple
And it works for me. But I'm wondering, if there might be any way to do it nicer, like
let tuple = ("Hello", "world")
do printfn "%s %s" <| magic tuple
My problem is that I can't get which type does printf need so that to print two arguments.
What could magic function look like?
You want
let tuple = ("Hello", "world")
printfn "%s %s" <|| tuple
Notice the double || in <|| and not a single | in <|
See: <||
You can also do
let tuple = ("Hello", "world")
tuple
||> printfn "%s %s"
There are other similar operators such as |>, ||>, |||>, <|, <||, and <|||.
A idiomatic way to do it using fst and snd is
let tuple = ("Hello", "world")
printfn "%s %s" (fst tuple) (snd tuple)
The reason you don't usually see a tuple passed to a function with one of the ||> or <|| operators is because of what is known as a destructuring.
A destructing expression takes a compound type and destructs it into parts.
So for the tuple ("Hello", "world") we can create a destructor which breaks the tuple into two parts.
let (a,b) = tuple
I know this may look like a tuple constructor to someone new to F#, or may look even odder because we have two values being bound to, (noticed I said bound and not assigned), but it takes the tuple with two values and destructured it into two separate values.
So here we do it using a destructuring expression.
let tuple = ("Hello", "world")
let (a,b) = tuple
printfn "%s %s" a b
or more commonly
let (a,b) = ("Hello", "world")
printfn "%s %s" a b

printfn in pipeline

So I have a function SolveEquasion that returns a pair float*float[]. What is the best way to print the number and the array and continue working with the array? I made the following code but it seems there is a better way
...
|> SolveEquasion
|> (fun (det, solution) -> printfn "Determinant = %f\nSolution = %A" det (Array.toList solution), solution )
|> snd
I don't think your solution can improved if you want to do this in a pipeline. Another approach is to use a let binding, along with splitting up the pipelined operations, to avoid having a function that acts like the love child of map and iter.
let (det, solution) = SolveEquasion
printfn "Determinant = %f\nSolution = %A" det (Array.toList solution)
//do something else with solution
I think the original solution is fine, and we can improve its clarity by giving your anonymous function the name I've seen it given in some other libraries based around pipelining higher-order functions: tap.
let tap f x =
f x
x
(1.0, [| 2.0; 3.0 |])
|> tap (fun (s, a) -> printfn "%A %A" s a)
|> snd
Well, for one thing you can skip the use of snd by returning a single value rather than a tuple from the previous function:
...
|> SolveEquasion
|> (fun (det, solution) ->
printfn "Determinant = %f\nSolution = %A" det (Array.toList solution)
solution )
I'd probably use Daniel's approach and just assign the value you want to print to a symbol using let. Alternatively, you could define a variant of printf that takes some arguments and returns one of them. I'm not sure if there is a general scheme how this should be done - for your example it would take a two-element tuple:
let mprintf fmt (a, b) =
Printf.kprintf (fun s -> printf "%s" s; (a, b)) fmt a b
Then you can write:
...
|> SolveEquasion
|> mprintfn "Determinant = %f\nSolution = %A"
|> snd |> // ... more stuff with solution

How do I concatenate a list of strings in F#?

I'm trying this at the moment, but I haven't quite got the method signature worked out... anyone? messages is a field of seq[string]
let messageString = List.reduce(messages, fun (m1, m2) -> m1 + m2 + Environment.NewLine)
> String.concat " " ["Juliet"; "is"; "awesome!"];;
val it : string = "Juliet is awesome!"
Not exactly what you're looking for, but
let strings = [| "one"; "two"; "three" |]
let r = System.String.Concat(strings)
printfn "%s" r
You can do
let strings = [ "one"; "two"; "three" ]
let r = strings |> List.fold (+) ""
printfn "%s" r
or
let strings = [ "one"; "two"; "three" ]
let r = strings |> List.fold (fun r s -> r + s + "\n") ""
printfn "%s" r
I'd use String.concat unless you need to do fancier formatting and then I'd use StringBuilder.
(StringBuilder(), [ "one"; "two"; "three" ])
||> Seq.fold (fun sb str -> sb.AppendFormat("{0}\n", str))
just one more comment,
when you are doing with string, you'd better use standard string functions.
The following code is for EulerProject problem 40.
let problem40 =
let str = {1..1000000} |> Seq.map string |> String.concat ""
let l = [str.[0];str.[9];str.[99];str.[999];str.[9999];str.[99999];str.[999999];]
l |> List.map (fun x-> (int x) - (int '0')) |> List.fold (*) 1
if the second line of above program uses fold instead of concat, it would be extremely slow because each iteration of fold creates a new long string.
System.String.Join(Environment.NewLine, List.to_array messages)
or using your fold (note that it's much more inefficient)
List.reduce (fun a b -> a ^ Environment.NewLine ^ b) messages

Resources