3

I understand that Scheme uses ports to perform Input and Output. While trying to learn how to get console input and output, I have come across MIT-Scheme's console-i/o-port variable.

But, the guile interpreter says it is an Unbound Variable. I would like to know how we can use ports to get input from and output to the console (Terminal in Unix) in a Guile Scheme Script. I am still a rookie in Scheme and Linux, a clear step-by-step is appreciated.

Also, how does (display <object>) work? Does it use ports inherently or is there another way.

P.S. If there is another way without using ports please let me know how to use that too.

Tarun Maganti
  • 3,076
  • 2
  • 35
  • 64

2 Answers2

3

If you want to read and write SExps, in guile you have (read), (write), (display) etc., if you want to read characters only use (read-char) and (write-char) -- they all use the input/output ports resp. you picked, by default they are stdin and stdout. Everything is rather straightforward (https://www.gnu.org/software/guile/manual/html_node/Input-and-Output.html#Input-and-Output).

You might also be interested in guile-ncurses (https://www.gnu.org/software/guile-ncurses/).

Of some more goodies check out pretty-print module from ice-9 (on very long sexps it's slow but outputs them really nicely formatted, great for e.g. code generation):

  (use-modules (ice-9 pretty-print))
  (pretty-print `(super cool stuff (+ 2 3) => ,(+ 2 3)))

And if you need your own parser, check out the lalr module (system base lalr).

edit a small example which reads a number, multiplies by itself and prints out the result:

#!/usr/bin/guile -s
!#

(let ((x (read)))
  (display (* x x))
  (newline))

(remember to chmod +x this script).

edit changed the expression to let form as Chris suggested, indeed the fewer parentheses the better

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
dercz
  • 962
  • 6
  • 9
  • Could you give me a small script for reading from the terminal and squaring it and printing. I wanted to know if there is an alternative for console-i/o-port in MIT-Scheme? – Tarun Maganti Jul 15 '16 at 16:57
  • @TarunMaganti there you go, does this help you? perhaps you'd like a more elaborate one, but this one works just fine with stdin/out (I was using guile ang gambit a lot piped with other things). – dercz Jul 15 '16 at 18:36
  • 1
    BTW, `((lambda (x) (* x x)) (read))` is more idiomatically written as `(let ((x (read))) (* x x))`.. – C. K. Young Jul 16 '16 at 05:41
  • @ChrisJester-Young thank you, it looks better now :) – dercz Jul 16 '16 at 12:29
2

In guile you have 2 functions: current-input-port and current-output-port (the docs)

to read and put text into string (if you don't want to read s-expressions) you can use this function:

(define (read-port port)
    (let iter ((result '()) (chr (read-char port)))
        (if (eof-object? chr)
            (list->string result)
            (iter (append result (list chr)) (read-char port)))))

reading from stdin will be:

(read-port (current-input-port))

to write to stdout you can use display it also accept second argument which is port relevant docs

jcubic
  • 61,973
  • 54
  • 229
  • 402