Why doesn't Console.Readline work but Console.Readline() does?

16,782

Solution 1

If you use

let s = Console.ReadLine

you are only building a delegate that points to the ReadLine function. You need to say

let s = Console.ReadLine()

to actually execute the function. This is just like C# syntax, except type inference means you don't get a compiler warning.

Solution 2

What do you mean by "it isn't being honored"? Here's a small console app I've just written in VS2010b1, and it works fine:

open System

let line = Console.ReadLine()
Console.WriteLine("You wrote {0}", line)

// Just to make it pause
let unused = Console.ReadLine()

Are you trying to run the code from F# Interactive within Visual Studio? If so, that may be the issue, as Brian's post explains.

However, I haven't seen the same problem when using F# Interactive from the command line. Here's a complete transcript of a session:

Microsoft F# Interactive, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.9.6.16, compiling for .NET Framework Version v4.0.20506

Please send bug reports to [email protected]
For help type #help;;

> open System;;
> let line = Console.ReadLine();;
Hello world

val line : string = "Hello world"

Running Brian's looping code from F# Interactive didn't show the same problem.

Bottom line: It seems like this is broken in F# Interactive in Visual Studio, but not when running interactively from the command line or in a full console app.

Solution 3

I don't have a Beta1 box handy, but I know that in the past we've had a bug where ReadLine() would see the background commands that communicate between the interactive UI and the background process that runs your F# code. It may be interesting to investigate what

let Foo max =
    let rec Loop i =
        if i < max then
            let line = System.Console.ReadLine() 
            printfn "line = %s" line
            Loop (i+1)
    Loop 1

Foo 12

prints when you highlight it and 'Send to Interactive'. I think possibly you'll see a few unexpected interesting lines, followed by lines you type into the window.

Share:
16,782
Jonathan Allen
Author by

Jonathan Allen

Editor for InfoQ

Updated on June 03, 2022

Comments

  • Jonathan Allen
    Jonathan Allen almost 2 years

    How do you use Console.Readline in F#? Unlike Console.Writeline, it isn't being honored when I call it.

  • Jon Skeet
    Jon Skeet almost 15 years
    Yup, that looks like it could be the problem: when I try that in beta 1, the first line written out is just "line = "
  • Jon Skeet
    Jon Skeet almost 15 years
    Hmmm... that's odd. Is this with the version installed with VS2010b1?
  • Jonathan Allen
    Jonathan Allen almost 15 years
    Weird. Yesterday I couldn't get it to work no matter what I tried. Now I can't get it to fail, again no matter what I try.
  • Jonathan Allen
    Jonathan Allen almost 15 years
    The difference is that you are putting empty parens on the end of the ReadLine call and I wasn't.
  • Jonathan Allen
    Jonathan Allen almost 15 years
    I figured it out. "Console.ReadLine()" works. "Console.ReadLine" is silently ignored because it is just building a delegate.
  • Jon Skeet
    Jon Skeet almost 15 years
    Ah, I assumed you were actually calling it as you mentioned Console.WriteLine() :) Anyway, glad the mystery is solved!
  • YotaXP
    YotaXP almost 15 years
    Yup. Console.ReadLine is a "unit -> string" value. By adding the (), you're passing in the 'unit' that it is expecting as an argument.
  • Jonathan Allen
    Jonathan Allen almost 15 years
    So did I. I'm used to VB where the parens are optional and you have to indicate when you want the function itself.
  • Jon Skeet
    Jon Skeet almost 15 years
    Ah... I wondered whether that might be the case, but felt foolish suggesting it :)
  • Jonathan Allen
    Jonathan Allen almost 15 years
    Given how subtle the difference is, I'm sure you will get many more chances to ask that question.
  • Erik Forbes
    Erik Forbes almost 15 years
    "let unused = Console.ReadLine()" would be more F# idiomatic as "Console.ReadLine() |> ignore" - this removes the need for a useless 'let' statement and handles ignoring the return value.
  • Robert Jeppesen
    Robert Jeppesen about 13 years
    +1 - This behaviour could be made clearer by requiring a space in front of the (), just like any other argument to a function.
  • Arturo Hernandez
    Arturo Hernandez about 9 years
    You would get a compiler warning! When you make use s. It sounds like you meant to write Console.ReadLine() |> ignore. I would argue that it is C# that does not check whether the output of a function is either captured or ignored.