If Guile is not the best Scheme for this usage, then which one should I be looking at? I'm basically looking for a Guile equivalent of awk '{print $N}'
. If Scheme can't do this, then I'd like to know why not.
Asked
Active
Viewed 750 times
0

takatakatek
- 103
- 2
-
You could do this in pure Scheme, but it would probably be obnoxious because there isn’t much of a standard library. Here’s a Racket one-liner that does it, though: `(for ([l (in-lines)]) (displayln (second (string-split l))))`. – Alexis King Sep 07 '17 at 23:19
-
@AlexisKing I'm willing to accept this as an answer, but it would be great to see alternatives in other dialects. That is less obnoxious than I might have imagined. It's certainly preferable to the equivalent C code presented by Brian Kernighan. Is the *for* macro available in other Schemes? What is *in-lines*? – takatakatek Sep 08 '17 at 02:41
-
No, [`for`](http://docs.racket-lang.org/reference/for.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for%29%29) in its precise form is a Racket-specific feature, as is [`in-lines`](http://docs.racket-lang.org/reference/sequences.html#%28def._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._in-lines%29%29). The latter is a constructor for a Racket “sequence” that iterates through the lines in a port. If no port is given, it defaults to `(current-input-port)`, aka stdin. – Alexis King Sep 08 '17 at 03:34
-
@AlexisKing I see. Would you recommend Racket over other Schemes if I intend to frequently do text processing, among other tasks? – takatakatek Sep 08 '17 at 13:23
2 Answers
0
At my blog I have an essay giving a set of functions that make it easy to handle delimited text files.

user448810
- 17,381
- 4
- 34
- 59
0
Guile changed its I/O a bit between 2.0 and 2.2, so this uses r6rs I/O which (hopefully) works the same in both, but I haven't tested with 2.2.
This can be optimized further.
#!/usr/bin/guile \
-e start -s
!#
(use-modules (rnrs io ports))
;;; Reads one line from current-input-port and prints the field indicated by
;;; field-num. If the line does not have enough fields, it prints a newline.
;;; Returns the field, an empty string, or #f if end of file is reached.
(define (get-field field-num)
(let ((line (get-line (current-input-port))))
(if (eof-object? line)
#f
(let ((fields (string-tokenize line)))
(if (< field-num (length fields))
(let ((field (list-ref fields field-num)))
(put-string (current-output-port)
(string-append field "\n"))
field)
(and (put-string (current-output-port) "\n")
""))))))
;;; Repeat get-field until until end of file is reached
(define (get-all-fields field-num)
(if (get-field field-num)
(get-all-fields field-num)
#f))
(define (start args)
(if (and (> (length args) 1)
(integer? (string->number (list-ref args 1))))
(get-all-fields (1- (string->number (list-ref args 1))))
(display (string-join
`("Usage:" ,(list-ref args 0) "<field-number>\n")
" "))))

Jeff Spaulding
- 223
- 3
- 8
-
This seems to work, and should prove helpful. Why the line continuation in the shebang line? Thanks. – takatakatek Sep 19 '17 at 11:15
-
That's what it recommends in the Guile manual. Apparently, POSIX is silent about shebang lines, and you get mixed results if you have more than one thing after the command. If I understand it correctly, using a continuation when there's more than one argument is "more portable" in practice. – Jeff Spaulding Sep 19 '17 at 15:36