Read from Console in F#

10,225

Solution 1

It is indeed a shame that there is no such built-in function. However, as Brian mentioned in a comment on Benjol's answer, it is possible to build a scanf function yourself. Here's a quick sketch of how one might define a sscanf variant, although only %s placeholders are implemented:

open System
open System.Text
open System.Text.RegularExpressions
open Microsoft.FSharp.Reflection

let sscanf (pf:PrintfFormat<_,_,_,_,'t>) s : 't =
  let formatStr = pf.Value
  let constants = formatStr.Split([|"%s"|], StringSplitOptions.None)
  let regex = Regex("^" + String.Join("(.*?)", constants |> Array.map Regex.Escape) + "$")
  let matches = 
    regex.Match(s).Groups 
    |> Seq.cast<Group> 
    |> Seq.skip 1
    |> Seq.map (fun g -> g.Value |> box)
  FSharpValue.MakeTuple(matches |> Seq.toArray, typeof<'t>) :?> 't


let (a,b) = sscanf "(%s, %s)" "(A, B)"
let (x,y,z) = sscanf "%s-%s-%s" "test-this-string"

Solution 2

Combination of TryParse() and split/regex is what you can use "out of box".

P.S. i've seen http://www.codeproject.com/KB/recipes/csscanf.aspx and it works ;)

Solution 3

As far as I know, no.

It would be handy for code golf :)

Share:
10,225

Related videos on Youtube

Aurril
Author by

Aurril

I'm a software developer.

Updated on April 15, 2022

Comments

  • Aurril
    Aurril about 2 years

    Does anyone know if there is a builtin function for reading from the console likewise to the printfn function? The only method I've seen so far is using System.Console.Read() but it doesn't feel as functional as using a construct like printfn is.

  • Tim Robinson
    Tim Robinson about 14 years
    It's a shame the printfn function itself relies on compiler magic - you couldn't make your own F# sscanf quite as nice.
  • Prakash
    Prakash about 14 years
    You can do it, I think. The only magic is that string literals can be coerced to PrintfFormats, at which point the types are manifest: let pf() : PrintfFormat< _ , _ , _ , _ > = "%d %s"
  • wmeyer
    wmeyer almost 13 years
    When I needed a more complete version of sscanf, it was quite easy to extend this code. See the result here: fssnip.net/4I
  • Mauricio Scheffer
    Mauricio Scheffer over 12 years
    @wmeyer : would you be interested in contributing this to FSharpx? github.com/fsharp/fsharpx
  • Rei Miyasaka
    Rei Miyasaka over 11 years
    @wmeyer Problem with this implementation is that it doesn't work so well when you have only one element, because then the MakeTuple barfs...
  • Rei Miyasaka
    Rei Miyasaka over 11 years
    Quick fix: replace the last MakeTuple line with: if matches.Length = 1 then matches.[0] :?> 't; else FSharpValue.MakeTuple(matches, typeof<'t>) :?> 't
  • wmeyer
    wmeyer over 11 years
    @Rei: Cool! If you want to, you can even fix it directly on fssnip! (I think)
  • Rei Miyasaka
    Rei Miyasaka over 11 years
    @wmeyer Oh, didn't notice. Done!