POV-Ray : Newsgroups : povray.off-topic : how to scheme a cat up? : Re: how to scheme a cat up? Server Time
5 Sep 2024 15:25:09 EDT (-0400)
  Re: how to scheme a cat up?  
From: Daniel Bastos
Date: 20 Aug 2009 05:45:50
Message: <4a8d1b4e$1@news.povray.org>
In article <4a8c516d$1@news.povray.org>,
nemesis wrote:

> PLT is amazing, an excellent choice.  I hope you also knows how to
> use the combination keys for easily navigating/editing Lisp code:
> alt+up/down to go up/down a parenthetical level, alt+left/right to
> go to the next beginning or end, combine with shift to select and
> copy/paste at will.  Turns editing Lisp code a breeze and almost as
> good as with emacs.

Hm. In DrScheme? I'm not using it. I only use mzscheme and I write the
code in anything. Usually on emacs.

> In recent years, many excellent performant and compliant with the
> latest language standard, R6RS, showed up: ikarus and ypsilon come
> to mind.

R6RS is sorta like POSIX or more sorta like ANSI C?

>> Can you give me a word on portability?
>
> Sure:  many Scheme implementations are pretty portable. :)

The implementation itself? I meant the scheme code itself. So that if
I move from mz to $y scheme, then my code would still run. If there is
a document saying which functions are likely to be common among
certain implementations, then that could be my favorite subset of
documentation. (I'll be reading the r6rs web document after posting
this.)

>> On UNIX, I use POSIX as a reference, even though I
>
> Forget about low-level system access.  Leave that to C.

I meant it as an analogy. When I'm working directly with UNIX, then
POSIX is a good document. Not to be followed, I say, but to be
noticed.

>>> #!r6rs
>>> (import (rnrs base)(rnrs io simple)(rnrs programs))
>>>
>>> ; simple and straightforward standard R6RS scheme solution
>>> (define (cat files)
>>>   (for-each
>>>     (lambda (file)
>>>       (call-with-input-file file
>>>         (lambda (port)
>>>           ; no simple line-oriented IO in standard R6RS
>>>           ; so you either write one or loop char-by-char
>>>           (let go ((c (read-char port)))
>>>             (if (not (eof-object? c))
>>>               (begin
>>>                 (write-char c)
>>>                 (go (read-char port))))))))
>>>     files))
>>>
>>> (cat (cdr (command-line)))
>> 
>> I've kinda been able to read this; which is cool. But I don't really
>> get the purpose of ``go'' here.
>
> let creates lexical scopes.  It's actually just a macro.

So a lexical scope is a scope from the point of view of a macro? To a
C programmer, the analogy would be scope of variables defined by a cpp
macro?

> (let ((x 2)) (+ 1 x))
>
> turns into:
>
> ((lambda (x) (+ 1 x)) 2)

That's instructive. There's probably a macro to expand macros? That be
even more instructive.

> (let label (bindings ...) ...) is called a named let.  It turns the let 
> body into a full fleged local function of name label.

Interesting. So let can be used to also group statements, right? For
example, (let () (+ 1 1) (* 3 4)). But what I have in mind is i/o,
which is where a sequence of isolated statements makes more sense.

(let () (display "this ") 
        (display "could help ") 
	(display "an imperative typa guy\n"))

> It's most immediate use is to create loops out of functions calls, since 
> as you know, there's no such builtin looping facility in functional 
> languages.

Makes sense. When people are functional, they don't run in circles.

> I could have defined an inner or outer function named go or whatever, 
> but simply used let.  The normal let bindings turn into parameters with 
> initial values for the function.  Thus,
>
> (go (read-char port))
>
> calls the function again.  Beware that many people enjoy creating such 
> loops like (let loop (...) ...) but the label may be any of your choice. 

So (go) was a function, with an initial value in c. Cool. Now it makes
perfect sense. Load another c, and continue.

>   Also, the body may sport several exits as stop condition.

I'm yet to see how to break out of loops. I mean, recursion. That is,
I'm yet to find out how to return earlier. That appears to be simply
to protect the region of code that would run in case whe need not
return earlier. So if eof shows up, then the usual block of code does
not run, and the last statement of the function runs which is its
return statement. IOW, we never break out; we simply get faster to the
end of the function. True?

>> Hey, looking at this very old cat, I can see that Warp is going to say
>> that our cats aren't cats after all; we don't read the stdin. And
>> he'll be right.
>
> Bah, just a matter of reorganizing a bit adding a short if before for-each:
>
> (define (cat files)
>    (define (process port)
>      ; no simple line-oriented IO in standard R6RS
>      ; so you either write one or loop char-by-char
>      (let go ((c (read-char port)))
>        (if (not (eof-object? c))
>            (begin
>              (write-char c)
>              (go (read-char port))))))
>    (if (null? files) (process (current-input-port))
>        (for-each
>         (lambda (file) (call-with-input-file file process))
>         files)))

I don't think that's going to satisfy Warp, even though I just met
her, or him. Because, although you appear to listen to the stdin if no
files are given, a real cat would also pay attention to a file named
-. :-) 

Changing subject. It is ugly to assign functionality to file names,
but it is much more likely, I say, that we will eventually need to
read a couple files plus the stdin, than to name a file as -.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.