I am looking to convert this code to use F# list instead of the C# list implementation.
I am connecting to a database and running a query usually with C# would create a list of a type and keep adding the list while the datareader has values. How would I go about converting this to use an F# list
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
let transactions = new List<string>()
let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
let json = dataReader.GetString(1)
transactions.Add(json)
transactions
The tricky thing here is that the input data source is inherently imperative (you have to call Read which mutates the internal state). So, you're crossing from imperative to a functional world - and so you cannot avoid all mutation.
I would probably write the code using a list comprehension, which keeps a similar familiar structure, but removes explicit mutation:
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
[ let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
yield dataReader.GetString(1) ]
Tomas' answer is a solution to use in product code. But for sake of learning F# and functional programming I present my snippet with tail recursion and cons operator:
let drToList (dr:DataReader) =
let rec toList acc =
if not dr.Read then acc
else toList <| dr.GetString(1) :: acc
toList []
This tail recursion function is compiled into imperative-like code, thus no stack overflow and fast execution.
Also I advice you look at this C# thread and this F# documentation to see how properly dispose your command. Basically, you need to use smth like this:
let queryDb (conn: NpgsqlConnection) (qStr: string) =
use cmd = new NpgsqlCommand(qStr, conn)
cmd.ExecuteReader() |> drToList
And if we go deeper, you should also think about exception handling.
Related
So, I found out that Ocaml supports the creation of circular lists using let rec.
utop # let rec ones = 1::ones;;
val ones : int list = [1; <cycle>]
That is pretty neat, and it even prints out in utop without blowing up.
But when I try to use List.map on this kind of data it does blow up:
utop # let twos = List.map ((+) 1) ones;;
Stack overflow during evaluation (looping recursion?).
Raised by primitive operation at Stdlib__List.map in file "list.ml", line 92, characters 32-39
Called from Stdlib__List.map in file "list.ml", line 92, characters 32-39
...
That is somewhat disapointing, though not totally unexpected.
Now the question, would it be possible to implement a 'better' map function that can handle this properly. I.e. you would do something like:
let twos = betterMap ((+) 1) ones;;
And instead of blowing up it would be able to detect the cycle properly and produce:
val twos : int list = [2; <cycle>]
Since the list of ones, though looping back on itself, is effectively a finite structure, it feels like this should be possible. But how?
It is only possible to create cyclic lists when the cycle is statistically known. It is thus impossible to create a map function that works on any cyclic lists without knowing in advance the topology of cycles in the list. For instance, this function works for lists that are 1-cycle:
let map_1_cycle f = function
| [] -> []
| a :: l ->
let rec answer = f a :: answer in
answer
The generic solution is to use sequences since as a form of lazy list, they have a much better support for infinite sequences of elements:
let ones = Seq.repeat 1
let twos = Seq.map ((+) 1) ones
I need to modify an OCaml function:
let removeDuplicates l =
let rec helper (seen,rest) =
match rest with
[] -> seen
| h::t ->
let seen' = failwith "to be written" in
let rest' = failwith "to be written" in
helper (seen',rest')
in
List.rev (helper ([],l));;
The function needs to take a list l and return the list with all duplicates removed. The failwith "to be written" parts is where I'm supposed to write my code. I understand how the helper function works but am having trouble understanding this part helper (seen',rest'). I'm not exactly sure how the function is supposed to flow with this part or how it works when you include a bunch of in's all together. We are allowed to use List.rev which reverses a list and list.mem which returns true if a certain element is in a list. Can someone please explain to me how the flow of the function is supposed to work so I can start to write a solution.
That line is confusing because it's indented incorrectly, or so I would claim. The proper indentation looks like this:
let seen' = failwith "to be written" in
let rest' = failwith "to be written" in
helper (seen',rest')
What it's saying is: calculate a new value for seen and a new value for rest, then call yourself recursively with the two new values.
Answers to this question do a good job of explaining how to use Scala's Java Converters to change a Java List into a Scala List. Unfortunately, I need to convert a List of Lists from Java to Scala types, and that solution doesn't work:
// pseudocode
java.util.List[java.util.List[String]].asScala
-> scala.collection.immutable.List[java.util.List[String]]
Is there a way to do this conversion without an O(N) iteration over the Java object?
You need to convert the nested lists as well, but that would require the up front O(n):
import scala.collection.JavaConverters._
val javaListOfLists = List(List("a", "b", "c").asJava, List("d", "e", "f").asJava).asJava
val scalaListOfLists = javaListOfLists.asScala.toList.map(_.asScala.toList)
Alternatively, you could convert the outer list into a Stream[List[T]], that would only apply the conversion cost as you accessed each item
val scalaStreamOfLists = javaListOfLists.asScala.toStream.map(_.asScala.toList)
If you don't want to pay the conversion cost at all, you could write a wrapper around java.util.List which would give you a scala collection interface. a rought shot at that would be:
def wrap[T](javaIterator: java.util.Iterator[T]): Stream[T] = {
if (javaIterator.hasNext)
javaIterator.next #:: wrap(javaIterator)
else
empty
}
val outerWrap = wrap(javaListOfLists.iterator).map(inner => wrap(inner.iterator()))
alternatively you can use scalaj-collection library i wrote specifically for this purpose
import com.daodecode.scalaj.collection._
val listOfLists: java.util.List[java.util.List[String]] = ...
val s: mutable.Seq[mutable.Seq[String]] = listOfLists.deepAsScala
that's it. It will convert all nested java collections and primitive types to scala versions. You can also convert directly to immutable data structures using deepAsScalaImmutable (with some copying overhead of course)
Me coming from a c# and python background, feels there must be a better way to read a file and populate a classic F# list. But then I know that a f# list is immutable. There must be an alternative using a List<string> object and calling its Add method.
So far what I have at hand:
let ptr = new StreamReader("stop-words.txt")
let lst = new List<string>()
let ProcessLine line =
match line with
| null -> false
| s ->
lst.Add(s)
true
while ProcessLine (ptr.ReadLine()) do ()
If I were to write the similar stuff in python I'd do something like:
[x[:-1] for x in open('stop-words.txt')]
Simple solution
System.IO.File.ReadAllLines(filename) |> List.ofArray
Although you can write a recursive function
let processline fname =
let file = new System.IO.StreamReader("stop-words.txt")
let rec dowork() =
match file.ReadLine() with
|null -> []
|t -> t::(dowork())
dowork()
If you want to read all lines from a file, you can just use ReadAllLines. The method returns the data as an array, but you can easily turn that into F# list using List.ofArray or process it using the functions in the Seq module:
open System.IO
File.ReadAllLines("stop-words.txt")
Alternatively, if you do not want to read all the contents into memory, you can use File.ReadLines which reads the lines lazily.
This is the error I'm getting and I have no idea why: "Error: Unbound record field label length "
Does anyonw know?
let rastavi str =
let sublist = ref [] in
let list = ref [] in
for i = ((str.length str)1) [down]to 0 do
if str.[i] =' ' then (str.[i] :: !sublist)
else (list := (!sublist:: !list)) sublist = []
done ;;
You're using OO notation to get the length of a string. OCaml uses functional notation. So it looks like this:
String.length str
Not like this:
str.length (* OO notation, not in OCaml *)
Edit:
Side comment: this solution is very much an imperative take on the problem. If you're trying to learn the FP mindset, you should try to think recursively and immutably. Since this looks like homework, it's very likely a functional solution is what you want.
But here are a few other problems in your original code:
You have two expressions next to each other with nothing in between. If you want to "do" two things, you need to separate them with a semicolon ; (however, this is imperative style)
You're using = which compares two values for equality. If you want to assign a value to a reference you need to use :=. (Imperative style, again.)