9

I am new to SML (and programming, actually).

fun readlist (infile : string) =  

  let
  val 
      ins = TextIO.openIn infile 

      fun loop ins = 

      case TextIO.inputLine ins of 

      SOME line => line :: loop ins 

    | NONE      => [] 

  in 

     loop ins before TextIO.closeIn ins 

  end ;

This is a program I encountered here. How do I use SOME and NONE, and how to use 'before'?

Marvin
  • 229
  • 1
  • 3
  • 11
Rohan
  • 93
  • 1
  • 1
  • 4
  • 5
    At your current level, you had better learn SML by reading a tutorial. Reading programs and asking about each word you encounter that you don't understand is not going to be efficient use of anyone's time. Try http://homepages.inf.ed.ac.uk/stg/NOTES/notes.pdf (first link when googling “SML tutorial”) – Pascal Cuoq Jul 27 '14 at 12:47
  • You should look for the "option" data type to learn more about your question. – Joomy Korkut Jul 27 '14 at 15:50
  • 5
    @PascalCuoq What I see is a person who has looked at a program that does something very practical - getting data from a file - and is trying to understand what it is doing. Unfortunately *Programming in Standard ML ’97: A Tutorial Introduction* to which you linked assumes the reader already has knowledge of the `option` structure, i.e. the first use is *"the results from the Bool.fromString function are either NONE or SOME b"* because tutorial assumes experience with C: e.g. "*A familiar C programming metaphor for processing files may be easily implemented in Standard ML.*" – ben rudgers Jul 28 '14 at 14:59
  • @benrudgers I am not saying that there isn't a problem with the ML tutorials available. I picked the first one because I wouldn't recognize a good one from a bad one, if a good one even exists. But trying to read a program that uses `TextIO.openIn` before you have encountered your first option type is not going to be a good programming-learning experience. – Pascal Cuoq Jul 28 '14 at 15:04
  • 1
    @PascalCuoq It is a good tutorial. But C isn't the only language to come out of Bell Labs. There is a vast class of beginner level programs where reading a file from a disk vastly improves efficiency - entering data in the REPL or inserting magic numbers in source can be great for debugging, but are often cumbersome for data processing. I see how your comment made the internet better. – ben rudgers Jul 28 '14 at 15:21

2 Answers2

10

The option data type is used if there is a possibility of something having no valid value.

For instance,

fun divide x y = if y == 0 then NONE else SOME (x / y)

could be used if you need to handle the special case of division by zero without resorting to exceptions.

TextIO.inputLine returns NONE when there is nothing more to read, and SOME l, where l is the line it has read, when there is.

before is a low-precedence (the lowest of all) infix function that first evaluates its left hand side, then the right hand side, and then returns the value of the left hand side.
It has type 'a * unit -> 'a, i.e. the right hand side is used only for its side effects.

In this case, it makes the code slightly more readable (and functional-looking) than the equivalent

fun readlist (infile : string) =  
  let
      val ins = TextIO.openIn infile 
      fun loop indata = 
          case TextIO.inputLine indata of 
              SOME line => line :: loop indata 
            | NONE      => []
      val result = loop ins
  in 
     TextIO.closeIn ins;
     result
  end 
Andreas Rossberg
  • 34,518
  • 3
  • 61
  • 72
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
6

Some('a) and None are part of the Option datatype. Option is an algebraic or compound data structure found in SML's Basis Library. More on the Option data type at Wikipedia. The big idea is, allow a function to return the value None when it doesn't make sense for the function to return a value of the type which the programmer really cares about.

In the case of your user defined function readlist the important data is the string. But at some point, the program hits the end of the file and reads a value interpreted as EOF instead of a string.

Think about TextIO.openIn as a function that opens a stream and searches it for strings. Each time it finds a string, it returns an option(string). When it does not find a string, it returns None. Because both are part of the Option(string) datatype, TextIO.openIn only returns a single type.

inputLine strm a stream] returns SOME(ln), where ln is the next line of input in the stream strm. Specifically, ln returns all characters from the current position up to and including the next newline (#"\n") character. If it detects an end-of-stream before the next newline, it returns the characters read appended with a newline. Thus, ln is guaranteed to always be new-line terminated (and thus nonempty). If the current stream position is the end-of-stream, then it returns NONE. It raises Size if the length of the line exceeds the length of the longest string.

A related concept in SML is user-defined datatypes. Both the option datastructure and user-defined data types provide flexibility within SML's static type system in a somewhat similar manner to the way objects are used in statically typed object oriented languages.

ben rudgers
  • 3,647
  • 2
  • 20
  • 32