I want to read a whole file into a string and then use the function lines to get the lines of the string. I'm trying to do it with these lines of code:
main = do
args <- getArgs
content <- readFile (args !! 0)
linesOfFiles <- lines content
But I'm getting the following error by compiling ad it fails:
Couldn't match expected type `IO t0' with actual type `[String]'
In the return type of a call of `lines'
In a stmt of a 'do' block: linesOfFiles <- lines content
I thought by binding the result of readFile to content it will be a String DataType, why isn't it?
I thought by binding the result of readFile to content it will be a String DataType, why isn't it?
It is a String indeed, that's not what the compiler complains about. Let's look at the code:
main = do
args <- getArgs
content <- readFile (args !! 0)
Now content is, as desired, a plain String. And then lines content is a [String]. But you're using the monadic binding in the next line
linesOfFiles <- lines content
in an IO () do-block. So the compiler expects an expression of type IO something on the right hand side of the <-, but it finds a [String].
Since the computation lines content doesn't involve any IO, you should bind its result with a let binding instead of the monadic binding,
let linesOfFiles = lines content
is the line you need there.
Related
I want to know how to transform the results of an iterator into an array. I have presented two options below, and both run, but yield the result in the wrong format.
This is the result I am getting vs what is expected.
enter image description here
I am trying to transform the iterator results into an array with Array(), but it does not work.
I tried:
Block code with .keep_if methods
for if conditionals with Array() to make the transformation.
What I expect:
An array of non-negative integers. The input (l) is an array of random integers and strings.
My code options are as follows:
Option 1:
def filter_list(l)
l.delete_if {|li| li.class ==String || li<0}
puts l
end
Option 2:
def filter_list(l)
arr=[]
for i in l
if i.class == Integer && i>=0
arr1=arr.push(i)
end
end
puts Array(arr1)
end
Why don't the above options work?
Why don't the above options work?
You have a syntax error here:
Def filter_list(l)
↑
Method definitions use the def keyword with a lower-case d. What you have written here will be interpreted as a method call to a method named Def, passing filter_list(l) as an argument, i.e. that code will be interpreted as
self.Def(filter_list(l))
Which then means that Ruby is not expecting to see an end keyword.
To output the result in the expected format just use p instead of puts.
From the docs of puts
[...] If called with an array argument, writes each element on a new line. Each given object that isn't a string or array will be converted by calling its to_s method. [...]
Whereas the p method doesn't call to_s but inspect before printing the output:
For each object, directly writes obj.inspect followed by a newline to the program's standard output.
The default string representation, returned by inspect for an array, looks like your expected output.
I have a .csv file holding scores. This is what it looks like:
"name",10
The .csv is parsed with this function:
func _ready():
var file = File.new()
file.open("user://scores.csv", file.READ)
while !file.eof_reached():
line = file.get_csv_line()
text = text + "%s: %s" % [line[0], line[1]] + "\n" ## Invalid get index: '1' (on base: PoolStringArray)
The file must be ending in a new line. As a result, you get two lines while reading it. The first one has what you expect ([name, 10]), the second one is empty, causing an error when you try to index it.
When I tested this, the last line does not come as an empty array, but as an array with a single empty string. Looking around, this behavior has been there for a while. However, I found no bug reports or proposals, I wonder if there is a reason, or this was just overlooked.
You can check the number of columns you got. For example, the code below would skip any lines with not enough fields for your case:
if line.size() < 2:
continue
And this code will specifically target the extra line:
if file.eof_reached() and line.size() == 1 and line[0] == "":
break
i am trying to read content of the file using readData function .I am able to read data from the file currently it is displaying size of content read from file but i want actual content of the file .
Code using for reading file
var fileHandle = FileHandle(forReadingAtPath: FullFileName as String)
var data = fileHandle?.readData(ofLength: 10)
var availabledata = fileHandle!.availableData
print("data")
print(data)
print("availabledata")
print(availabledata)
Output
data
Optional(10 bytes)
availabledata
11 bytes
Q1. How can i print actual content read from the file ?
please suggest method related to the readData function only .
How can i print actual content read from the file ? please suggest method related to the readData function only .
The question isn't really tied to readData – this function returns Data?, an optional value. When you print this you will get Option(x bytes) where the x bytes is the .description of the value.
If you wish to print the byte values you need to write something to produce your desired format. For example:
print(data?.map { $0 })
will print the data as an array of UInt8. If you wish to format each byte differently, say as hex, change the closure to produce the format you wish – each byte gets passed to the closure as a UInt8 value.
This is far from the only way to do it, you just need to wrote what you need as Data itself doesn't provide a description that meets your needs.
HTH
The following code :
(spit "/Users/nha/tmp/spit.txt" (.getBytes "hello"))
produces a file containing "[B#71e054bc", which is independent of the content ("hello" in this case) since this is the JVM representation of the address of a byte array.
However the following works (taken from this SO post):
(clojure.java.io/copy
(.getBytes "hello")
(java.io.File. "/Users/nha/tmp/spit.txt"))
And the file then contains the correct content "hello".
Why does spit behave like this ? Is there a way to expand it's behaviour for bytes ?
This problem isn’t particular to byte arrays.
(spit "spit.txt" (Object.))
(slurp "spit.txt") ;; => "java.lang.Object#90b293d"
Looking at the source of spit you’ll see that it simply tries to obtain the string representation of the argument before writing it out.
You could try to wrap any byte array in a new string before writing, but take care to select the proper encoding.
;; platform-dependent!
(spit "spit.txt" (String. b))
;; better
(spit "spit.txt" (String. b java.nio.charset.StandardCharsets/UTF_8))
the reason is that the content is passed to str
you can check that via (source spit):
user=> (source spit)
(defn spit
"Opposite of slurp. Opens f with writer, writes content, then
closes f. Options passed to clojure.java.io/writer."
{:added "1.2"}
[f content & options]
(with-open [^java.io.Writer w (apply jio/writer f options)]
(.write w (str content))))
; - ^^^ - here
therefor you get the string representation of the byte-array written
EDIT: and since spit the "inverse" of slurp which gives you a string, it makes sense and is consistent behaviour
I'm currently working on project with Haskell, and have found myself some trouble. I'm supposed to read and insert into a list each line in a "dictionary.txt" file, but I can't seem to do so. I've got this code:
main = do
let list = []
loadNums "dictionary.txt" list
loadNums location list = do
inh <- openFile location ReadMode
mainloop inh list
hClose inh
mainloop inh list = do
ineof <- hIsEOF inh
if ineof
then return ()
else do
inpStr <- hGetLine inh
inpStr:list
mainloop inh list
It is supposed to get every line (I know it does get every line, since replacing the "inpStr:list" with a "putStrLn inpStr" works correctly, displaying all lines), and insert it into a list but I get the following error:
Couldn't match expected type `IO' against inferred type `[]'
Probably because the hGetLine isn't a String, but a IO String, which I have no idea how to handle in order to obtain a proper string I can insert in my list. I have no idea how this could be solved, or what the problem is exactly, but if anyone has any idea of how to properly get every line in a file into a list, I'd appreciate it.
Thanks in advance!
Unless this is for homework or something, there's no reason to use so much effort. Reuse is lazy!
getLines = liftM lines . readFile
main = do
list <- getLines "dictionary.txt"
mapM_ putStrLn list
But as you seem to still be learning Haskell, it is important for you to understand what CesarB has written.
In the line where the error happens, Haskell is expecting "IO a", but you are giving it a []. Simplifying things a lot, on a do block on the IO monad, every line is either:
Something which returns a value of the "IO a" type; the value of the "a" type within it is discarded (so the "a" is often "()")
A <- expression, which does the same thing but instead of discarding the value of the "a" type gives it the name to the left of the <-
A let, which does nothing more than give a name to a value
In that do block, the "hGetLine inh" returns an "IO String", and the String within it is extracted and given the name inpStr. The next line, since it's neither a let or a <-, should have a type "IO a", which it doesn't (thus causing the compiler error). What you can do instead, since you already have the String, is a let:
let list' = inpStr:list
This creates a new list consisting of the String followed by the original list, and gives it the name of "list' ".
Change the following line to use "list' " instead of "list" (thus passing it the new list). That line calls (recursively) mainloop, which will read one more line, call itself, and so on. After reading the whole file, it will return something with the "IO ()" type. This "IO ()" will be returned to the do block at loadNums. Congratulations, you just created a list with the lines read from the file, in reverse order (since you were appending to the head of the list), and then did nothing to it.
If you want to do something to it, change the "return ()" to "return list"; the return will generate a value of type "IO [String]", with the list within it (return does nothing more than encapsulating the value), which you can extract at loadNums with the <- syntax.
The rest is left as an exercise to the reader.