1

NOTE: I'm totally Newbie in Standard ML. I merely have basic F# knowledge.

This is a good ol' code in C

#include <stdio.h>

int main()
{
  char str[100]; // size whatever you want

  scanf("%s", str);
  printf("%s\n", str);
  return 0;
}

now, I want to make a Standard ML-version-equivalent of this code. so I tried this:

val str = valOf (TextIO.inputLine TextIO.stdIn)
val _ = print str

but my SML/NJ says this:

uncaught exception Option
 raised at: smlnj/init/pre-perv.sml:21.28-21.34

I googled it, and I also searched this site, but I cannot find any solution which doesn't cause error.

does anyone knows it?

EDIT: I tried this code:

fun main =
    let val str = valOf (TextIO.inputLine TextIO.stdIn)
    in
        case str
            of NONE => print "NONE\n"
            | _     => print str
    end

but it also makes error:

stdIn:1.6-1.10 Error: can't find function arguments in clause
stdIn:4.9-6.33 Error: case object and rules don't agree [tycon mismatch]
  rule domain: 'Z option
  object: string
  in expression:
    (case str
      of NONE => print "NONE\n"
       | _ => print str)
Jihoo Byeon
  • 69
  • 1
  • 8
  • You're assuming that `TextIO.inputLine` did not return `NONE`, but it did. – molbdnilo Jun 24 '20 at 14:25
  • @molbdnilo Oh, then what am I have to do? – Jihoo Byeon Jun 24 '20 at 14:28
  • Use pattern matching to examine the result, like in F#. – molbdnilo Jun 24 '20 at 14:29
  • Pattern matching is more convenient than in F#; `case expression of case1 => expr1 | case2 => expr2 | ...` – molbdnilo Jun 24 '20 at 14:37
  • @molbdnilo Thanks for your advice, but I still can't get a clue. I edited original post. – Jihoo Byeon Jun 24 '20 at 14:49
  • The expression you need to match on is `TextIO.inputLine TextIO.stdIn`. Don't use `valOf` at all. – molbdnilo Jun 24 '20 at 14:52
  • This [question](https://stackoverflow.com/questions/28185770/operator-and-operand-dont-agree-tycon-mismatch-sml-assuming-the-wrong-list) may have some bearing on this for you. It mentions that tycon mismatch error you're seeing. – Onorio Catenacci Jun 24 '20 at 14:53
  • @molbdnilo OK, I tried without `valOf`, and changed `print str` to `print "SOME\n"`, now it only says this: `stdIn:1.6-1.10 Error: can't find function arguments in clause` – Jihoo Byeon Jun 24 '20 at 14:55
  • @OnorioCatenacci Thanks, but `tycon mismatch` error has gon after I erased `valOf` – Jihoo Byeon Jun 24 '20 at 14:58
  • Rather than a bunch of back and forth on this may I suggest you look at Rosetta Code for some basic SML code to start with? For example, [this code](http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Standard_ML) which is for determining if string input is numeric. Not exactly what you're asking but it may give you some ideas of how to proceed. – Onorio Catenacci Jun 24 '20 at 15:00
  • @OnorioCatenacci Oh, Thanks! – Jihoo Byeon Jun 24 '20 at 15:01
  • Try `case TextIO.inputLine TextIO.stdIn of SOME s => print s | NONE => print "Nothing";` – molbdnilo Jun 24 '20 at 15:06
  • You can't write a function that takes no arguments, like your `main`. The convention is to use the `unit` value, `()`: `fun main () = ...`. (You've seen it in `val it = () :unit`.) – molbdnilo Jun 24 '20 at 15:11
  • @molbdnilo OK, your code works fine on interactive mode(`sml test.sml`), but in compile mode(`sml – Jihoo Byeon Jun 24 '20 at 15:26
  • [this](http://rosettacode.org/wiki/User_input/Text#Standard_ML) also works fine on interactive mode, but raises `uncaught exception Option raised at: smlnj/init/pre-prev.sml:25.28-25.34` on compile mode. – Jihoo Byeon Jun 24 '20 at 15:31
  • @Julien That's not "compile mode", it's "use this file instead of the terminal as standard input". It works exactly like it does interactively, except the input ends when the file ends. You need to use my suggestion inside a function and then call that function. (And not redirect a file as standard input.) – molbdnilo Jun 24 '20 at 15:38
  • @molbdnilo Oh, I didn't knew that! thanks for correcting my error. – Jihoo Byeon Jun 24 '20 at 15:41
  • Does this answer your question? [How to read string from user keyboard in SML language?](https://stackoverflow.com/questions/62236458/how-to-read-string-from-user-keyboard-in-sml-language) – sshine Jun 25 '20 at 13:24

1 Answers1

1

This answer was pretty much given in the next-most recent question tagged sml: How to read string from user keyboard in SML language? -- you can just replace the user keyboard with stdin, since stdin is how you interact with the keyboard using a terminal.

So you have two problems with this code:

fun main =
    let val str = valOf (TextIO.inputLine TextIO.stdIn)
    in
        case str
            of NONE => print "NONE\n"
            | _     => print str
    end

One problem is that if you write fun main then it has to take arguments, e.g. fun main () = .... The () part does not represent "nothing" but rather exactly one thing, being the unit value.

The other problem is eagerness. The Option.valOf function will crash when there is no value, and it will do this before you reach the case-of, making the case-of rather pointless. So what you can do instead is:

fun main () =
    case TextIO.inputLine TextIO.stdIn of
         SOME s => print s
       | NONE => print "NONE\n"

Using the standard library this can be shortened to:

fun main () =
    print (Option.getOpt (TextIO.inputLine TextIO.stdIn, "NONE\n"))

I encourage you to read How to read string from user keyboard in SML language?

sshine
  • 15,635
  • 1
  • 41
  • 66