Loading ...
Sorry, an error occurred while loading the content.

reading files into list

Expand Messages
  • oliver@first.in-berlin.de
    Hello, I want to read a file into a list. ######################################### type read_file = Line of string | ENDE let rec ap chan li = let res = try
    Message 1 of 3 , Feb 4, 2003
    • 0 Attachment
      Hello,


      I want to read a file into a list.

      #########################################
      type read_file = Line of string | ENDE

      let rec ap chan li =
      let res =
      try
      Line (input_line chan)
      with _ -> ENDE
      in
      match res with
      ENDE -> li
      | l -> res :: ap chan li
      #########################################

      I would prefer to work on plain lists.
      But if I want to do it, my solution would look like this:

      #########################################
      let rec ap chan li =
      let res =
      try
      input_line chan
      with _ -> ""
      in
      match res with
      "" -> li
      | l -> res :: ap chan li
      #########################################


      Is there a way to have a unique identifier
      (ENDE or such stuff (EOF) instead of the
      empty string?
      If the read would return the empty string,
      then this would be detected as an EOF.
      This may cause problems, depending on the read data.

      In my data this will not be a problem, but I want
      to have a function without ambiguities, so that
      I can reuse the code in other programs, where
      the input_line-function may return empty strings.

      Any hints?

      Ciao,
      Oliver
    • Michel Quercia
      ... You can try this : let rec input_lines chan = try let l = input_line chan in l::(input_lines chan) with _ - [] ;; Note that you may run out of stack space
      Message 2 of 3 , Feb 4, 2003
      • 0 Attachment
        Le Tue, 4 Feb 2003 21:14:34 +0100 oliver@...-berlin.de écrivit:

        > I want to read a file into a list.
        > #########################################
        > let rec ap chan li =
        > let res =
        > try
        > input_line chan
        > with _ -> ""
        > in
        > match res with
        > "" -> li
        > | l -> res :: ap chan li
        > #########################################
        >
        >
        > Is there a way to have a unique identifier
        > (ENDE or such stuff (EOF) instead of the
        > empty string?

        You can try this :

        let rec input_lines chan =
        try let l = input_line chan in l::(input_lines chan)
        with _ -> []
        ;;

        Note that you may run out of stack space if the file has too many lines because there is a "try ... with" block for each recursive call. Here is an imperative solution with only one "try ... with" block :

        let input_lines chan =
        let res = ref [] in
        begin
        try
        while true do res := (input_line chan) :: !res done
        with _ -> ()
        end;
        List.rev !res
        ;;

        There is still a (less acute) risk of stack overflow due to the call to List.rev though.

        --
        Michel Quercia
        23 rue de Montchapet, 21000 Dijon
        http://michel.quercia.free.fr (maths)
        http://pauillac.inria.fr/~quercia (informatique)
        mailto:michel.quercia@...
      • Remi VANICAT
        ... Well it is not the only reason. The fact that the result of the recursive call is the tail of the new list is the other one. Remark that the original
        Message 3 of 3 , Feb 4, 2003
        • 0 Attachment
          Michel Quercia <michel.quercia@...> writes:

          > Le Tue, 4 Feb 2003 21:14:34 +0100 oliver@...-berlin.de écrivit:
          >
          >> I want to read a file into a list.
          >> #########################################
          >> let rec ap chan li =
          >> let res =
          >> try
          >> input_line chan
          >> with _ -> ""
          >> in
          >> match res with
          >> "" -> li
          >> | l -> res :: ap chan li
          >> #########################################
          >>
          >>
          >> Is there a way to have a unique identifier
          >> (ENDE or such stuff (EOF) instead of the
          >> empty string?
          >
          > You can try this :
          >
          > let rec input_lines chan =
          > try let l = input_line chan in l::(input_lines chan)
          > with _ -> []
          > ;;
          >
          > Note that you may run out of stack space if the file has too many
          > lines because there is a "try ... with" block for each recursive
          > call.

          Well it is not the only reason. The fact that the result of the
          recursive call is the tail of the new list is the other one.

          Remark that the original function had the same problem, and this is
          not such a problem if the files are not big.

          > Here is an imperative solution with only one "try ... with"
          > block :
          >
          > let input_lines chan =
          > let res = ref [] in
          > begin
          > try
          > while true do res := (input_line chan) :: !res done
          > with _ -> ()
          > end;
          > List.rev !res
          > ;;
          >
          > There is still a (less acute) risk of stack overflow due to the call
          > to List.rev though.

          No. List.rev is tail recursive, there is no risk of stack overflow
          here.

          Here is the tail recursive version :

          let input_lines chan =
          let rec input_lines_helper res =
          let sl =
          try
          Some (input_line chan)
          with
          End_of_file -> None in
          match sl with
          None -> List.rev res
          | Some l -> input_lines_helper (l :: res) in
          aux []

          --
          Rémi Vanicat
          vanicat@labri.u-bordeaux.fr
          http://dept-info.labri.u-bordeaux.fr/~vanicat
        Your message has been successfully submitted and would be delivered to recipients shortly.