Moe
Moe

Reputation: 65

f# how to access the data from another function?

I am having trouble with accessing a value from another function in f sharp. Below is my code, I am taking the user input a student name and 3 exam scores and calculating their averages and saving that in the variable "let average" of the InputStudents function. Now I am trying to access that value in another function PringtAverages as shown below, but it would not compile. I need help to fix this issue. Appreciate if you can help. Thank you.

let rec InputStudents students =
    let line = System.Console.ReadLine()
    match line with
    | "#" -> (List.rev students)
    |  _  -> 
    let data = line.Split ' '
    //Getting the student name at data.[0], and getting the 3 exam 
    //scores in data.[1]..[3].
    let student = (data.[0], [int(data.[1]); int(data.[2]); int(data.[3])])
    //calculating the average by for the 3 exam scores
    let average = (data.[0], [(float(data.[1]) + float(data.[2]) + float(data.[3]))/3.0])
    InputStudents (student:: students) 

 //Function below I am trying to get the above-calculated averages and print
let rec PrintAverages L = 
    match L with
    | []      -> ()   
    | e::rest -> 
           let avg = InputStudents[]
           printfn "%A: %A" "netid" avg.average //Here I am trying to print 
                              //the average calculated in the function 
                             //InputStudents[] above
           PrintAverages rest

Upvotes: 0

Views: 117

Answers (1)

AMieres
AMieres

Reputation: 5004

That is not possible.

You cannot access internal calculations from another function. What you need to do is return the values that you need to use outside.

In your case your function InputStudents has the following signature:

(string * int list) list -> (string * int list) list

Which means it returns a list with each student name and notes. The average is calculated but then is lost, because it is not used anywhere. If you want to be able to print it in another function you need to include it as part of the return value:

         ...
         let name    =        data.[0]
         let scores  = [float data.[1]
                        float data.[2]
                        float data.[3] ]
         //calculating the average by for the 3 exam scores
         let average = List.average scores
         InputStudents ((name, scores, average) :: students)

now the signature is this:

(string * float list * float) list -> (string * float list * float) list

indicating it returns a tuple for each student that includes name, notes and average.


Now lets address the PrintAverages function.

The function has a problem: it calls InputStudents and it calls itself recursively. What you want to do is call first InputStudents and then pass the result to PrintAverages:

InputStudents [] |> PrintAverages

Also in your match statement you can unpack the tuple that you are receiving. Right now you have e::rest which gives you one element and the rest of the list. That element would be of type string * float list * float which you can unpack like this:

let name, notes, average = e

or directly in the match statement:

match L with
| [] -> ()
| (name, notes, average) :: rest ->

Upvotes: 1

Related Questions