[racket] fun with ports and (system ..) calls

From: Vlad Kozin (vladilen.kozin at gmail.com)
Date: Wed Oct 16 12:35:24 EDT 2013

Hi. 

I want to read whatever a process writes to (current-output-port). There has to be a simple pattern for that which unfortunately I've failed to come up with.

Here's a process: (system (format "find . ~a ~a" "-name \"*.c\"" "-print"))

assuming I have a number of .c files I expect "find" to write corresponding lines to (current-output-port). I want to collect them in a list. Here's a solution I thought would work:
------------------------------------
(define-values (in out) (make-pipe))
(parameterize ((current-output-port out))
  (system (format "find . ~a ~a" "-name \"*.c\"" "-print"))
  (for/list ((line (in-lines in)))
    line))

It doesn't. It blocks expecting input. Let's simplify the example:
------------------------------------
(define-values (in out) (make-pipe))
(displayln "hello" out)
(displayln "world" out)
(for/list ((line (in-lines in)))
  line)

Blocks again. Am I not getting EOF here?

Here's a contrived and backwards solution that works:
---------
(for/list 
    ((line 
      (in-lines (open-input-string 
                 (with-output-to-string 
                  (lambda () (system (format "find . ~a ~a" "-name \"*.c\"" "-print"))))))))
  line)

Clearly, I don't understand ports. Help?

PS: placing a system call is an overkill for this particular task. Racket is perfectly capable of finding all .c files: 
---------------------------------------------------------------
(for/list ((path (in-list (map path->string (directory-list))))
                #:when (regexp-match #rx".*\\.c$" path))
       path)
---
Vlad Kozin <vladilen.kozin at gmail.com>





Posted on the users mailing list.